Невозможно развернуть обновленное развертывание из-за nodeAffinity и podAffinity

#kubernetes #deployment #continuous-deployment #azure-aks

#kubernetes #развертывание #непрерывное развертывание #azure-aks

Вопрос:

Итак, у меня есть 4 узла. 1 — System, 1 — Dev, 1 — Qa и 1 — UAT.

Моя привязка заключается в следующем:

 apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth
  namespace: dev
  labels:
    app: auth
    environment: dev
    app-role: api
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: auth
  template:
    metadata:
      labels:
        app: auth
        environment: dev
        app-role: api
        tier: backend
      annotations:
        build: _{Tag}_
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - auth
            topologyKey: kubernetes.io/hostname
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: environment
                operator: In
                values:
                - dev
      containers:
        - name: companyauth
          image: company.azurecr.io/auth:_{Tag}_
          imagePullPolicy: Always
          env:
            - name: ConnectionStrings__DevAuth
              value: dev
          ports:
            - containerPort: 80
      imagePullSecrets:
        - name: ips
 

Я намерен убедиться, что в моем производственном кластере, который имеет 3 узла в 3 разных зонах доступности. Что все модули будут запланированы на другом узле / зоне доступности. Однако, похоже, что если у меня уже есть модули, запланированные на узле, то при выполнении развертывания они не будут перезаписывать уже существующие модули.

Доступно 0/4 узлов: 1 узел (ы) не соответствует привязке / анти-привязке pod, 3 узла (ов) не соответствуют селектору узлов.

Однако, если я удалю podAffinity, он будет работать нормально и перезапишет текущий узел новым модулем из развертывания. Каков правильный способ сделать это, чтобы гарантировать, что мое развертывание в моем производственном кластере всегда будет иметь модуль, запланированный на другом узле в другой зоне доступности, а также иметь возможность обновлять существующие узлы?

Комментарии:

1. Не могли бы вы поделиться своими манифестами развертывания / Pod и конфигурацией узла (метки и т. Д.)? Опубликованная привязка предназначена для Pod, Deployment, что-нибудь еще? Похоже, что у вашего модуля нет метки with app: auth , и ни у одного из ваших узлов нет environment: dev метки. Пожалуйста, предоставьте вышеуказанную информацию для дальнейшего изучения.

2. @PjoterS Я обновил до полного файла развертывания. Первое развертывание работает, но последующие развертывания не работают, если я не удалю привязку к pod.

Ответ №1:

Ваша цель может быть достигнута с помощью только PodAntiAffinity.

Я протестировал это с моим GKE тестовым кластером, но он должен работать аналогично Azure .

Текущая проблема

В вашей текущей настройке вы установили podAntiAffinity with nodeAffinity .

Pod anti-affinity может помешать планировщику найти новый модуль на том же узле, что и модули с теми же метками, если селектор меток в новом модуле совпадает с меткой в текущем модуле.

В вашей Deployment настройке новые модули будут иметь такие метки, как:

  • app: auth
  • environment: dev
  • app-role: api
  • tier: backend

PodAntiAffinity был настроен так, чтобы не разрешать развертывание нового модуля, если уже есть модуль с меткой: app: auth .

NodeAffinity был настроен для развертывания только на узле с меткой environment: dev .

Подводя итог, ваша ошибка:

 0/4 nodes are available: 1 node(s) didn't match pod affinity/anti-affinity, 3 node(s) didn't match node selector.
 

1 узел (ы) не соответствовал привязке / анти-привязке pod

ваша настройка позволяет развертывать только на узле с меткой environment: dev и только на одном модуле с меткой app: auth .

Как вы упомянули

если у меня уже есть модули, запланированные на узле, то при выполнении развертывания они не будут перезаписывать уже существующие модули.

PodAntiAffinity поведение сработало и не позволило развернуть новый модуль с меткой app: auth , поскольку он уже был.

3 узла не соответствуют селектору узлов.

NodeAffinity позволяет развертывать модули только на узле с меткой environment: dev . Другие узлы, вероятно, имеют метки типа environment: system , environment: uat , environment: qa которые не соответствуют environment: dev метке, поэтому не совпадают node selector .

Решение

Самый простой способ — удалить NodeAffinity .

Пока TolpologyKey установлено значение kubernetes.io/hostname in PodAntiAffinity , этого достаточно.

topologyKey использует метку по умолчанию, прикрепленную к узлу, для динамической фильтрации по имени узла.

Для получения дополнительной информации, пожалуйста, ознакомьтесь с этой статьей.

Если вы опишете свой nodes и grep их, kubernetes.io/hostname вы получите уникальное значение:

 $ kubectl describe node | grep kubernetes.io/hostname
                    kubernetes.io/hostname=gke-affinity-default-pool-27d6eabd-vhss
                    kubernetes.io/hostname=gke-affinity-default-pool-5014ecf7-5tkh
                    kubernetes.io/hostname=gke-affinity-default-pool-c2afcc97-clg9
 

Тесты

 apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth
  labels:
    app: auth
    environment: dev
    app-role: api
    tier: backend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: auth
  template:
    metadata:
      labels:
        app: auth
        environment: dev
        app-role: api
        tier: backend
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - auth
            topologyKey: kubernetes.io/hostname
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: Always
          ports:
            - containerPort: 80
 

После развертывания этого YAML.

 $ kubectl get po -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP         NODE                                      NOMINATED NODE   READINESS GATES
auth-7fccf5f7b8-4dkc4   1/1     Running   0          9s    10.0.1.9   gke-affinity-default-pool-c2afcc97-clg9   <none>           <none>
auth-7fccf5f7b8-5qgt4   1/1     Running   0          8s    10.0.2.6   gke-affinity-default-pool-5014ecf7-5tkh   <none>           <none>
auth-7fccf5f7b8-bdmtw   1/1     Running   0          8s    10.0.0.9   gke-affinity-default-pool-27d6eabd-vhss   <none>           <none>
 

Если вы увеличите количество реплик до 7, модули больше не будут развернуты. Все новые модули будут заблокированы в Pending состоянии, в antiPodAffinity котором они работали (у каждого узла уже есть модуль с меткой app: dev ).

 $ kubectl get po -o wide
NAME                    READY   STATUS    RESTARTS   AGE    IP         NODE                                      NOMINATED NODE   READINESS GATES
auth-7fccf5f7b8-4299k   0/1     Pending   0          79s    <none>     <none>                                    <none>           <none>
auth-7fccf5f7b8-4dkc4   1/1     Running   0          2m1s   10.0.1.9   gke-affinity-default-pool-c2afcc97-clg9   <none>           <none>
auth-7fccf5f7b8-556h5   0/1     Pending   0          78s    <none>     <none>                                    <none>           <none>
auth-7fccf5f7b8-5qgt4   1/1     Running   0          2m     10.0.2.6   gke-affinity-default-pool-5014ecf7-5tkh   <none>           <none>
auth-7fccf5f7b8-bdmtw   1/1     Running   0          2m     10.0.0.9   gke-affinity-default-pool-27d6eabd-vhss   <none>           <none>
auth-7fccf5f7b8-q4s2c   0/1     Pending   0          79s    <none>     <none>                                    <none>           <none>
auth-7fccf5f7b8-twb9j   0/1     Pending   0          79s    <none>     <none>                                    <none>           <none>
 

Аналогичное решение было описано в блоге High-Availability Deployment of Pods on Multi-Zone Worker Nodes.

Ответ №2:

Ваше правило привязки к узлу требует, чтобы для планирования рассматривался только узел разработчика. В сочетании с вашим podAntiAffinityRule это означает, что можно запланировать только один модуль (тот, который находится на узле разработки).

Чтобы получить равномерное планирование между узлами, вам придется добавить дополнительные узлы разработчика или удалить правило nodeAffinity.

Комментарии:

1. Итак, как мне гарантировать, что в моем производственном кластере я всегда получаю равномерное планирование узлов в пуле узлов (иначе запланируйте каждый модуль в другой зоне доступности)? Но также убедитесь, что каждое последующее развертывание, кроме первого, способно перезаписывать / обновлять исходное развертывание?