Настройка проверки готовности, работоспособности или запуска
Мне сложно понять, что лучше всего подходит для моей ситуации и как это реализовать.
В двух словах проблема такая:
- Я развертываю свои DB (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 должен знать, что содержащаяся в нем программа потерпела неудачу. Однако все, что я пробовал, приводит к провалу проверки, отказу в соединении и т. Д.:
# 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 ответа
На самом деле, думаю, я мог бы разобраться в этом.
Отчасти проблема в том, что хотя restartPolicy: Always
по умолчанию, модули не знают, что Django потерпел неудачу, поэтому они думают, что они исправны.
Мое мнение было неправильным, поскольку я изначально предполагал, что мне нужно обратиться к развертыванию БД, чтобы увидеть, началось ли оно перед запуском развертывания API. Вместо этого мне нужно было проверить, не сработал ли Django, и повторно развернуть его, если это так.
Для меня это было сделано следующим образом:
livenessProbe:
tcpSocket:
port: 5000
initialDelaySeconds: 2
periodSeconds: 2
readinessProbe:
tcpSocket:
port: 5000
initialDelaySeconds: 2
periodSeconds: 2
Я изучаю Kubernetes, поэтому поправьте меня, если есть лучший способ сделать это или это просто неправильно. Я просто знаю, что он выполняет то, что я хочу.
Вы просто не ждете достаточно долго.
Артефакты развертывания, которые вы здесь показываете, выглядят вполне нормально. Даже если ваше приложение не может достичь базы данных, например, потому, что оно еще не запущено, это совершенно нормально. Однако у каждого модуля есть политика перезапуска, которая по умолчаниюAlways
. Таким образом, когда модуль выходит из строя, Kubernetes перезапускает его; и когда он снова выйдет из строя, он будет снова запущен; и когда он продолжает выходить из строя, Kubernetes будет делать паузу на десятки секунд между перезапусками (ужасныйCrashLoopBackOff
государство).
В конце концов, если вы находитесь в этом цикле ожидания и перезапуска, база данных действительно появится, а затем Kubernetes перезапустит ваши модули приложений, после чего приложение запустится нормально.
Единственное, что я бы здесь изменил, это то, что ваши зонды готовности для двух модулей должны проверять сами службы, а не какую-либо другую службу. Вы, наверное, хотитеpath
быть чем-то вроде /
или /healthz
или что-то еще, что является фактическим путем HTTP-запроса в службе. Это может вернуть 503 Service Unavailable, если обнаружит, что его зависимость недоступна, или вы можете просто дать сбой. Просто сбой - это нормально.
Это совершенно нормальная установка в Kubernetes; Невозможно более прямо сказать, что модуль A не может запуститься, пока служба B не будет готова. Обратной стороной этого является то, что шаблон на самом деле довольно общий: если ваше приложение вылетает и перезапускается всякий раз, когда не может получить доступ к своей базе данных, не имеет значения, размещена ли база данных вне кластера, или если она выйдет из строя через некоторое время. время запуска; та же логика попытается перезапустить ваше приложение, пока оно снова не заработает.