Деплой сервисов в Kubernetes: практическое руководство 2026 | AdminWiki

Деплой сервисов в Kubernetes: практическое руководство 2026

26 августа 2026 7 мин. чтения

Введение: что мы будем разворачивать и зачем

В этом руководстве развернем типовое веб-приложение с базой данных в Kubernetes. Используем основные объекты: Deployment для управления подами, Service для сетевого доступа, Ingress для маршрутизации внешнего трафика, ConfigMap и Secrets для конфигурации. Все шаги проверены на практике в 2026 году и актуальны для текущих версий Kubernetes.

Вы получите рабочий деплой, который можно использовать как шаблон для production-среды. Каждый шаг сопровождается готовыми YAML-манифестами и командами kubectl. Если вы впервые разворачиваете сервис в Kubernetes, пройдите все разделы по порядку. Опытные специалисты могут использовать материал как шпаргалку.

Материал дополняет базовые руководства по архитектуре кластера и ключевым объектам API. Если вам нужны production-манифесты с расширенными настройками проб и стратегий обновления, обратитесь к полному руководству по Deployment.

Подготовка окружения

Для выполнения шагов нужен работающий кластер Kubernetes. Подойдет minikube, kind, k3s или облачный managed-кластер. Также потребуется настроенный kubectl и доступ к реестру образов. В примерах используем публичный образ nginx и образ приложения, доступный вашему кластеру.

Проверка доступа к кластеру

Убедитесь, что kubectl подключен к нужному кластеру. Выполните команду:

kubectl config current-context

Вывод покажет текущий контекст. Проверьте, что он соответствует целевому кластеру. Затем запросите список узлов:

kubectl get nodes

Если команда возвращает узлы в статусе Ready, доступ к кластеру настроен корректно. При ошибке подключения проверьте kubeconfig и права доступа.

Создание namespace

Изолируем ресурсы статьи в отдельном namespace. Это стандартная практика, которая упрощает управление и очистку.

kubectl create namespace demo-app

Namespace demo-app создан. Все последующие команды выполняем с флагом -n demo-app или установим его как текущий контекст:

kubectl config set-context --current --namespace=demo-app

Создание Deployment

Deployment управляет репликами подов и обеспечивает декларативное обновление приложения. Создадим манифест deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  namespace: demo-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
      - name: web-app
        image: nginx:1.27
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "256Mi"

Ключевые поля: replicas задает количество подов, selector связывает Deployment с подами по метке app: web-app, template описывает под. Применим манифест:

kubectl apply -f deployment.yaml

Проверим статус:

kubectl get deployments
kubectl get pods

После применения вы увидите три пода в статусе Running. Если поды не запускаются, перейдите к разделу о типичных проблемах.

Выбор стратегии обновления

Deployment поддерживает две стратегии обновления: RollingUpdate и Recreate. RollingUpdate обновляет поды поочередно, сохраняя доступность приложения. Recreate сначала удаляет все поды, затем создает новые, что вызывает простой.

Для большинства веб-приложений выбирайте RollingUpdate. Она задана по умолчанию. Параметры maxSurge и maxUnavailable управляют темпом обновления. Для stateful-приложений с жесткими требованиями к состоянию может потребоваться Recreate, но это частный случай.

Настройка ресурсов (requests/limits)

Поля requests и limits в манифесте задают минимальные и максимальные ресурсы для контейнера. Requests используются планировщиком для выбора узла. Limits ограничивают потребление и предотвращают влияние одного пода на другие.

Указывайте реальные значения, основанные на нагрузке. Заниженные limits приведут к OOMKilled, завышенные requests - к неэффективному использованию кластера. Начните с приведенных значений и корректируйте по метрикам.

Настройка конфигурации: ConfigMap и Secrets

Конфигурация отделяется от кода. Несекретные настройки хранятся в ConfigMap, чувствительные данные - в Secrets. Это упрощает обновление конфигурации без пересборки образа.

Создание ConfigMap

Создадим ConfigMap с настройками приложения:

apiVersion: v1
kind: ConfigMap
metadata:
  name: web-app-config
  namespace: demo-app
data:
  APP_ENV: "production"
  LOG_LEVEL: "info"
  DATABASE_HOST: "postgres-service"

Применим и проверим:

kubectl apply -f configmap.yaml
kubectl get configmap web-app-config -o yaml

Создание Secret

Secret хранит пароли, ключи API и токены. Данные кодируются в base64. Создадим Secret для пароля базы данных:

apiVersion: v1
kind: Secret
metadata:
  name: web-app-secret
  namespace: demo-app
type: Opaque
data:
  DATABASE_PASSWORD: c3VwZXJzZWNyZXRwYXNz

Значение c3VwZXJzZWNyZXRwYXNz - это base64-кодированная строка. Закодировать значение можно командой:

echo -n 'supersecretpass' | base64

В реальных кластерах включите шифрование Secrets в etcd и используйте RBAC для ограничения доступа. Для production-среды рассмотрите интеграцию с внешними системами управления секретами, например HashiCorp Vault.

Подключение ConfigMap и Secret к подам

Обновим Deployment, добавив переменные окружения из ConfigMap и Secret:

spec:
  containers:
  - name: web-app
    image: nginx:1.27
    envFrom:
    - configMapRef:
        name: web-app-config
    - secretRef:
        name: web-app-secret

Директива envFrom передает все ключи из ConfigMap и Secret как переменные окружения. Альтернативный способ - монтирование как volume. Выбор зависит от приложения: переменные окружения проще, volume позволяют обновлять конфигурацию без перезапуска пода.

Обеспечение сетевого доступа: Service

Поды в Kubernetes эфемерны, их IP-адреса меняются при перезапуске. Service предоставляет стабильный IP и DNS-имя для доступа к группе подов.

Типы Service: ClusterIP, NodePort, LoadBalancer

ClusterIP - тип по умолчанию, доступен только внутри кластера. NodePort открывает порт на каждом узле. LoadBalancer создает внешний балансировщик в облачных кластерах. Для внутреннего взаимодействия сервисов используйте ClusterIP. Для внешнего доступа - Ingress поверх ClusterIP.

Создадим Service типа ClusterIP:

apiVersion: v1
kind: Service
metadata:
  name: web-app-service
  namespace: demo-app
spec:
  selector:
    app: web-app
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP

Применим и проверим:

kubectl apply -f service.yaml
kubectl get services

Service направляет трафик на поды с меткой app: web-app. Балансировка выполняется автоматически между всеми готовыми подами.

Настройка внешнего доступа: Ingress

Ingress маршрутизирует внешний HTTP/HTTPS-трафик к Service по правилам хоста и пути. Для работы Ingress нужен Ingress-контроллер в кластере.

Установка Ingress-контроллера

Проверьте, установлен ли контроллер:

kubectl get pods -n ingress-nginx

Если namespace отсутствует, установите nginx-ingress через Helm:

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx --create-namespace

Дождитесь, пока поды контроллера перейдут в статус Running.

Настройка TLS

Для HTTPS создайте Secret с сертификатом и укажите его в Ingress. Автоматизировать получение сертификатов можно с помощью cert-manager. Для тестовой среды допустимо использовать самоподписанный сертификат.

Создадим Ingress с правилом для хоста app.example.com:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-app-ingress
  namespace: demo-app
spec:
  ingressClassName: nginx
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-app-service
            port:
              number: 80

Применим и проверим:

kubectl apply -f ingress.yaml
kubectl get ingress

Поле ingressClassName: nginx указывает, какой контроллер обрабатывает этот Ingress. Для добавления TLS добавьте секцию tls с именем Secret и списком хостов.

Проверка доступности сервиса

После применения всех манифестов проверьте, что приложение отвечает. Начните с локальной проверки через port-forward.

Проверка через port-forward

Команда port-forward пробрасывает порт Service на локальную машину:

kubectl port-forward service/web-app-service 8080:80

В другом терминале выполните запрос:

curl localhost:8080

Ответ HTTP 200 с содержимым страницы подтверждает, что Service и поды работают. Для проверки Ingress добавьте запись в /etc/hosts, указывающую на IP Ingress-контроллера, и выполните curl по хосту.

Просмотр логов и событий

Логи пода показывают работу приложения:

kubectl logs <pod-name>

События пода содержат информацию о жизненном цикле:

kubectl describe pod <pod-name>

В выводе ищите секцию Events. Ошибки при старте, проблемы с образами и сбои проб отображаются там. Это первый шаг при диагностике.

Типичные проблемы и их решение

При деплое в Kubernetes возникают повторяющиеся ошибки. Разберем три частые проблемы и способы их устранения.

ImagePullBackOff

Статус ImagePullBackOff означает, что кластер не может загрузить образ контейнера. Причины: неверный тег образа, отсутствие доступа к приватному реестру, превышение лимита запросов к Docker Hub.

Проверьте имя образа в манифесте. Для приватных реестров настройте imagePullSecrets в Deployment. Проверьте, что Secret с учетными данными создан в том же namespace.

CrashLoopBackOff

Контейнер запускается и сразу завершается с ошибкой. Причины: ошибка в коде приложения, неверная конфигурация, нехватка памяти.

Смотрите логи пода: kubectl logs <pod-name> --previous. Проверьте readiness/liveness пробы, если они настроены. Убедитесь, что limits по памяти достаточны для приложения.

Pod в состоянии Pending

Под не может быть запланирован на узел. Причины: недостаточно ресурсов в кластере, проблемы с PersistentVolumeClaim, селекторы узлов без совпадений.

Выполните kubectl describe pod <pod-name> и изучите события. Если не хватает ресурсов, уменьшите requests или добавьте узлы. При проблемах с PVC проверьте StorageClass и доступность томов.

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

Заключение: что дальше?

Вы развернули веб-приложение в Kubernetes: создали Deployment с тремя репликами, настроили ConfigMap и Secrets, обеспечили внутренний доступ через Service и внешний через Ingress. Проверили доступность и разобрали типичные ошибки.

Этот базовый сценарий - основа для production-деплоя. Следующие шаги: автоматизация через Helm, настройка CI/CD пайплайнов, мониторинг с Prometheus и Grafana, усиление безопасности через RBAC и Network Policies. Для проектирования production-ready кластеров изучите руководство по проектированию промышленных кластеров.

Для размещения кластера Kubernetes в облаке подойдет Timeweb Cloud с гибкой инфраструктурой и managed-решениями. Если вы работаете с микросервисной архитектурой, обратитесь к гайду по структуре манифестов для корректного версионирования YAML-файлов.

Поделиться:
Сохранить гайд? В закладки браузера