Настройка готовности, живучести или запуска пробника - PullRequest
0 голосов
/ 22 января 2020

Мне трудно понять, что было бы лучше для моей ситуации, и как на самом деле ее реализовать.

В двух словах, проблема заключается в следующем:

  • Я ускорение развертывания моих БД (Postgres), BE (Django) и FE (React) с помощью Skaffold
  • Приблизительно в 50% случаев BE будет раскручиваться до того, как DB
  • Одна из первых вещей, которые Django пытается сделать, - это подключиться к БД
  • Он пытается только один раз (по замыслу и не может быть изменен), если он не может, он терпит неудачу, и приложение не работает

  • Таким образом, , мне нужно убедиться, что каждый раз, когда я ускоряю развертывание, развертывание БД запускается перед началом развертывания BE

Я наткнулся на готовность, жизнеспособность и пробный запуск . Я прочитал его пару раз, и тесты готовности звучат так, как мне нужно: я не хочу, чтобы развертывание BE начиналось до тех пор, пока развертывание БД не будет готово принимать соединения.

Я полагаю, я не понимаю как это настроить. Это то, что я пробовал, но я все еще сталкиваюсь с случаями, когда один загружается раньше другого.

postgres .yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: postgres
  template:
    metadata:
      labels:
        component: postgres
    spec:
      containers:
        - name: postgres
          image: testappcontainers.azurecr.io/postgres
          ports:
            - containerPort: 5432
          env: 
            - name: POSTGRES_DB
              valueFrom:
                secretKeyRef:
                  name: testapp-secrets
                  key: PGDATABASE
            - name: POSTGRES_USER
              valueFrom:
                secretKeyRef:
                  name: testapp-secrets
                  key: PGUSER
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: testapp-secrets
                  key: PGPASSWORD
            - name: POSTGRES_INITDB_ARGS
              value: "-A md5"
          volumeMounts:
            - name: postgres-storage
              mountPath: /var/lib/postgresql/data
              subPath: postgres
      volumes:
        - name: postgres-storage
          persistentVolumeClaim:
            claimName: postgres-storage
---
apiVersion: v1
kind: Service
metadata:
  name: postgres-cluster-ip-service
spec:
  type: ClusterIP
  selector:
    component: postgres
  ports:
    - port: 1423
      targetPort: 5432

api.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      component: api
  template:
    metadata:
      labels:
        component: api
    spec:
      containers:
        - name: api
          image: testappcontainers.azurecr.io/testapp-api
          ports:
            - containerPort: 5000
          env:
            - name: PGUSER
              valueFrom:
                secretKeyRef:
                  name: testapp-secrets
                  key: PGUSER
            - name: PGHOST
              value: postgres-cluster-ip-service
            - name: PGPORT
              value: "1423"
            - name: PGDATABASE
              valueFrom:
                secretKeyRef:
                  name: testapp-secrets
                  key: PGDATABASE
            - name: PGPASSWORD
              valueFrom:
                secretKeyRef:
                  name: testapp-secrets
                  key: PGPASSWORD
            - name: SECRET_KEY
              valueFrom:
                secretKeyRef:
                  name: testapp-secrets
                  key: SECRET_KEY
            - name: DEBUG
              valueFrom:
                secretKeyRef:
                  name: testapp-secrets
                  key: DEBUG
          readinessProbe:
            httpGet:
              host: postgres-cluster-ip-service
              port: 1423
            initialDelaySeconds: 10
            periodSeconds: 5
            timeoutSeconds: 2
---
apiVersion: v1
kind: Service
metadata:
  name: api-cluster-ip-service
spec:
  type: ClusterIP
  selector:
    component: api
  ports:
    - port: 5000
      targetPort: 5000

client.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: client-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      component: client
  template:
    metadata:
      labels:
        component: client
    spec:
      containers:
        - name: client
          image: testappcontainers.azurecr.io/testapp-client
          ports:
            - containerPort: 3000
          readinessProbe:
            httpGet:
              path: api-cluster-ip-service
              port: 5000
            initialDelaySeconds: 10
            periodSeconds: 5
            timeoutSeconds: 2
---
apiVersion: v1
kind: Service
metadata:
  name: client-cluster-ip-service
spec:
  type: ClusterIP
  selector:
    component: client
  ports:
    - port: 3000
      targetPort: 3000

Я не думаю, что ingress.yaml и skaffold.yaml будут полезно, но дайте мне знать, если я должен добавить их.

Так что я здесь не так делаю?


Редактировать:

Итак Я опробовал несколько вещей, основываясь на ответе Дэвида Мейз. Это помогло мне понять, что происходит лучше, но я все еще сталкиваюсь с проблемами, которые я не совсем понимаю, как решить.

Первая проблема заключается в том, что даже при использовании по умолчанию restartPolicy: Always, и даже при Django терпит неудачу, сами стручки не терпят неудачу. Стручки думают, что они совершенно здоровы, хотя Django не удалось.

Вторая проблема состоит в том, что очевидно, что Стручки должны быть осведомлены о статусе Django. Это та часть, которую я не совсем оборачиваю, особенно если зонды проверяют состояние других развертываний или самих себя?

Вчера мое мышление было первым, но сегодня я думаю, что оно второе: Pod должен знать, что содержащаяся в нем программа провалилась. Тем не менее, все, что я пробовал, приводило к отказу зонда, отказу в соединении и т. Д. c.:

# referring to itself
host: /health
port: 5000

host: /healthz
port: 5000

host: /api
port: 5000

host: /
port: 5000

host: /api-cluster-ip-service
port: 5000

host: /api-deployment
port: 5000

# referring to the DB deployment
host: /health
port: 1423 #or 5432

host: /healthz
port: 1423 #or 5432

host: /api
port: 1423 #or 5432

host: /
port: 1423 #or 5432

host: /postgres-cluster-ip-service
port: 1423 #or 5432

host: /postgres-deployment
port: 1423 #or 5432

Так что, очевидно, я неправильно настроил зонд, несмотря на то, что он "супер легкая "реализация (как это описали несколько блогов). Например, маршруты /health и /healthz: они встроены в Kubernetes или их нужно настроить? Перечитывая документы, надеюсь, прояснить это.

Ответы [ 2 ]

2 голосов
/ 22 января 2020

Вы просто не ждете достаточно долго.

Показанные здесь артефакты развертывания выглядят вполне нормально. Даже если ваше приложение не может достичь базы данных, это даже нормально, если приложение не запускается быстро. Тем не менее, у каждого модуля есть политика перезапуска , по умолчанию Always. Таким образом, когда модуль выходит из строя, Kubernetes перезапустит его; и когда это снова терпит неудачу, это будет перезапущено снова; и когда он продолжает терпеть неудачу, Kubernetes делает паузу в десятки секунд между перезапусками (состояние ужаса CrashLoopBackOff).

В конце концов, если вы находитесь в этом ожидании и перезапуске l oop, база данных будет фактически Поднимитесь, а затем Kubernetes перезапустит ваши модули приложений, после чего приложение будет запускаться нормально.

Единственное, что я хотел бы изменить здесь, это то, что ваши тесты готовности для двух модулей должны проверять службы сами, а не какой-то другой сервис. Возможно, вы хотите, чтобы path был чем-то вроде / или /healthz или чем-то еще, что является действительным путем HTTP-запроса в службе. Это может вернуть 503 Service Unavailable, если он обнаружит, что его зависимость недоступна, или вы можете просто создать sh. Просто сбой в порядке.

Это абсолютно нормальная настройка в Кубернетесе; нет более прямого способа сказать, что модуль A не может запуститься, пока служба B не будет готова. Обратная сторона этого заключается в том, что шаблон на самом деле довольно обобщенный c: если ваше приложение аварийно завершает работу и перезапускается всякий раз, когда оно не может достичь своей базы данных, не имеет значения, размещена ли база данных за пределами кластера или происходит сбой через некоторое время после запуска; тот же лог c будет пытаться перезапустить ваше приложение, пока оно не заработает снова.

0 голосов
/ 22 января 2020

На самом деле, думаю, я мог бы разобраться.

Часть проблемы в том, что, хотя restartPolicy: Always является значением по умолчанию, модули не знают о сбое Django, поэтому они думают, что они здоровый.

Я ошибся, так как изначально предполагал, что мне нужно обратиться к развертыванию БД, чтобы узнать, началось ли оно до начала развертывания API. Вместо этого мне нужно было проверить, не удалось ли Django, и повторно развернуть его, если это так.

Выполнение следующих действий для меня:

livenessProbe:
  tcpSocket:
    port: 5000
  initialDelaySeconds: 2
  periodSeconds: 2
readinessProbe:
  tcpSocket:
    port: 5000
  initialDelaySeconds: 2
  periodSeconds: 2

Я изучаю Kubernetes, поэтому, пожалуйста, поправьте меня, если есть лучший способ сделать это или это просто неправильно. Я просто знаю, что это выполняет то, что я хочу.

...