Kubernetes Deployment: полное руководство по управлению приложениями | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Kubernetes Deployment: полное руководство по управлению приложениями

04 апреля 2026 9 мин. чтения
Содержание статьи

Deployment в Kubernetes — это основной контроллер для декларативного управления жизненным циклом stateless-приложений в кластере. Вместо ручного создания и обновления подов (Pods) вы описываете желаемое состояние приложения в YAML-манифесте: сколько должно работать реплик, какой образ контейнера использовать и как проводить обновления. Kubernetes непрерывно сравнивает фактическое состояние кластера с этим описанием и автоматически вносит корректировки, обеспечивая отказоустойчивость и минимальный простой. Это фундаментальный инструмент для любого DevOps-инженера, работающего с production-средами.

По своей философии Deployment действует как слой управления (governance layer) для вашего приложения, аналогично тому, как системы вроде Eidos AGI устанавливают guardrails для AI-агентов. Он обеспечивает соблюдение правил (например, количество реплик, стратегия обновления) и документирует конфигурацию через YAML, что схоже с ведением Architectural Decision Records (ADR). В этом руководстве мы детально разберем структуру манифеста, стратегии обновления RollingUpdate и Recreate, а также предоставим готовые практические примеры для веб-приложений, микросервисов и приложений с состоянием.

Что такое Deployment и почему он — основа управления приложениями в Kubernetes

Deployment — это объект API Kubernetes, который управляет развертыванием и обновлением набора идентичных подов. Его ключевая роль — обеспечить декларативное управление желаемым состоянием (desired state). Вы не даете кластеру команды «создать 3 пода» или «обновить образ». Вместо этого вы заявляете: «Я хочу, чтобы работало 3 реплики моего приложения на образе app:v2.0». Контроллер Deployment, работающий в плоскости управления Kubernetes, постоянно отслеживает это состояние и реактивно вносит изменения для его достижения и поддержания.

Этот принцип аналогичен работе реактивных UI-фреймворков, таких как Floem, где состояние интерфейса (сигнал) автоматически вызывает обновления представления. В Kubernetes состояние (например, количество готовых реплик) — это сигнал, на который реагируют контроллеры. Без Deployment вам пришлось бы вручную управлять подами, что чревато ошибками, простоями и сложным масштабированием. Deployment абстрагирует эту работу, предоставляя надежный механизм для развертывания, масштабирования (изменения replicas), обновления и отката приложений.

Желаемое состояние: как Deployment обеспечивает порядок в кластере

Концепция желаемого состояния (desired state) — краеугольный камень Kubernetes. Вы описываете цель в YAML-манифесте, а система непрерывно работает для её достижения. Deployment выступает в роли исполнителя этой философии для рабочих нагрузок без состояния. Он не управляет подами напрямую, а создает и управляет объектом ReplicaSet, который, в свою очередь, гарантирует наличие указанного количества идентичных подов.

Схема работы: Deployment -> ReplicaSet -> Pod(s). При обновлении образа приложения Deployment создает новый ReplicaSet с обновленным шаблоном пода и начинает плавно переносить нагрузку на новые поды, управляя жизненным циклом старого ReplicaSet. Такой подход обеспечивает документированность (весь процесс описан в YAML), воспроизводимость и контроль, подобно тому, как governance-системы устанавливают правила и отслеживают выполнение задач для AI-агентов.

Deployment vs другие контроллеры: когда что использовать

Выбор правильного контроллера критически важен для корректной работы приложения. Deployment предназначен в первую очередь для stateless-приложений, где каждый под является взаимозаменяемой единицей.

  • StatefulSet: Используйте для stateful-приложений, требующих устойчивых сетевых идентификаторов (стабильные имена хостов), упорядоченного и безопасного развертывания/масштабирования, а также постоянного хранилища (PersistentVolume). Примеры: базы данных (MySQL, PostgreSQL), кластеры Kafka, Elasticsearch.
  • DaemonSet: Используйте, когда необходимо запустить под на каждом (или на некоторых) узле кластера. Идеален для системных демонов: сборщики логов (Fluentd), мониторинг (Node Exporter), сетевые плагины.
  • Job / CronJob: Используйте для выполнения разовых задач (Job) или задач по расписанию (CronJob), которые должны завершиться. После выполнения поди останавливаются. Примеры: миграции БД, пакетная обработка, ночные репорты.

Для большинства веб-приложений, API-сервисов и микросервисов без сохранения состояния на локальном диске Deployment является правильным и достаточным выбором.

Структура YAML-манифеста Deployment: разбор ключевых полей

Практическая работа с Deployment начинается с YAML-манифеста. Понимание каждого поля необходимо для эффективного управления. Вот базовый каркас:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-app
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: example-app
  template:
    metadata:
      labels:
        app: example-app
    spec:
      containers:
      - name: app-container
        image: nginx:1.25-alpine
        ports:
        - containerPort: 80

replicas и selector: управление масштабом и связывание

Поле spec.replicas определяет желаемое количество идентичных реплик (подов) вашего приложения, которые должны работать одновременно. Это основа для горизонтального масштабирования. Изменить количество можно как правкой манифеста и применением kubectl apply, так и командой kubectl scale deployment/example-app --replicas=5.

Поле spec.selector критически важно для связывания Deployment с управляемыми им подами. Deployment использует селектор matchLabels для поиска подов, которыми он должен управлять. Метки (labels), указанные здесь, должны точно совпадать с метками, заданными в spec.template.metadata.labels. Это механизм, с помощью которого созданный Deployment'ом ReplicaSet находит «свои» поды. Используйте уникальные, осмысленные пары ключ-значение, например, app: example-app, component: api.

template: определение контейнеров и их конфигурации

Блок spec.template — это шаблон пода (Pod Template). Именно здесь определяется само приложение. Внутри template.spec вы описываете контейнеры аналогично обычному Pod-манифесту.

  • containers: Список контейнеров в поде. Для большинства приложений он состоит из одного элемента.
  • name: Уникальное имя контейнера внутри пода.
  • image: Имя Docker-образа и его тег. Всегда указывайте конкретный тег (не latest) для воспроизводимости.
  • ports: Список портов, которые контейнер открывает.
  • resources: Запросы (requests) и лимиты (limits) на CPU и память. Лимиты — это guardrails, предотвращающие истощение ресурсов узла, аналогично ограничениям для AI-агентов.
  • livenessProbe, readinessProbe: Проверки жизнеспособности и готовности. Критически важны для production, так как позволяют Kubernetes понимать, жив ли контейнер и готов ли он принимать трафик. Их настройка — это форма проверки задачи перед допуском к работе, как в системах управления вроде Eidos AGI.

Стратегии обновления: RollingUpdate и Recreate для минимизации downtime

Одна из ключевых функций Deployment — управляемое обновление приложения. Стратегия обновления задается в поле spec.strategy.type. Выбор правильной стратегии напрямую влияет на доступность сервиса во время деплоя.

RollingUpdate: плавное обновление без простоев

Стратегия RollingUpdate (используется по умолчанию) обеспечивает постепенное обновление реплик приложения без остановки всего сервиса. Новые поды создаются с новой версией, и после их готовности (readinessProbe проходит) старые поды постепенно удаляются. Доступность поддерживается на протяжении всего процесса.

Поведение управляется двумя параметрами в spec.strategy.rollingUpdate:

  • maxUnavailable: Максимальное количество подов, которые могут быть недоступны во время обновления. Может быть абсолютным числом (например, 1) или процентом от replicas (например, 25%). Установка в 0 означает, что нельзя удалять старые поды, пока новые не станут готовы.
  • maxSurge: Максимальное количество подов, которые могут быть созданы сверх желаемого количества replicas. Может быть абсолютным числом или процентом. Установка в 1 позволяет создать одну новую реплику перед удалением старой, ускоряя обновление.

Пример для 3 реплик: maxUnavailable: 1 и maxSurge: 1. При обновлении Kubernetes может: 1) создать 1 новый под (всего 4), 2) после его готовности удалить 1 старый под (остается 3), 3) повторять цикл, пока все поды не будут обновлены. Для веб-приложений и микросервисов часто используют maxUnavailable: 25% и maxSurge: 25% для баланса скорости и доступности.

Recreate: когда нужна полная остановка

Стратегия Recreate полностью останавливает текущую версию приложения (удаляет все поды) перед созданием новых. Это приводит к простою (downtime) на время перезапуска.

Используйте эту стратегию только в особых случаях:

  • Приложения, которые не поддерживают работу в двух разных версиях одновременно (например, из-за изменений в схеме общей базы данных).
  • Критичные изменения конфигурации, требующие полного перезапуска всех экземпляров.
  • Если ваше приложение не имеет внешнего состояния и быстрый перезапуск допустим.

Этот сценарий требует особого внимания, подобно выполнению рискованной операции миграции в системах управления, где необходимо предварительное документирование решения (ADR) и полный контроль над процессом. Для сложных обновлений, например, с миграцией данных, может быть полезно ознакомиться с практиками безопасного деплоя в production.

Практические примеры развертывания разных типов приложений

Теория закрепляется практикой. Ниже приведены готовые к использованию манифесты для типичных сценариев.

Пример 1: Развертывание веб-приложения (Nginx)

Базовый stateless Deployment для веб-сервера с проверкой готовности.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-web
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: nginx-web
    spec:
      containers:
      - name: nginx
        image: nginx:1.25-alpine
        ports:
        - containerPort: 80
        readinessProbe:          # Проверка готовности
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
        resources:
          requests:
            memory: "64Mi"
            cpu: "50m"
          limits:
            memory: "128Mi"
            cpu: "200m"

Пример 2: Развертывание микросервиса (API сервис)

Deployment для REST API сервиса с настройкой ресурсов и обеими проверками (liveness и readiness).

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-service
      version: v1
  template:
    metadata:
      labels:
        app: api-service
        version: v1
    spec:
      containers:
      - name: api
        image: myregistry/api-service:2.5.1
        ports:
        - containerPort: 8080
        env:
        - name: DB_HOST
          value: "postgres-service"
        livenessProbe:          # Проверка, жив ли контейнер
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
          failureThreshold: 3
        readinessProbe:         # Проверка, готов ли принимать трафик
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
        resources:
          requests:
            memory: "256Mi"
            cpu: "200m"
          limits:                # Guardrails для ресурсов
            memory: "512Mi"
            cpu: "500m"

Пример 3: Развертывание приложения с состоянием (с временным хранилищем)

Deployment для приложения, которому нужно временное хранилище на уровне пода (например, для кэша). Важно: для истинно stateful-приложений с постоянными данными используйте StatefulSet.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cache-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: cache-app
  template:
    metadata:
      labels:
        app: cache-app
    spec:
      containers:
      - name: app
        image: redis:7-alpine
        ports:
        - containerPort: 6379
        volumeMounts:
        - name: cache-storage
          mountPath: /data
      volumes:
      - name: cache-storage
        emptyDir: {}            # Временное хранилище, живет пока жив под.

Внимание: Использование emptyDir в Deployment означает, что данные будут потеряны при пересоздании или перемещении пода на другой узел. Для данных, которые должны сохраняться, необходимо использовать PersistentVolumeClaim и понимать, что Deployment не гарантирует устойчивых идентификаторов подов или порядка запуска. В таких случаях изучите различия в инструментах конфигурации, чтобы выбрать правильный подход для хранения конфигов, и рассмотрите переход на StatefulSet.

Best Practices и guardrails для production-сред

Следование проверенным практикам превращает Deployment из рабочего инструмента в надежный механизм управления production-нагрузкой.

Настройка проверок жизнеспособности (liveness/readiness probes)

Probes — это механизм обратной связи приложения с Kubernetes.

  • livenessProbe определяет, жив ли контейнер. Если проверка падает, Kubernetes перезапускает контейнер. Используйте для обнаружения «зависших» состояний (deadlock).
  • readinessProbe определяет, готов ли контейнер принимать трафик. Пода с непройденной проверкой исключается из балансировщиков нагрузки Service. Критично для плавного обновления (RollingUpdate).

Настраивайте разные эндпоинты для liveness и readiness. Liveness-эндпоинт должен быть легковесным и не зависеть от внешних сервисов (БД, кэш). Readiness-эндпоинт может проверять доступность всех критичных зависимостей. Правильные интервалы (initialDelaySeconds, periodSeconds) предотвращают ложные перезапуски.

Управление ресурсами и предотвращение инцидентов

Всегда задавайте resources.requests и resources.limits.

  • requests: Гарантированное количество CPU/памяти, которое планировщик Kubernetes резервирует для пода. Под будет размещен на узле, где есть достаточно свободных ресурсов.
  • limits: Максимальное количество ресурсов, которое контейнер может использовать. Если контейнер превышает лимит по памяти (OOM), он будет убит. Превышение лимита по CPU приведет к throttling.

Отсутствие limits — частая причина инцидентов, когда один контейнер исчерпывает память узла, вызывая падение всех остальных подов на нем. Слишком завышенные requests ведут к неэффективному использованию кластера. Начинайте с умеренных значений, основанных на метриках мониторинга, и корректируйте. Для оркестрации более сложных зависимостей и шаблонов развертывания рассмотрите использование инструментов вроде Helm. Шпаргалка по командам Helm CLI поможет ускорить работу.

Итоговый чеклист для production Deployment:

  1. Всегда используйте readinessProbe и livenessProbe.
  2. Всегда задавайте limits и requests для CPU и памяти.
  3. Используйте стратегию RollingUpdate с настроенными maxUnavailable/maxSurge.
  4. Избегайте тега образа latest, используйте семантическое версионирование.
  5. Применяйте метки (labels) для организации ресурсов и селекторов.
  6. Храните манифесты в системе контроля версий (Git) — это ваши ADR для инфраструктуры.
  7. Мониторьте статус развертываний: kubectl get deployments, kubectl rollout status deployment/<name>, kubectl describe deployment/<name>.
  8. Знайте, как выполнить откат: kubectl rollout undo deployment/<name>.

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

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