Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revisionBoth sides next revision
linux_faq:kubernetes_using_single_node_as_master_and_worker [2020/07/09 15:01] – [Ingress, Cert-Manager и сертификаты Let's Encrypt] adminlinux_faq:kubernetes_using_single_node_as_master_and_worker [2022/11/09 09:42] – [Установка сервера метрик kubernetes] admin
Line 8: Line 8:
      
   echo 'deb http://apt.kubernetes.io/ kubernetes-xenial main' | sudo tee /etc/apt/sources.list.d/kubernetes.list   echo 'deb http://apt.kubernetes.io/ kubernetes-xenial main' | sudo tee /etc/apt/sources.list.d/kubernetes.list
-  curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add +  ######### curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add 
-  +  gpg_key_url="https://packages.cloud.google.com/apt/doc/apt-key.gpg" 
 +  gpg_keyring_path="/etc/apt/trusted.gpg.d/kubernetes.gpg" 
 +  curl -fsSL "${gpg_key_url}" | gpg --dearmor | sudo tee -a ${gpg_keyring_path} 
 + 
 +  cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf 
 +  overlay 
 +  br_netfilter 
 +  EOF 
 + 
 +  sudo modprobe overlay 
 +  sudo modprobe br_netfilter 
 + 
 +  # Setup required sysctl params, these persist across reboots. 
 +  cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf 
 +  net.bridge.bridge-nf-call-iptables  = 1 
 +  net.ipv4.ip_forward                 = 1 
 +  net.bridge.bridge-nf-call-ip6tables = 1 
 +  EOF 
 + 
 +  # Apply sysctl params without reboot 
 +  sudo sysctl --system 
   sudo apt-get update   sudo apt-get update
-  sudo apt-get install -y docker.io kubeadm kubelet+  #sudo apt-get install -y docker.io kubeadm kubelet 
 +  sudo apt-get install -y containerd kubeadm kubelet
      
-  # Setup Docker daemon. +  sudo mkdir -p /etc/containerd 
-  cat > /etc/docker/daemon.json <<EOF +  containerd config default | sudo tee /etc/containerd/config.toml 
-  +    
-    "exec-opts": ["native.cgroupdriver=systemd"]+  cat << EOF | sudo tee /etc/systemd/system/kubelet.service.d/12-after-docker.conf 
-    "log-driver": "json-file", +  [Unit
-    "log-opts":+  After=containerd.service
-      "max-size": "100m" +
-    }, +
-    "storage-driver": "overlay2" +
-  }+
   EOF   EOF
      
-  sudo mkdir -/etc/systemd/system/docker.service.d+  sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true//etc/containerd/config.toml 
 +  sudo service containerd restart
      
-  # Enable services and restart docker. 
-  sudo systemctl daemon-reload 
-  sudo systemctl enable docker 
-  sudo systemctl restart docker 
-  sudo systemctl enable kubelet.service 
      
-  sudo usermod -a -G docker $USER 
-   
-  # To ensure that kubelet starts only after docker: 
-  cat << EOF | sudo tee /etc/systemd/system/kubelet.service.d/12-after-docker.conf 
-  [Unit] 
-  After=docker.service 
-  EOF 
-    
   # Kubernetes Cluster Init    # Kubernetes Cluster Init 
-  sudo kubeadm init --pod-network-cidr=10.244.0.0/16+  sudo kubeadm init --cri-socket /run/containerd/containerd.sock --pod-network-cidr=10.244.0.0/16
      
   mkdir -p $HOME/.kube   mkdir -p $HOME/.kube
Line 56: Line 62:
   kubectl taint nodes --all node-role.kubernetes.io/master-   kubectl taint nodes --all node-role.kubernetes.io/master-
  
 +====== Настройка манифестов компонентво кубера на слабых маишинках ======
 +Я запускаю свой кластер в контейнере на сервере Proxmox,  на довольно слабой машинке, поэтому при старте компоненты кубера начинают отвечать очень нескоро. \\
 +Чтобы немного облегчить им жизнь и сделать поведение компонентов k8s более предсказуемым нужно увеличить таймауты **livenessProbe**, **readinessProbe** и **startupProbe** - в результате у сервисов будет больше времени чтобы прийти в норму при запуске/перезапуске и кластер будет вести себя стабильнее, особенно если в нем много полезной нагрузки. \\
 +Для этого - редактируем манифесты в директории **/etc/kubernetes/manifests/** и подкручиваем там значения до, например, таких: 
 +<code>
 +    livenessProbe:
 +      failureThreshold: 300
 +      initialDelaySeconds: 60
 +      periodSeconds: 15
 +      timeoutSeconds: 30
 +    readinessProbe:
 +      failureThreshold: 300
 +      periodSeconds: 15
 +      timeoutSeconds: 30
 +    startupProbe:
 +      failureThreshold: 300
 +      initialDelaySeconds: 60
 +      periodSeconds: 15
 +      timeoutSeconds: 30
 +</code>
 +И перезапускаем **kubelet**:
 +  sudo service kubelet restart
 ====== Изменение редактора kubectl edit ====== ====== Изменение редактора kubectl edit ======
   sudo awk -v line='export KUBE_EDITOR="/bin/nano"' 'FNR==NR && line==$0{f=1; exit} END{if (!f) print line >> FILENAME}' /etc/bash.bashrc   sudo awk -v line='export KUBE_EDITOR="/bin/nano"' 'FNR==NR && line==$0{f=1; exit} END{if (!f) print line >> FILENAME}' /etc/bash.bashrc
Line 99: Line 127:
 ===== Установка сервера метрик kubernetes ===== ===== Установка сервера метрик kubernetes =====
 https://github.com/kubernetes-sigs/metrics-server https://github.com/kubernetes-sigs/metrics-server
-  kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.3.6/components.yaml+  kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
 В результате в неймспейсе **kube-system** появится **deployment** **metrics-server** и развернется **pod** **metrics-server-...**.\\ В результате в неймспейсе **kube-system** появится **deployment** **metrics-server** и развернется **pod** **metrics-server-...**.\\
 В нашем кластере отключен **ssl**, но он включен по-дефолту в **metrics-server**. Поэтому выполняем: В нашем кластере отключен **ssl**, но он включен по-дефолту в **metrics-server**. Поэтому выполняем:
Line 105: Line 133:
 и в **spec.template.spec.containers.args** добавляем: и в **spec.template.spec.containers.args** добавляем:
 <code>  - --kubelet-insecure-tls</code> <code>  - --kubelet-insecure-tls</code>
 +Без этого параметра metrics-server не запустится, а в логах будет примерно такое:
 +<code>[unable to fully scrape metrics from node kub-worker01: unable to fetch metrics from node kub-sbl-apps-dev-worker01: Get "https://192.168.44.11:10250/stats/summary?only_cpu_and_memory=true": x509: cannot validate certificate for 192.168.44.11 because it doesn't contain any IP SANs </code>
 Все. Через некоторое время команды **kubectl top** начнут выдавать осмысленную информацию. \\ Все. Через некоторое время команды **kubectl top** начнут выдавать осмысленную информацию. \\
 Если этого не происходит, а в логах  Если этого не происходит, а в логах 
Line 114: Line 144:
 С третьей версией **Helm** ничего в кластер ставить не нужно. Для использования достаточно бинарника и сконфигурированного **context** для доступа к кластеру. С третьей версией **Helm** ничего в кластер ставить не нужно. Для использования достаточно бинарника и сконфигурированного **context** для доступа к кластеру.
  
 +====== Обновление kubernetes ======
 +смотрим какие версии **kubeadm** нам доступны
 +  sudo apt-get update
 +  apt-cache madison kubeadm
 +Разрешаем обновление **kubernetes-cni** и **kubeadm**:
 +  sudo apt-mark unhold kubernetes-cni kubeadm
 +Ставим нужную версию **kubeadm**: 
 +  sudo apt-get install kubeadm=1.20.9-00
 +Проверяем возможность апгрейда:
 +  sudo kubeadm upgrade plan
 +Если у нас хост с **containerd** (без **docker**), то нужно проверить, что параметр **kubeadm.alpha.kubernetes.io/cri-socket** указывает не на **docker-shim**, а на сокет **containerd**. У меня так:
 +  kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock
 +если этого не сделать - будет ошибка, поскольку **kubeadm** возьмет эту запись и будет пытаться работать через docker, которого нет:
 +  error execution phase preflight: docker is required for container runtime: exec: "docker": executable file not found in $PATH
 +Обновляем:
 +  sudo kubeadm upgrade apply v1.20.9
 +Разрешаем обновление **kubelet** и **kubectl**
 +  sudo apt-mark unhold kubelet kubectl
 +И обновляем их до нужной версии:
 +  sudo apt-get install -y kubelet=1.20.9-00 kubectl=1.20.9-00
 +Морозим обратно версии пакетов:
 +  sudo apt-mark hold kube*
 +Апгрейдим всю систему:
 +  sudo apt-get update && sudo apt-get upgrade
 ====== Доступ к подам снаружи ====== ====== Доступ к подам снаружи ======
 Для доступа к сервисам, которые предоставляют поды, нужно установить и настроить: Для доступа к сервисам, которые предоставляют поды, нужно установить и настроить:
Line 122: Line 176:
 https://habr.com/ru/company/southbridge/blog/443110/ \\ https://habr.com/ru/company/southbridge/blog/443110/ \\
 https://metallb.universe.tf/installation/ \\ https://metallb.universe.tf/installation/ \\
-  kubectl create ns metallb-system +  helm repo add metallb https://metallb.github.io/metallb 
-  helm install --name metallb stable/metallb --namespace metallb-system +  helm repo update 
-При установке с помощью **helm** конфигурация хранится в **ConfigMap** с именем **metallb-config**, который лежит в том же неймспейсе куда установлен **metallb** (в данном случае - **metallb-system**). +  kubectl create ns metallb-system  
-<code>apiVersion: v1 +  helm upgrade --install -metallb-system metallb metallb/metallb 
-kind: ConfigMap +    --set configInline.address-pools[0].name="default" \ 
-metadata: +    --set configInline.address-pools[0].protocol="layer2" \ 
-  namespace: metallb-system +    --set configInline.address-pools[0].addresses[0]="192.168.77.160-192.168.77.189"
-  name: metallb-config +
-data: +
-  config: | +
-    address-pools: +
-    - name: default +
-      protocol: layer2 +
-      addresses+
-      - 192.168.77.160-192.168.77.189 +
-</code>+
 ==== Апгрейдим metallb ==== ==== Апгрейдим metallb ====
   helm repo update   helm repo update
-  helm upgrade metallb stable/metallb --namespace metallb-system +  helm upgrade -n metallb-system metallb metallb/metallb --reuse-values
 ===== Ingress-controller ===== ===== Ingress-controller =====
 https://docs.cert-manager.io/en/latest/tutorials/acme/quick-start/# \\ https://docs.cert-manager.io/en/latest/tutorials/acme/quick-start/# \\
 Либо тоже самое можно сделать с помощью helm-чарта: Либо тоже самое можно сделать с помощью helm-чарта:
   kubectl create ns ingress   kubectl create ns ingress
 +  helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
 +  helm repo update
 +
   #helm install stable/nginx-ingress --name http-https --namespace ingress   #helm install stable/nginx-ingress --name http-https --namespace ingress
-  helm install stable/nginx-ingress --name http-https --namespace ingress --set controller.service.type=LoadBalancer,controller.service.externalTrafficPolicy=Local,controller.service.loadBalancerIP=192.168.77.160 \+  helm upgrade --install nginx -n ingress ingress-nginx/ingress-nginx \ 
 +  --set controller.service.type=LoadBalancer,controller.service.externalTrafficPolicy=Cluster,controller.service.loadBalancerIP=192.168.77.160 \
   --set controller.addHeaders."X-XSS-Protection"="1\;mode=block" \   --set controller.addHeaders."X-XSS-Protection"="1\;mode=block" \
   --set controller.addHeaders."Content-Security-Policy"="default-src 'self'; \   --set controller.addHeaders."Content-Security-Policy"="default-src 'self'; \
Line 158: Line 206:
   --set controller.addHeaders."X-Content-Type-Options"="nosniff"   --set controller.addHeaders."X-Content-Type-Options"="nosniff"
 Ну или без драконовских запретов (заголовки **Content-Security-Policy** влияют на все ресурсы за этим **ingress-controller** и что-то может просто не заработать): Ну или без драконовских запретов (заголовки **Content-Security-Policy** влияют на все ресурсы за этим **ingress-controller** и что-то может просто не заработать):
-  helm upgrade http-https stable/nginx-ingress --set controller.service.type=LoadBalancer \ +  helm upgrade --install nginx -ingress ingress-nginx/ingress-nginx \ 
-  --set controller.service.externalTrafficPolicy=Local \+  --set controller.service.type=LoadBalancer \ 
 +  --set controller.service.externalTrafficPolicy=Cluster \
   --set controller.service.loadBalancerIP=192.168.77.160 \   --set controller.service.loadBalancerIP=192.168.77.160 \
   --set controller.addHeaders."X-XSS-Protection"="1\;mode=block" \   --set controller.addHeaders."X-XSS-Protection"="1\;mode=block" \
Line 166: Line 215:
   --set controller.addHeaders."X-Content-Type-Options"="nosniff"   --set controller.addHeaders."X-Content-Type-Options"="nosniff"
  
-В результате - в неймспейсе **ingress** появится сервис **http-https-nginx-ingress-controller**, у которого будет тип **LoadBalancer** и который получит указанный IP-адрес в локальной сети из диапазона, сконфигурированного для **metallb**. \\+В результате - в неймспейсе **ingress** появится сервис **nginx-ingress-nginx-controller**, у которого будет тип **LoadBalancer** и который получит указанный IP-адрес в локальной сети из диапазона, сконфигурированного для **metallb**. \\
 Теперь можно создавать **ingress**'ы, которые будут смотреть на сервисы внутри кластера и предоставлять к ним доступ. Пользователи будут посылать запросы на **ingress-controller**, а он, в свою очередь, - пересылать их на **ingress**'ы. Теперь можно создавать **ingress**'ы, которые будут смотреть на сервисы внутри кластера и предоставлять к ним доступ. Пользователи будут посылать запросы на **ingress-controller**, а он, в свою очередь, - пересылать их на **ingress**'ы.
 +==== Мониторинг nginx ingess ====
 +В кластере нужно развернуть **CRD** и оператор **prometheus**: https://wiki.autosys.tk/devops/prometheus_federation#%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%B0_prometheus \\
 +\\
 +**nginx-ingress-monitoring-values.yaml**
 +<code>
 +controller:
 +  metrics:
 +    port: 10254
 +    enabled: true
 +    service:
 +      annotations:
 +        prometheus.io/scrape: "true"
 +        prometheus.io/port: "10254"
 +      servicePort: 10254
 +      type: ClusterIP
  
-===== Cert manager ===== +    serviceMonitor: 
-https://docs.cert-manager.io/en/latest/tutorials/acme/quick-start/ +      enabledtrue 
-https://docs.cert-manager.io/en/latest/getting-started/install/kubernetes.html#installing-with-helm \\ +      additionalLabels: 
-Устанавливаем+        jobLabel: nginx-ingress 
-<code># Install the CustomResourceDefinition resources separately +      namespace"ingress" 
-kubectl apply --validate=false -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.11/deploy/manifests/00-crds.yaml+      namespaceSelector: 
 +        matchNames: 
 +          ingress 
 +      scrapeInterval30s
  
-# Create the namespace for cert-manager +    prometheusRule: 
-kubectl create namespace cert-manager+      enabled: true 
 +      namespace: ingress 
 +      rules: 
 +        - alert: NGINXConfigFailed 
 +          expr: count(nginx_ingress_controller_config_last_reload_successful == 0) > 0 
 +          for: 1s 
 +          labels: 
 +            severity: critical 
 +          annotations: 
 +            description: bad ingress config nginx config test failed 
 +            summary: uninstall the latest ingress changes to allow config reloads to resume 
 +        alert: NGINXCertificateExpiry 
 +          expr: (avg(nginx_ingress_controller_ssl_expire_time_seconds) by (host) - time()) < 604800 
 +          for: 1s 
 +          labels: 
 +            severity: critical 
 +          annotations: 
 +            description: ssl certificate(s) will expire in less then a week 
 +            summary: renew expiring certificates to avoid downtime 
 +        - alert: NGINXTooMany500s 
 +          expr: 100 * ( sum( nginx_ingress_controller_requests{status=~"5.+"} ) / sum(nginx_ingress_controller_requests) ) > 5 
 +          for: 1m 
 +          labels: 
 +            severity: warning 
 +          annotations: 
 +            description: Too many 5XXs 
 +            summary: More than 5% of all requests returned 5XX, this requires your attention 
 +        - alert: NGINXTooMany400s 
 +          expr: 100 * ( sum( nginx_ingress_controller_requests{status=~"4.+"} ) / sum(nginx_ingress_controller_requests) ) > 5 
 +          for: 1m 
 +          labels: 
 +            severity: warning 
 +          annotations: 
 +            description: Too many 4XXs 
 +            summary: More than 5% of all requests returned 4XX, this requires your attention 
 +</code>
  
-# Add the Jetstack Helm repository+  helm upgrade --reuse-values -n ingress nginx ingress-nginx/ingress-nginx -f ./nginx-ingress-monitoring-values.yaml 
 +===== Cert manager ===== 
 +https://cert-manager.io/docs/installation/helm/ \\ 
 +Устанавливаем: 
 +<code>kubectl create namespace cert-manager
 helm repo add jetstack https://charts.jetstack.io helm repo add jetstack https://charts.jetstack.io
- 
-# Update your local Helm chart repository cache 
 helm repo update helm repo update
  
-# Install the cert-manager Helm chart +helm upgrade --install \ 
-helm install \ +  cert-manager jetstack/cert-manager \
-  --name cert-manager \+
   --namespace cert-manager \   --namespace cert-manager \
-  --version v0.11.0 +  --create-namespace 
-  jetstack/cert-manager+  --set installCRDs=true \ 
 +  --version v1.8.2
 </code> </code>
 https://docs.cert-manager.io/en/latest/tasks/issuers/index.html \\ https://docs.cert-manager.io/en/latest/tasks/issuers/index.html \\
 Создаем издателя **Let's Encrypt** (ACME Issuer): Создаем издателя **Let's Encrypt** (ACME Issuer):
-<code>apiVersion: cert-manager.io/v1alpha2+<code>kubectl apply -f - << EOF 
 +apiVersion: cert-manager.io/v1
 kind: ClusterIssuer kind: ClusterIssuer
 metadata: metadata:
Line 204: Line 309:
     # certificates, and issues related to your account.     # certificates, and issues related to your account.
     email: mike@autosys.tk     email: mike@autosys.tk
-    server: https://acme-staging-v02.api.letsencrypt.org/directory+    server: https://acme-v02.api.letsencrypt.org/directory
     privateKeySecretRef:     privateKeySecretRef:
       # Secret resource used to store the account's private key.       # Secret resource used to store the account's private key.
Line 213: Line 318:
         ingress:         ingress:
           class: nginx           class: nginx
 +EOF
 </code> </code>
 Смотрим на его состояние: Смотрим на его состояние:
Line 227: Line 333:
 ==== Апгрейдим cert-manager ==== ==== Апгрейдим cert-manager ====
   helm repo update   helm repo update
-  helm upgrade --namespace cert-manager cert-manager jetstack/cert-manager+  helm upgrade --namespace cert-manager cert-manager jetstack/cert-manager --reuse-values
 ===== Ingress, Cert-Manager и сертификаты Let's Encrypt ===== ===== Ingress, Cert-Manager и сертификаты Let's Encrypt =====
 <del>https://docs.cert-manager.io/en/latest/getting-started/install/kubernetes.html</del>\\ <del>https://docs.cert-manager.io/en/latest/getting-started/install/kubernetes.html</del>\\
 <del>https://docs.bitnami.com/kubernetes/how-to/secure-kubernetes-services-with-ingress-tls-letsencrypt/#step-3-configure-tls-with-let-s-encrypt-certificates-and-cert-manager</del>\\ <del>https://docs.bitnami.com/kubernetes/how-to/secure-kubernetes-services-with-ingress-tls-letsencrypt/#step-3-configure-tls-with-let-s-encrypt-certificates-and-cert-manager</del>\\
 https://docs.cert-manager.io/en/latest/tutorials/acme/quick-start/#\\ https://docs.cert-manager.io/en/latest/tutorials/acme/quick-start/#\\
 +https://cert-manager.io/docs/installation/helm/ \\
 Итак, у нас установлен **MetalLB**, **Ingress Controller** и **CertManager**. \\ Итак, у нас установлен **MetalLB**, **Ingress Controller** и **CertManager**. \\
 В результате, сервис **Ingress Controller** должен получить адрес в локальной (или нелокальной сети) из диапазона, прописанного в конфигурации **MetalLB**: В результате, сервис **Ingress Controller** должен получить адрес в локальной (или нелокальной сети) из диапазона, прописанного в конфигурации **MetalLB**:
Line 264: Line 371:
 В результате, HTTP-запросы на **IP**-адрес **Ingress**-контроллера будут перенаправлены на сервис web-морды AWX. \\ В результате, HTTP-запросы на **IP**-адрес **Ingress**-контроллера будут перенаправлены на сервис web-морды AWX. \\
 \\ \\
-Теперь нужно сконфигурировать **ACME Issuer** - это сущность, которая будет запрашивать сертификаты по протоколу **ACME** у серверов **Let's Encrypt**: +Теперь нужно сконфигурировать **ACME Issuer** - это сущность, которая будет запрашивать сертификаты по протоколу **ACME** у серверов **Let's Encrypt**: \\ 
-<code>apiVersion: cert-manager.io/v1alpha2+https://cert-manager.io/docs/configuration/acme/ 
 +<code> 
 +kubectl apply -f - << EOF 
 +apiVersion: cert-manager.io/v1
 kind: ClusterIssuer kind: ClusterIssuer
 metadata: metadata:
   name: letsencrypt   name: letsencrypt
-  namespace: cert-manager 
 spec: spec:
   acme:   acme:
Line 276: Line 385:
     # certificates, and issues related to your account.     # certificates, and issues related to your account.
     email: mike@autosys.tk     email: mike@autosys.tk
-    server: https://acme-v02.api.letsencrypt.org/directory+    server: https://acme-staging-v02.api.letsencrypt.org/directory
     privateKeySecretRef:     privateKeySecretRef:
-      # Secret resource used to store the account's private key. +      # Secret resource that will be used to store the account's private key. 
-      name: letsencrypt-cert-issuer-account-key+      name: letsencrypt-issuer-account-key
     # Add a single challenge solver, HTTP01 using nginx     # Add a single challenge solver, HTTP01 using nginx
     solvers:     solvers:
Line 285: Line 394:
         ingress:         ingress:
           class: nginx           class: nginx
 +EOF
 </code> </code>
 После того, как создан **Issuer** (в данном случае - **ClusterIssuer** с именем **letsencrypt**) можно добавить в манифест ингресса информацию о нем. Редактируем ресурс **Ingress** и приводим секцию **annotations** к виду: После того, как создан **Issuer** (в данном случае - **ClusterIssuer** с именем **letsencrypt**) можно добавить в манифест ингресса информацию о нем. Редактируем ресурс **Ingress** и приводим секцию **annotations** к виду:
  • linux_faq/kubernetes_using_single_node_as_master_and_worker.txt
  • Last modified: 2024/04/22 12:38
  • by admin