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
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 [2024/04/22 12:38] (current) – [Cert manager] 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.+  --create-namespace \ 
-  jetstack/cert-manager+  --set installCRDs=true \ 
 +  --version v1.14.
 +  --set prometheus.enabled=false
 </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 310:
     # 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 319:
         ingress:         ingress:
           class: nginx           class: nginx
 +EOF
 </code> </code>
 Смотрим на его состояние: Смотрим на его состояние:
Line 227: Line 334:
 ==== Апгрейдим 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 372:
 В результате, 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 386:
     # 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 395:
         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