Production-развертывание приложения в Kubernetes строится вокруг нескольких связанных объектов. ConfigMap передает обычные настройки, Secret хранит пароли и токены, Deployment управляет жизненным циклом Pod, Service дает подам стабильный внутренний адрес, а Ingress направляет внешний HTTP или HTTPS-трафик к Service.
Рабочий порядок выглядит так: подготовить Namespace и образ с фиксированным тегом, проверить доступ к кластеру, Registry и Ingress Controller, применить ConfigMap и Secret, создать Deployment, дождаться готовности Pod, связать их с Service, опубликовать Service через Ingress и выполнить внешний запрос. Команда kubectl apply подтверждает прием манифеста API-сервером, но не гарантирует, что приложение уже принимает трафик.
В этой инструкции используется приложение web-api с двумя репликами, портом контейнера 8080, внутренним Service на порту 80 и доменом app.example.com. Число реплик, лимиты CPU и памяти, домен, health endpoints и политика обновления должны соответствовать SLA и результатам нагрузочного тестирования.
Как устроена production-схема развертывания в Kubernetes
Какие объекты участвуют в публикации приложения
Каждый объект отвечает за отдельный участок цепочки. Связи между ними строятся через имена, namespace и labels, поэтому ошибка в одном поле может оставить весь сервис без трафика.
| Объект | Назначение | Что проверять |
|---|---|---|
| Namespace | Изолирует ресурсы приложения и ограничивает область действия имен. | Совпадение namespace во всех манифестах и командах kubectl. |
| Deployment | Задает желаемое число реплик, образ, probes и стратегию обновления. | Selector, labels, состояние ReplicaSet и доступность Pod. |
| ReplicaSet | Создается Deployment и поддерживает нужное число Pod для конкретной ревизии. | Количество desired, current и ready реплик. |
| Pod | Запускает один или несколько контейнеров приложения. | Фаза, Ready-состояние, рестарты, события и логи. |
| Service | Дает стабильный DNS-адрес и распределяет запросы между готовыми Pod. | Selector, порт, targetPort и EndpointSlices. |
| Ingress | Связывает host и path с Service для внешнего HTTP или HTTPS-доступа. | IngressClass, DNS, TLS, backend и статус контроллера. |
| ConfigMap | Хранит обычную конфигурацию: режим работы, таймауты, feature flags. | Имена ключей, namespace и факт передачи в контейнер. |
| Secret | Передает пароли, токены, ключи и TLS-материалы. | RBAC, ротация, способ хранения и отсутствие значений в логах. |
Для дополнительного разбора control plane, worker nodes, Pod, Deployment, Service и Namespace пригодится материал об архитектуре кластера и ключевых объектах API.
В каком порядке проходят запрос и обновление версии
Внешний запрос проходит через DNS к внешнему адресу Ingress Controller. Контроллер выбирает правило по host и path, передает запрос в Service, а Service направляет его на готовый Pod по labels. Pod считается подходящим backend после успешной проверки readinessProbe.
Обновление начинается с изменения image tag в Deployment. Kubernetes создает новую ReplicaSet, запускает новые Pod и ждет их readiness. При параметрах maxUnavailable: 0 и maxSurge: 1 старая версия продолжает обслуживать запросы, пока новая реплика не пройдет проверку. Предыдущая ReplicaSet сохраняется в истории, поэтому Deployment можно вернуть на прошлую ревизию.
Полная схема релиза: образ -> манифесты -> API-сервер -> ReplicaSet -> Pod -> readiness -> Service -> Ingress -> внешний запрос. Значения replicas, ресурсов и времени ожидания нельзя копировать без проверки нагрузки и времени запуска конкретного приложения.
Подготовить production-окружение и набор манифестов
Проверить доступ к кластеру, Registry и Ingress Controller
Начните с проверки контекста и прав. Ошибка в текущем кластере опаснее синтаксической ошибки YAML: манифест может попасть в другой environment.
kubectl config current-context
kubectl cluster-info
kubectl auth can-i get deployments -n production
kubectl auth can-i create deployments -n production
kubectl get namespace production
kubectl get ingressclass
kubectl get pods -A
Для приватного Registry создайте pull-secret в том же namespace, где работает Deployment. Secret с учетными данными Registry не переносится автоматически между namespace.
kubectl create secret docker-registry regcred \
--docker-server=REGISTRY_HOST \
--docker-username=REGISTRY_USER \
--docker-password=REGISTRY_PASSWORD \
-n production
Проверьте точный image tag, доступность Registry с worker-узлов и наличие образа для нужной архитектуры CPU. Локальный образ на машине администратора не помогает Pod, если worker-узел не может получить его из Registry.
Ingress сам по себе трафик не принимает. Нужен работающий Ingress Controller, его Service с внешним адресом и настроенная DNS-запись. Для размещения кластера в облаке можно рассмотреть облачную инфраструктуру Timeweb Cloud с Kubernetes, но сетевые настройки Ingress, DNS и TLS все равно нужно проверить в выбранной среде.
Зафиксировать параметры приложения до написания YAML
Составьте короткую таблицу параметров. Она устраняет путаницу между портом процесса, портом контейнера, портом Service и внешним адресом.
| Параметр | Пример | Проверка |
|---|---|---|
| Имя приложения | web-api | Одинаковое значение в Deployment, Service и Ingress. |
| Namespace | production | Namespace существует, права выданы. |
| Образ | registry.example.org/team/web-api:2026.09.06 | Тег существует и не меняет содержимое после публикации. |
| Порт процесса | 8080 | Приложение слушает этот порт внутри контейнера. |
| Порт Service | 80 | На него ссылается Ingress или внутренний клиент. |
| Health endpoints | /startup, /ready, /live | Каждый endpoint возвращает ожидаемый код. |
| Реплики | 2 | В кластере хватает CPU, памяти и worker-узлов. |
| Домен | app.example.com | DNS указывает на внешний адрес Ingress Controller. |
Зафиксируйте целевую версию Kubernetes и API-версии ресурсов. Для Ingress используйте networking.k8s.io/v1. Тег latest усложняет диагностику и откат, потому что его содержимое может измениться без изменения YAML.
Описать Deployment для запуска и обновления приложения
Связать Deployment, ReplicaSet и Pod через labels
Deployment выбирает управляемые Pod через spec.selector.matchLabels. Эти labels должны совпадать с labels в spec.template.metadata.labels. Service использует такой же принцип, но его selector задается отдельно.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-api
namespace: production
labels:
app.kubernetes.io/name: web-api
spec:
replicas: 2
revisionHistoryLimit: 5
progressDeadlineSeconds: 600
selector:
matchLabels:
app.kubernetes.io/name: web-api
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
template:
metadata:
labels:
app.kubernetes.io/name: web-api
spec:
imagePullSecrets:
- name: regcred
terminationGracePeriodSeconds: 30
securityContext:
runAsNonRoot: true
containers:
- name: web-api
image: registry.example.org/team/web-api:2026.09.06
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: web-api-config
- secretRef:
name: web-api-secrets
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
startupProbe:
httpGet:
path: /startup
port: http
periodSeconds: 5
failureThreshold: 30
readinessProbe:
httpGet:
path: /ready
port: http
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /live
port: http
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
Поле selector связывает Deployment с Pod и после создания Deployment не меняется произвольно. Для изменения схемы labels создайте новый Deployment или заранее спланируйте миграцию. Подстановка другого selector может привести к ошибке применения или потере управления нужными Pod.
Подробные примеры полей Deployment, RollingUpdate, probes, requests и limits собраны в руководстве по управлению приложениями через Kubernetes Deployment.
Добавить probes и ограничения ресурсов
startupProbe дает медленно запускающемуся процессу время на инициализацию. Пока эта проверка не прошла, Kubernetes не запускает liveness-проверку. Это снижает риск рестартов во время миграции или загрузки большого кэша.
readinessProbe определяет, можно ли отправлять Pod пользовательский трафик. Ошибка readiness убирает Pod из EndpointSlices, но не обязательно перезапускает контейнер. livenessProbe ищет зависший процесс и при повторяющейся ошибке инициирует рестарт контейнера.
Проверяйте endpoints непосредственно в приложении. Если процесс слушает порт 8080, а probe обращается к порту 8000, Pod останется NotReady. Если endpoint зависит от базы данных, решите отдельно, должна ли недоступность базы исключать Pod из трафика или приводить к перезапуску.
requests участвуют в планировании Pod. limits ограничивают потребление ресурсов. Значения 100m CPU и 128Mi памяти подходят только как пример, их нужно подтвердить метриками и нагрузкой. Недостаточный memory limit приводит к OOMKilled, слишком низкий CPU limit увеличивает время ответа.
Настроить управляемое rolling update
Параметр maxUnavailable: 0 запрещает уменьшать число доступных реплик во время обновления. maxSurge: 1 разрешает временно создать одну дополнительную реплику. При двух репликах кластеру нужно место минимум для трех Pod на части процесса обновления.
progressDeadlineSeconds: 600 задает срок, после которого Deployment получит состояние прогресса с ошибкой, если новые Pod не стали готовыми. Это не отменяет обновление автоматически. Статус нужно проверить командой kubectl rollout status.
revisionHistoryLimit: 5 сохраняет пять старых ReplicaSet. Слишком маленькое значение сокращает выбор для rollback, слишком большое увеличивает число объектов, которые нужно обслуживать. Сценарий обновления и отката полезно автоматизировать после проверки ручного процесса, например по схеме из примера скрипта развертывания приложения в Kubernetes.
Настроить ConfigMap и Secret в Kubernetes
Что хранить в ConfigMap
ConfigMap подходит для значений, которые не дают доступа к системе: режима запуска, уровня логирования, URL сервиса без учетных данных, feature flags и таймаутов.
apiVersion: v1
kind: ConfigMap
metadata:
name: web-api-config
namespace: production
data:
APP_ENV: production
LOG_LEVEL: info
UPSTREAM_TIMEOUT_MS: '2000'
FEATURE_CACHE: 'true'
Подключение через envFrom передает все ключи как переменные окружения. Для точечного подключения используйте configMapKeyRef, когда контейнеру нужен один параметр и нежелательно передавать весь набор.
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: web-api-config
key: LOG_LEVEL
optional: false
Что хранить в Secret и как защитить данные
В Secret помещают пароль базы данных, API-токен, ключ подписи, строку подключения с credentials и TLS-материалы. Реальные значения нельзя коммитить в публичный репозиторий, помещать в Docker-образ или печатать в логах.
apiVersion: v1
kind: Secret
metadata:
name: web-api-secrets
namespace: production
type: Opaque
stringData:
DB_PASSWORD: replace-before-apply
API_TOKEN: replace-before-apply
stringData позволяет передать обычный текст при создании объекта, после чего API-сервер преобразует его в формат Secret. Base64 в поле data служит кодированием, не шифрованием. Ограничьте доступ RBAC, включите encryption at rest для etcd и настройте ротацию. Для production с большим числом секретов разумно использовать внешний secret manager, который выдает значения по контролируемой политике.
Secret действует внутри своего namespace. Сервисный аккаунт Pod должен получать только нужные ресурсы, а доступ к Secret через RBAC нужно проверять командой kubectl auth can-i.
Проверить обновление конфигурации
При передаче ConfigMap и Secret через environment variables приложение получает значения при старте процесса. Изменение объекта не перезапускает контейнер и не обновляет переменную в уже работающем процессе.
kubectl apply -f web-api-config.yaml -n production
kubectl apply -f web-api-secrets.yaml -n production
kubectl rollout restart deployment/web-api -n production
kubectl rollout status deployment/web-api -n production
При volume mount Kubernetes обновляет файл с учетом механизма синхронизации, но приложение должно перечитать его само. Процесс, который читает конфигурацию только при запуске, потребует restart. После изменения имени ключа проверьте, что Deployment ссылается на актуальный ConfigMap или Secret.
Создать Service для внутреннего доступа к Pod
Сопоставить selector, port и targetPort
Для приложения, которое публикуется через Ingress, обычно достаточно Service типа ClusterIP. Он не получает публичный адрес и доступен внутри кластера по DNS-имени.
apiVersion: v1
kind: Service
metadata:
name: web-api
namespace: production
labels:
app.kubernetes.io/name: web-api
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: web-api
ports:
- name: http
port: 80
targetPort: http
protocol: TCP
selector Service должен совпадать с labels Pod. targetPort: http ссылается на именованный порт контейнера 8080. Service port 80 используется клиентом или Ingress. Если задать targetPort: 80, а процесс слушает 8080, запросы не дойдут до приложения.
Проверить endpoints до настройки внешнего доступа
Сначала проверьте, появились ли готовые EndpointSlices. Пустой список означает, что Service не нашел подходящие Ready Pod или все Pod исключены readiness-проверкой.
kubectl get service web-api -n production
kubectl get endpointslices -n production \
-l kubernetes.io/service-name=web-api
kubectl describe service web-api -n production
kubectl get pods -n production \
-l app.kubernetes.io/name=web-api \
-o wide
Выполните тестовый запрос из временного Pod в том же namespace. Для успешного ответа ожидайте HTTP-код, который приложение использует для health endpoint, обычно 200.
kubectl run netcheck -n production --rm -it \
--restart=Never \
--image=curlimages/curl:8.10.1 \
-- curl -i http://web-api.production.svc.cluster.local/ready
Service не делает Pod готовым. В балансировку попадают только адреса, которые Kubernetes считает Ready. Если EndpointSlices пусты, проверяйте labels, readinessProbe и фазу Pod до перехода к Ingress.
Опубликовать Service через Ingress
Настроить host, path и backend Service
Ingress описывает правило маршрутизации, но обработку выполняет Ingress Controller. В примере используется класс nginx, корневой path и Service web-api на порту 80.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-api
namespace: production
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: web-api-tls
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-api
port:
number: 80
Имя Service и порт должны совпадать с фактическим объектом в том же namespace. Ingress не ищет Service в другом namespace через имя host. Для одного точного URL применяйте pathType: Exact, для всех вложенных путей используйте Prefix. Обработку завершающего slash и rewrite проверьте отдельно, потому что эти правила зависят от контроллера.
Готовые примеры связки Deployment, Service, Ingress, ConfigMap и Secret можно использовать как сверку структуры в практическом руководстве по деплою сервисов в Kubernetes.
Подключить TLS и проверить DNS
TLS Secret должен находиться в namespace production и содержать сертификат для host app.example.com. Создать его из файлов сертификата и ключа можно командой:
kubectl create secret tls web-api-tls \
--cert=fullchain.pem \
--key=privkey.pem \
-n production
DNS-запись должна указывать на внешний адрес Service Ingress Controller. ClusterIP приложения для этого не подходит. Проверьте адрес контроллера и состояние Ingress:
kubectl get service -A
kubectl get ingress web-api -n production
kubectl describe ingress web-api -n production
kubectl get secret web-api-tls -n production
Для проверки TLS используйте имя host при установлении соединения. Переменные позволяют не хранить адрес конкретного окружения в команде:
export APP_HOST=app.example.com
export INGRESS_ADDRESS=INGRESS_EXTERNAL_ADDRESS
openssl s_client -connect ${INGRESS_ADDRESS}:443 -servername ${APP_HOST}
export APP_URL=APP_SCHEME://${APP_HOST}
curl -i ${APP_URL}/health
HTTP-код 404 от контроллера часто означает несовпадение host или path. Код 502 обычно указывает на недоступный backend, неверный Service port или отсутствие Ready endpoints. Ответ приложения с собственным кодом ошибки нужно анализировать по логам контейнера.
Применить манифесты и проверить состояние релиза
Проверить rollout Deployment
Перед применением убедитесь, что команды обращаются к правильному контексту. Для предварительного просмотра используйте kubectl diff, затем применяйте ресурсы в логическом порядке.
kubectl config current-context
kubectl diff -f k8s/ -n production
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/configmap.yaml -f k8s/secret.yaml
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/ingress.yaml
kubectl rollout status deployment/web-api -n production --timeout=10m
После rollout сверяйте несколько уровней состояния. Значения desired, current, ready и available должны соответствовать ожидаемому числу реплик.
kubectl get deployment web-api -n production
kubectl get rs -n production -l app.kubernetes.io/name=web-api
kubectl get pods -n production -l app.kubernetes.io/name=web-api -o wide
kubectl get pods -n production -l app.kubernetes.io/name=web-api \
-o=jsonpath='{range .items[*]}{.metadata.name}{" Ready="}{.status.containerStatuses[0].ready}{" Restarts="}{.status.containerStatuses[0].restartCount}{"\n"}{end}'
Ожидайте завершения rollout, статус 1/1 для контейнера и отсутствие новых рестартов. Принятый YAML и готовый релиз, это разные состояния, поэтому внешнюю проверку выполняйте после проверки Pod и EndpointSlices.
Найти причину проблем через describe, Events и logs
Команда describe показывает условия Pod и события планировщика. Ищите сообщения о нехватке ресурсов, невозможности скачать образ, ошибках монтирования, отказах probes и завершении контейнера.
kubectl describe pod POD_NAME -n production
kubectl get events -n production --sort-by=.lastTimestamp
kubectl logs deployment/web-api -n production --all-containers=true --tail=200
kubectl logs pod/POD_NAME -n production --previous --tail=200
Текущие логи помогают увидеть ошибку работающего процесса. Ключ --previous показывает вывод контейнера перед последним рестартом и часто раскрывает причину CrashLoopBackOff. Не выводите в логах environment variables целиком и не копируйте значения Secret в диагностические сообщения.
Проверить цепочку Service и Ingress
Проверка сетевой цепочки должна идти изнутри наружу. Сначала подтвердите готовые Pod, потом EndpointSlices, затем запрос к ClusterIP или DNS Service, после чего проверьте Ingress и внешний host.
kubectl get pods -n production
kubectl get service web-api -n production
kubectl get endpointslices -n production \
-l kubernetes.io/service-name=web-api
kubectl get ingress web-api -n production
kubectl run netcheck -n production --rm -it \
--restart=Never \
--image=curlimages/curl:8.10.1 \
-- curl -i http://web-api/ready
Для внешнего запроса задайте APP_URL с нужной схемой и host, затем проверьте HTTP-код, заголовки, время ответа и сертификат. Запрос с другим Host может попасть в default backend и создать ошибочное впечатление, что приложение недоступно.
Разобрать типовые ошибки при запуске
| Симптом | Вероятная причина | Проверка | Исправление |
|---|---|---|---|
ImagePullBackOff, ErrImagePull | Неверное имя образа или тега, закрытый Registry, отсутствует pull-secret. | kubectl describe pod POD_NAME -n production | Проверить точный tag, доступ worker-узлов к Registry и imagePullSecrets в том же namespace. |
CrashLoopBackOff | Процесс завершается, не хватает конфигурации, недоступна зависимость или probe настроена на неверный endpoint. | kubectl logs pod/POD_NAME -n production --previous | Сверить exit code, команду запуска, ConfigMap, Secret, зависимости и health endpoints. |
Pending | Не хватает CPU или памяти, не подходят taints, nodeSelector, PVC или политика размещения. | kubectl describe pod POD_NAME -n production | Изучить Events, проверить ресурсы узлов, requests, tolerations, PVC и доступность подходящих worker-узлов. |
Running, но NotReady | Неверный порт probe, ошибочный путь health endpoint или приложение еще запускается. | kubectl describe pod POD_NAME -n production | Проверить URL, порт, задержки, логи и фактическое поведение endpoint изнутри Pod. |
| Service без endpoints | Selector не совпадает с labels Pod или все Pod не прошли readiness. | kubectl get endpointslices -n production | Сверить labels Deployment и selector Service, затем исправить readiness или состояние Pod. |
Ingress возвращает 404 | Не совпадает host, path или ingressClassName, запрос попал в другой backend. | kubectl describe ingress web-api -n production | Проверить Host в запросе, DNS, path, IngressClass и наличие правила для нужного namespace. |
Ingress возвращает 502 | Service не имеет Ready endpoints, неверен порт или контроллер не может подключиться к backend. | kubectl get service,endpointslices -n production | Сверить port, targetPort, selector и readiness Pod. |
| Ingress не отвечает | Нет внешнего адреса контроллера, DNS указывает не туда или контроллер не запущен. | kubectl get service -A и kubectl get pods -A | Проверить внешний Service контроллера, DNS-запись, сетевые правила и его логи. |
Диагностируйте в порядке зависимости: образ и Pod, затем ресурсы и probes, после этого labels и Service, в конце Ingress и DNS. Такой порядок сокращает число ложных гипотез. Например, проверка DNS не исправит пустой EndpointSlices, а изменение timeout Ingress не устранит падение процесса.
ImagePullBackOff и ErrImagePull
Начните с Events. Kubernetes обычно сообщает, не найден ли tag, отклонены ли credentials или недоступен Registry. Убедитесь, что Secret типа kubernetes.io/dockerconfigjson создан в production, а имя в imagePullSecrets совпадает с его metadata.name.
CrashLoopBackOff и постоянные рестарты
Сравните текущие и предыдущие логи, exit code и настройки запуска. Проверьте обязательные ключи ConfigMap и Secret, DNS-имена зависимостей, миграции и права на файловую систему. Увеличение задержки probe без анализа причины может скрыть проблему и отсрочить ее проявление.
Pending, NotReady и отсутствие endpoints
Для Pending первыми проверяйте Events. Сообщения о Insufficient cpu или Insufficient memory указывают на requests и свободные ресурсы. Сообщения о taint, PVC или node affinity требуют проверки правил размещения.
Для NotReady проверьте путь и порт readinessProbe. Если Pod Ready, но Service пуст, сравните selector Service с labels Pod посимвольно, включая регистр и префиксы.
Ingress возвращает 404, 502 или не отвечает
Разделите проблему на четыре уровня: DNS, внешний Service контроллера, правило Ingress и backend Service. Код 404 от контроллера обычно связан с host или path. Код 502 появляется, когда правило найдено, но контроллер не получает корректный ответ от backend. Отсутствие соединения требует проверки адреса контроллера, сетевых правил и DNS.
Выполнить базовый откат неудачного релиза
Сохранить и посмотреть историю ревизий
Deployment хранит историю изменений, если старые ReplicaSet не удалены из-за малого revisionHistoryLimit. Перед релизом зафиксируйте image tag, номер задачи и изменения конфигурации в системе деплоя или changelog.
kubectl rollout history deployment/web-api -n production
kubectl rollout history deployment/web-api -n production --revision=3
kubectl get rs -n production -l app.kubernetes.io/name=web-api
В описании ревизии проверяйте образ, environment variables и другие поля Pod template. Изменение только ConfigMap или Secret не всегда создает новую ревизию Deployment, поэтому история Deployment не покажет полный набор изменений окружения.
Откатить Deployment и подтвердить восстановление
Для возврата на предыдущую ревизию выполните rollback и дождитесь готовности новых Pod.
kubectl rollout undo deployment/web-api -n production
kubectl rollout status deployment/web-api -n production --timeout=10m
kubectl get pods -n production -l app.kubernetes.io/name=web-api
kubectl get endpointslices -n production \
-l kubernetes.io/service-name=web-api
Если нужно выбрать конкретную ревизию, используйте ее номер:
kubectl rollout undo deployment/web-api \
--to-revision=3 \
-n production
Команда rollout undo меняет Pod template, но сама по себе не подтверждает работу приложения. После нее проверьте Ready-состояние Pod, отсутствие рестартов, EndpointSlices, внутренний запрос и внешний HTTP или HTTPS-запрос с правильным Host.
Учесть ограничения rollback
Откат Deployment не отменяет миграцию базы данных, изменение внешнего API, удаление данных или ротацию Secret. Если новая версия уже изменила схему БД необратимым способом, возврат старого образа может привести к дополнительным ошибкам.
Для безопасного релиза используйте backward-compatible migrations: сначала добавляйте новые поля, сохраняйте совместимость старого кода, переключайте чтение и запись после проверки, а удаление старой схемы выполняйте отдельным этапом. Перед критическим изменением проверьте backup и процедуру восстановления.
Если проблема связана с ConfigMap или Secret, их нужно вернуть отдельно и затем запустить новый rollout. После восстановления зафиксируйте причину сбоя и обновите чек-лист, манифест или pipeline.
Проверить production-готовность перед передачей сервиса пользователям
Контрольный список перед релизом
- Манифесты и версии: YAML проходит проверку, API-версии поддерживаются кластером, image tag фиксирован и существует в Registry.
- Deployment: selector совпадает с labels, replicas соответствуют SLA, заданы requests и limits, настроены startup, readiness и liveness probes.
- Безопасность: реальные пароли отсутствуют в Git и Docker-образе, RBAC ограничен, Secret не выводится в логи, контейнер запускается без root-привилегий.
- Конфигурация: имена ConfigMap и Secret совпадают со ссылками в Deployment, обязательные ключи присутствуют, после изменения конфигурации выполнен нужный restart.
- Service: selector совпадает с labels,
portиtargetPortпроверены, EndpointSlices содержат Ready-адреса. - Ingress и TLS: установлен нужный Ingress Controller, указан
ingressClassName, host и path совпадают с запросом, сертификат действителен. - DNS: запись направляет домен на внешний адрес Ingress Controller, а не на ClusterIP приложения.
- Наблюдаемость: доступны логи, события, метрики и алерты на недоступность, рост рестартов и потерю Ready-реплик.
- Восстановление: известны команды rollback, сохранена история ревизий, проверен backup и описаны ограничения отката для базы данных.
- Нагрузка: число реплик, requests, limits, timeout и параметры rolling update подтверждены тестом, а не взяты без изменений из примера.
Минимальный набор команд для дежурной проверки
kubectl config current-context
kubectl get deployment DEPLOYMENT_NAME -n NAMESPACE
kubectl rollout status deployment/DEPLOYMENT_NAME -n NAMESPACE
kubectl get pods -n NAMESPACE -l app.kubernetes.io/name=APP_NAME -o wide
kubectl describe pod POD_NAME -n NAMESPACE
kubectl logs pod/POD_NAME -n NAMESPACE --tail=200
kubectl get events -n NAMESPACE --sort-by=.lastTimestamp
kubectl get service SERVICE_NAME -n NAMESPACE
kubectl get endpointslices -n NAMESPACE \
-l kubernetes.io/service-name=SERVICE_NAME
kubectl get ingress INGRESS_NAME -n NAMESPACE
kubectl describe ingress INGRESS_NAME -n NAMESPACE
kubectl rollout history deployment/DEPLOYMENT_NAME -n NAMESPACE
Для рабочего релиза замените placeholders конкретными значениями namespace и имен ресурсов. Команды не должны печатать содержимое Secret. Результат проверки фиксируйте в журнале релиза: версия образа, номер ревизии, время rollout, число Ready Pod, HTTP-код внешнего запроса и выявленные события.
Такая последовательность дает воспроизводимый production-деплой: Kubernetes принимает описанные ресурсы, Deployment запускает нужную версию, probes подтверждают готовность, Service формирует endpoints, Ingress публикует маршрут, а rollback возвращает предыдущий Pod template при проблемном обновлении. Каждый этап проверяется отдельной командой, поэтому причину сбоя можно локализовать без перебора случайных настроек.