Kubernetes: How can we create service dependencies using kubernetes
Ты развернул в кластере веб-приложение и базу данных. Прописал манифесты, накатил их и — бац — ваше приложение сразу полетело в цикл перезапусков, потому что не
Ты развернул в кластере веб-приложение и базу данных. Прописал манифесты, накатил их и — бац — ваше приложение сразу полетело в цикл перезапусков, потому что не нашло базу. Суровые будни: кубер не знает о ваших логических зависимостях между подами. Он создаёт всё примерно одновременно, и кто успел, тот и стартанул.
Вам нужно, чтобы MySQL точно была готова к коннекту до старта веб-сервиса. Наивная надежда на простой порядок в kubectl apply не сработает — поды могут создаваться в разной последовательности, да и readiness самого пода базы нужно дождаться.
Ждём готовности, а не просто создания
Прямой команды «запусти это после того» в Kubernetes нет. Но есть паттерны. Базовый — использовать readinessProbe для сервиса базы данных и initContainers для веб-приложения.
В под веб-приложения добавляем initContainer, который будет терзать проверкой доступность MySQL. Пока база не откликнется, основной контейнер не стартанёт.
apiVersion: v1
kind: Pod
metadata:
name: web-app-pod
spec:
initContainers:
- name: wait-for-db
image: appropriate/curl
command: ['sh', '-c', 'until curl http://mysql-service:3306; do echo waiting; sleep 2; done']
containers:
- name: web-app
image: your-web-app:latest
env:
- name: DB_HOST
value: "mysql-service"
Это грубый пример. В реальности для проверки MySQL лучше использовать специализированный клиент (mysqladmin ping) или скрипт на Python.
Уровень сервиса: зависеть от Service, а не от Pod
Ваш веб-сервис зависит от другого сервиса (MySQL), а не от конкретных под. Убедитесь, что Service для базы создан и селектит правильные поды. InitContainer будет обращаться по DNS-имени этого сервиса (mysql-service). Кубер начнёт резолвить имя только когда сервис реально существует.
Порядок применения манифестов всё же имеет значение: сначала сервис и deployment базы, потом — всё для приложения. Можно склеить манифесты в один файл — kubectl apply -f all-in-one.yaml — ресурсы создаются в том порядке, в котором описаны.
Если всё совсем сложно — Helm и зависимости
Когда сервисов много, управлять зависимостями вручную становится тем ещё танцем с бубном. Здесь в игру входят пакетные менеджеры, например Helm.
В Helm вы можете явно указать в Chart.yaml зависимости (dependencies) между чартами. Установщик (Tiller в Helm 2 или Helm 3) будет учитывать порядок. Это чисто оркестрационный уровень развёртывания, а не runtime-ожидание внутри кластера, но часто этого достаточно.
Итог
Kubernetes не запускает ресурсы по вашим логическим зависимостям. Ваша задача — описать условия готовности.
Порядок действий: накатываете манифесты БД и её Service, добавляете в под приложения initContainer с проверкой доступности этого сервиса, настраиваете readinessProbe для самих под БД. Или упаковываете всё в Helm с явными dependency. В 90% случаев initContainer — ваш выход.