GKE Autopilot Ingress возвращает ошибку 502 в течение 5–15 минут после развертывания.

Я настроил (очень) простое развертывание с помощью GKE в кластере GKE Autopilot с последней версией Kubernetes (1.18.15-gke.1501) и подключил вход (внешний балансировщик нагрузки HTTP(s)), который ссылается на простую службу ClusterIP.

Всякий раз, когда я обновляю развертывание новым образом, у меня возникает около 5-15 минут простоя, когда балансировщик нагрузки возвращает ошибку 502. Кажется, что плоскость управления создает новый, обновленный модуль, позволяет пройти проверки работоспособности на уровне обслуживания (не проверки балансировки нагрузки, он еще не создает NEG), затем убивает старый модуль, в то же время время установки нового NEG. Затем он не удаляет старый NEG до определенного промежутка времени.

введите здесь описание изображения

Журналы в модулях показывают, что проверки работоспособности выполняются, но панель инструментов GKE показывает противоречивые результаты для состояния Ingress. Вход будет отображаться нормально, но служба будет 502.

Вещи, которые я пробовал

  • Увеличение количества модулей с 1 до 3. Это помогло при некоторых развертываниях, но при каждом другом развертывании это увеличивало количество времени, которое требовалось балансировщику нагрузки для правильного разрешения.
  • Попытка установить maxSurge на 1 и maxUnavailable на 0. Это совсем не уменьшило время простоя.
  • Добавление lifecycle.preStop.exec.command: ["sleep", "60"] в контейнер при развертывании. Это было предложено в документации GKE здесь .
  • Повторное создание входа, службы, развертываний и кластеров несколько раз.
  • Добавление BackendConfig к сервису, который добавляет к нему более медленный слив.
  • Добавление ворот готовности, найденных в документации, которые должны исправить это, но по какой-то причине этого не делают?

Ничто из вышеперечисленного не помогло и не оказало заметного влияния на то, как долго все было не так.

Я действительно, очень смущен тем, почему это не работает. Такое ощущение, что я упускаю что-то действительно очевидное, но это настолько простая конфигурация, что вы думаете, что она... просто сработает?? Кто-нибудь знает, что происходит?

Файлы конфигурации

Конфигурация развертывания:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: foundation-deployment
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  selector:
    matchLabels:
      app: foundation-web
  template:
    metadata:
      labels:
        app: foundation-web
    spec:
      readinessGates:
        - conditionType: "cloud.google.com/load-balancer-neg-ready"

      serviceAccountName: foundation-database-account
      containers:
        # Run Cloud SQL proxy so we can safely connect to Postgres on localhost.
        - name: cloud-sql-proxy
          image: gcr.io/cloudsql-docker/gce-proxy:1.17
          resources:
            requests:
              cpu: "250m"
              memory: 100Mi
            limits:
              cpu: "500m"
              memory: 100Mi
          command:
            - "/cloud_sql_proxy"
            - "-instances=nine-foundation:us-central1:foundation-staging=tcp:5432"
          securityContext:
            runAsNonRoot: true
        # Main container config
        - name: foundation-web
          image: gcr.io/project-name/foundation_web:latest
          imagePullPolicy: Always
          lifecycle:
            preStop:
              exec:
                command: ["sleep", "60"]
          env:
           # Env variables
          resources:
            requests:
              memory: "500Mi"
              cpu: "500m"
            limits:
              memory: "1000Mi"
              cpu: "1"
          livenessProbe:
            httpGet:
              path: /healthz
              port: 4000
            initialDelaySeconds: 10
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /healthz
              port: 4000
            initialDelaySeconds: 10
            periodSeconds: 10
          ports:
            - containerPort: 4000

Конфиг службы:

apiVersion: v1
kind: Service
metadata:
  name: foundation-web-service
  annotations:
    cloud.google.com/neg: '{"ingress": true}'
    cloud.google.com/backend-config: '{"ports": {"4000": "foundation-service-config"}}'
spec:
  type: ClusterIP
  selector:
    app: foundation-web
  ports:
    - port: 4000
      targetPort: 4000

БэкэндКонфигурация:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: foundation-service-config
spec:
  # sessionAffinity:
  #   affinityType: "GENERATED_COOKIE"
  #   affinityCookieTtlSec: 120
  connectionDraining:
    drainingTimeoutSec: 60

Входная конфигурация:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: foundation-web-ingress
  labels:
    name: foundation-web-ingress
spec:
  backend:
    serviceName: foundation-web-service
    servicePort: 4000



Ответы (1)


Причина, по которой ваш кластер Autopilot испытывал задержку во время нового развертывания, заключается в том, что мастер кластера проходил обновление. Система GKE Autopilot обновляет мастер каждый раз, когда пользователь выполняет развертывание в кластере. Однако, с точки зрения предотвращения этого в критические моменты в вашей работе, вы можете создать окно обслуживания для этого кластера, чтобы вы могли контролировать, когда автоматическое обслуживание кластера, такое как автоматические обновления, может и не может происходить в вашем кластере GKE Autopilot. .

Я надеюсь, что это объясняет проблему.

К сведению: по умолчанию Kubernetes для проверки готовности составляет 10 минут. Это означает, что даже если развертывание все еще происходит, проверка готовности пометит его как неудачное через 10 минут. GKE Autopilot устанавливает настраиваемый тайм-аут для всего этапа развертывания (а не только для состояния ожидания готовности), и во время ожидания состояния готовности Kubernetes вызывает зонд готовности для мониторинга развертывания.

Зонд готовности, основанный на значениях по умолчанию Kubernetes, отмечает сбой развертывания через 10 минут. GKE Autopilot видит сообщение от проверки готовности и сообщает о сбое развертывания из-за превышения крайнего срока.

В качестве возможного решения можно увеличить время ожидания проверки готовности по умолчанию в YAML, указав значение «progressDeadlineSeconds» [5] в секундах. Значение по умолчанию — 600 секунд (10 минут). Подробнее об этом здесь [6]. Я бы предложил попробовать добавить это в ваш файл YAML и увеличить время ожидания, чтобы увидеть, решит ли это проблему. Когда происходит чрезмерное масштабирование. Мы рекомендуем клиенту установить значение конфигурации автоматического масштабирования minNodes равным maxNodes.

Cluster Autoscaler считает, что модуль можно запланировать на одном из существующих узлов, но планировщик говорит, что это невозможно. Модуль не будет запланирован, и масштабирование не произойдет. В этом случае мы предлагаем создать новый пул узлов или изменить размер MIG, поддерживающего существующий пул узлов, в качестве быстрого решения проблемы. Поскольку вы упомянули, что повторно создавали вход, службу, развертывания и кластеры несколько раз, обязательно выполните следующие шаги: Неполная сборка мусора Мусор Google Kubernetes Engine каждые две минуты собирает встроенные в контейнер балансировщики нагрузки. Если кластер удаляется до полного удаления балансировщиков нагрузки, необходимо вручную удалить группы NEG балансировщика нагрузки. Просмотрите NEG в своем проекте, выполнив следующую команду:

gcloud compute network-endpoint-groups list

В выводе команды найдите соответствующие NEG. Чтобы удалить NEG, выполните следующую команду, где neg — это имя NEG:

gcloud compute network-endpoint-groups delete [neg]

Согласование развертываний рабочих нагрузок с распространением конечных точек https://cloud.google.com/kubernetes-engine/docs/how-to/container-native-load-balancing#align_rollouts

Примечание. Эта проблема не возникает в кластерах, использующих обратную связь о готовности Pod для управления развертыванием рабочей нагрузки. Дополнительную информацию см. в разделе Готовность Pod.

Когда вы развертываете рабочую нагрузку в своем кластере или обновляете существующую рабочую нагрузку, встроенному в контейнер балансировщику нагрузки может потребоваться больше времени для распространения новых конечных точек, чем для завершения развертывания рабочей нагрузки. Пример развертывания, который вы развертываете в этом руководстве, использует два поля для согласования развертывания с распространением конечных точек: TerminationGracePeriodSeconds и minReadySeconds. terminationGracePeriodSeconds позволяет корректно завершать работу Pod, ожидая прекращения соединений после запланированного удаления Pod. minReadySeconds добавляет период задержки после создания пода. Вы указываете минимальное количество секунд, в течение которых новый модуль должен находиться в состоянии «Готово» без сбоя какого-либо из его контейнеров, чтобы модуль считался доступным. Вы должны настроить значения minReadySeconds и TerminationGracePeriodSeconds рабочих нагрузок на 60 секунд или выше, чтобы гарантировать, что служба не будет нарушена из-за развертывания рабочей нагрузки. terminationGracePeriodSeconds доступен во всех спецификациях Pod, а minReadySeconds доступен для Deployments и DaemonSet. Дополнительные сведения о тонкой настройке развертывания см. в статье RollingUpdateStrategy.

InitialDelaySeconds в readinessProbe пода не учитывается. Можно ожидать, что конфигурация initialDelaySeconds в readinessProbe пода будет учитываться подсистемой балансировки нагрузки контейнера; однако readinessProbe реализуется kubelet, а конфигурация initialDelaySeconds управляет проверкой работоспособности kubelet, а не собственным балансировщиком нагрузки контейнера. Встроенная в контейнер балансировка нагрузки имеет собственную проверку работоспособности балансировки нагрузки.

Неудачное развертывание Ваше развертывание может застрять, пытаясь развернуть свой новейший набор реплик, так и не завершив его. Это может произойти из-за некоторых из следующих факторов:

Insufficient quota
Readiness probe failures
Image pull errors
Insufficient permissions
Limit ranges
Application runtime misconfiguration
For more information on failed deployments please refer [4].

Я хотел бы поделиться следующими документами, касающимися автопилота GKE, для справки, поскольку этот продукт является относительно новым:

  1. Обзор GKE Autopilot: https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview
  2. Архитектура кластера автопилота: https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-architecture
  3. Статья о развертывании Kubernetes: https://medium.com/polarsquad/check-your-kubernetes-deployments-46dbfbc47a7c [4]. Неудачное развертывание: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#failed-deployment [5]. Срок выполнения в секундах: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#progress-deadline-seconds [6]Развертывания: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
person Divya Chikoti    schedule 21.05.2021