Kubernetes для DevOps инженера: от основ к продакшену

Курс помогает DevOps-инженеру освоить Kubernetes: от устройства кластера и базовых объектов до сетей, безопасности, наблюдаемости и эксплуатации в продакшене. В результате вы научитесь разворачивать приложения, управлять ресурсами и надежно сопровождать кластеры в реальных условиях.

1. Архитектура Kubernetes и базовые концепции

Архитектура Kubernetes и базовые концепции

Kubernetes (K8s) — платформа оркестрации контейнеров: она запускает приложения, следит за их состоянием, масштабирует, перезапускает при сбоях и помогает управлять сетевым доступом и конфигурацией. Эта статья закладывает фундамент: из каких частей состоит кластер Kubernetes и какими объектами вы будете управлять как DevOps-инженер.

Ментальная модель Kubernetes

Kubernetes удобно понимать как систему декларативного управления:

  • Вы описываете желаемое состояние (например, “хочу 3 реплики приложения”).
  • Control Plane пытается привести фактическое состояние к желаемому.
  • Ключевая мысль: вы не “запускаете контейнер”, вы описываете объекты (ресурсы), а Kubernetes непрерывно их “дотягивает” до нужного состояния.

    Что такое кластер Kubernetes

    Кластер — это набор узлов (nodes), объединённых общим Control Plane.

  • Control Plane — “мозг” кластера, принимает решения и хранит состояние.
  • Worker Nodes — выполняют нагрузку: запускают Pod’ы с контейнерами.
  • !Общая схема: Control Plane управляет Worker Nodes через API

    Полезные ссылки:

  • Компоненты Kubernetes
  • Объекты Kubernetes
  • Control Plane: компоненты и их роли

    kube-apiserver

    kube-apiserver — центральная точка управления.

  • Принимает запросы от kubectl, CI/CD, операторов и компонентов кластера.
  • Проверяет аутентификацию/авторизацию и валидирует запросы.
  • Записывает и читает состояние из etcd.
  • Практическое следствие: если API server недоступен, кластером невозможно управлять (хотя уже запущенные Pod’ы могут какое-то время продолжать работать).

    etcd

    etcd — распределённое key-value хранилище, где лежит вся конфигурация и состояние Kubernetes.

  • Хранит объекты: Deployments, Services, Secrets, статусы и т.д.
  • Требует бэкапов и защиты доступа.
  • Ссылка:

  • etcd
  • kube-scheduler

    kube-scheduler выбирает, на какой Node поставить Pod.

    Он учитывает:

  • доступные ресурсы (CPU/RAM);
  • ограничения и предпочтения (node selectors, affinity/anti-affinity);
  • политики распределения.
  • Важно: scheduler назначает Pod на Node, но не запускает контейнеры — запуском занимается kubelet на выбранной Node.

    kube-controller-manager

    kube-controller-manager запускает контроллеры — фоновые процессы, которые следят за состоянием ресурсов.

    Примеры контроллеров:

  • Node controller — отслеживает доступность нод.
  • ReplicaSet controller — поддерживает нужное число реплик.
  • Job controller — управляет задачами до успешного завершения.
  • Идея контроллера: “наблюдай и исправляй”.

    cloud-controller-manager

    cloud-controller-manager интегрирует кластер с облаком (если применимо):

  • создание внешних LoadBalancer’ов;
  • управление дисками (в зависимости от провайдера и CSI);
  • привязка маршрутов/сетей.
  • Ссылка:

  • Cloud Controller Manager
  • Worker Node: что выполняет приложения

    На каждой Worker Node обычно есть:

  • kubelet — агент ноды: получает инструкции через API и управляет Pod’ами.
  • container runtime — запускает контейнеры (часто containerd).
  • kube-proxy — реализует сетевую абстракцию Service (через правила iptables/ipvs).
  • Ссылка:

  • Container Runtime Interface (CRI)
  • Kubernetes API и объекты: как устроено управление

    Всё — ресурс в API

    В Kubernetes почти всё выражается через API-ресурсы: Pod, Deployment, Service, Secret и т.д.

    Вы отправляете описание (обычно YAML) в API, а дальше:

  • оно попадает в etcd;
  • контроллеры и scheduler реагируют;
  • kubelet приводит выполнение на нодах к нужному состоянию.
  • Desired state и reconciliation loop

    Kubernetes работает циклами согласования (reconciliation loops):

  • API хранит “как должно быть”.
  • Контроллер сравнивает “как есть” и “как должно быть”.
  • Вносит изменения, пока состояние не совпадёт.
  • Это базовый принцип, который объясняет, почему Kubernetes устойчив к сбоям и самовосстанавливается.

    Основные workload-объекты

    Pod

    Pod — минимальная единица размещения в Kubernetes.

  • Обычно содержит 1 контейнер с приложением.
  • Может содержать несколько контейнеров, которые разделяют сеть (один IP) и тома.
  • Важно понимать:

  • Pod — “смертный”: при пересоздании он получает новый IP.
  • Надёжность обычно достигается не “бережным” отношением к Pod, а использованием контроллеров (Deployment/StatefulSet и т.д.).
  • Ссылка:

  • Pods
  • ReplicaSet

    ReplicaSet поддерживает заданное число Pod’ов по селектору label’ов.

  • Обычно вы не создаёте ReplicaSet вручную.
  • Его создаёт Deployment.
  • Ссылка:

  • ReplicaSet
  • Deployment

    Deployment — основной объект для stateless-приложений.

    Что даёт:

  • rolling update (постепенное обновление);
  • rollback (откат);
  • управление числом реплик.
  • Ссылка:

  • Deployment
  • StatefulSet

    StatefulSet — для stateful-нагрузок, где важны стабильные идентификаторы.

    Характерные свойства:

  • стабильные имена Pod’ов;
  • предсказуемое масштабирование (по порядку);
  • часто используется вместе с PersistentVolumeClaim.
  • Ссылка:

  • StatefulSet
  • DaemonSet

    DaemonSet гарантирует, что на каждой (или выбранной) Node запущен Pod.

    Типичные кейсы:

  • агенты логирования;
  • node-exporter;
  • CNI-плагины.
  • Ссылка:

  • DaemonSet
  • Job и CronJob

    Job запускает Pod’ы до успешного завершения (batch-задачи).

    CronJob запускает Job по расписанию.

    Ссылки:

  • Job
  • CronJob
  • Labels, selectors и анатомия “управления группой”

    Labels — это пары ключ-значение, которые приклеиваются к объектам.

  • Labels позволяют группировать Pod’ы (например, app=api, tier=backend).
  • Selectors используются контроллерами и Service, чтобы выбрать нужные Pod’ы.
  • Если запомнить только одну вещь: не IP связывает компоненты в Kubernetes, а labels/selectors.

    Ссылка:

  • Labels and Selectors
  • Service: стабильная сеть поверх “смертных” Pod’ов

    Зачем нужен Service

    Pod’ы пересоздаются и меняют IP, поэтому напрямую ходить “на Pod IP” — плохая идея. Service даёт стабильную точку доступа.

    Service:

  • создаёт стабильный виртуальный IP (ClusterIP) внутри кластера;
  • балансирует трафик на набор Pod’ов по selector’у;
  • может публиковать сервис наружу (NodePort/LoadBalancer).
  • Ссылка:

  • Service
  • Типы Service

  • ClusterIP — доступен только внутри кластера.
  • NodePort — открывает порт на каждой Node.
  • LoadBalancer — просит облачный балансировщик (если поддерживается).
  • DNS в кластере

    Обычно вместе с Service вы получаете DNS-имя (например, my-svc.my-namespace.svc.cluster.local). Это обеспечивает DNS-система кластера (CoreDNS).

    Ссылка:

  • DNS for Services and Pods
  • !Как Service направляет трафик на Pod'ы через селекторы

    Ingress: входящий HTTP/HTTPS-трафик

    Ingress — набор правил L7 (обычно HTTP/HTTPS), который маршрутизирует входящий трафик к Service.

    Важно различать:

  • Ingress — это правила.
  • Ingress Controller — это реализация, которая эти правила применяет (например, NGINX Ingress Controller, Traefik и т.д.).
  • Ссылка:

  • Ingress
  • Namespace: логическая изоляция

    Namespace — способ разделить кластер на логические области.

    Используется для:

  • разделения окружений (dev/stage/prod) в одном кластере (не всегда лучшая практика, но встречается);
  • разделения команд;
  • применения RBAC и квот.
  • Ссылка:

  • Namespaces
  • Конфигурация и секреты

    ConfigMap

    ConfigMap хранит некритичную конфигурацию:

  • переменные окружения;
  • конфиги файлов.
  • Ссылка:

  • ConfigMaps
  • Secret

    Secret хранит чувствительные данные (токены, пароли, ключи).

    Важные нюансы:

  • Secret по умолчанию хранится в etcd (часто в base64, это не шифрование само по себе).
  • В продакшене обычно включают шифрование Secret’ов на уровне API Server и контролируют доступ RBAC.
  • Ссылка:

  • Secrets
  • Хранение данных: Volumes, PV/PVC и StorageClass

    Контейнеры и Pod’ы эфемерны, поэтому для данных нужны тома.

  • Volume — общий термин: способ примонтировать хранилище в Pod.
  • PersistentVolume (PV) — ресурс кластера: “кусок” хранилища.
  • PersistentVolumeClaim (PVC) — запрос на хранилище со стороны приложения.
  • StorageClass — описывает классы хранилища и динамическое выделение PV.
  • Ссылки:

  • Persistent Volumes
  • Storage Classes
  • Плагины и интерфейсы: CNI, CSI, CRI

    Kubernetes опирается на стандартные интерфейсы, чтобы быть расширяемым.

  • CRI — интерфейс для container runtime (например, containerd).
  • CNI — интерфейс для сетевых плагинов (Calico, Cilium и др.).
  • CSI — интерфейс для драйверов хранилищ (облачные диски, SAN/NAS и т.д.).
  • Ссылки:

  • CNI (спецификация)
  • CSI (спецификация)
  • Безопасность на базовом уровне: ServiceAccount и RBAC

    Kubernetes управляет доступом через:

  • ServiceAccount — “учётка” для Pod’ов, чтобы ходить в API.
  • RBAC — роли и привязки (Role/ClusterRole и RoleBinding/ClusterRoleBinding).
  • Практический принцип: выдавайте Pod’ам минимально необходимое.

    Ссылка:

  • Using RBAC Authorization
  • Что важно запомнить перед следующими темами

  • Kubernetes — это API + контроллеры, которые приводят кластер к желаемому состоянию.
  • Pod — базовая единица запуска, но управлять нужно через контроллеры (Deployment/StatefulSet).
  • Service даёт стабильную точку доступа к набору Pod’ов по labels/selectors.
  • Ingress добавляет L7-маршрутизацию (обычно HTTP/HTTPS), но требует Ingress Controller.
  • Хранилище и сеть — через стандартные интерфейсы (CSI/CNI), а безопасность — через ServiceAccount и RBAC.
  • В следующих материалах курса логично перейти к практике: установка локального кластера, работа с kubectl, базовые манифесты (Pod/Deployment/Service), а затем — к сетям, хранилищам и продакшен-паттернам.

    2. Работа с kubectl: namespaces, контексты, манифесты

    Работа с kubectl: namespaces, контексты, манифесты

    kubectl — основной CLI-инструмент для работы с Kubernetes API. В предыдущей статье мы разобрали, что Kubernetes управляется декларативно через API-объекты, а Control Plane приводит фактическое состояние к желаемому. Теперь закрепим это на практике: научимся безопасно переключаться между кластерами и неймспейсами, понимать, куда именно отправляются команды, и писать манифесты так, чтобы ими было удобно управлять в продакшене.

    Полезные первоисточники:

  • kubectl Overview
  • kubectl Cheat Sheet
  • Namespaces
  • Organizing Cluster Access Using kubeconfig Files
  • Declarative Management of Kubernetes Objects Using Configuration Files
  • Что именно делает kubectl

    kubectl не “ходит на ноды” напрямую. Он:

  • читает настройки подключения (обычно из ~/.kube/config);
  • выбирает контекст (какой кластер, какой пользователь, какой namespace по умолчанию);
  • отправляет запросы в kube-apiserver;
  • отображает ответ и помогает формировать/валидировать запросы.
  • Практический вывод: почти все проблемы “kubectl не работает” сводятся к одному из трёх: не тот контекст, не те права (RBAC), нет сетевого доступа до API.

    Namespaces: логическая изоляция и работа по умолчанию

    Namespace — логическая область внутри кластера. Многие ресурсы “живут” внутри namespace (Pod, Deployment, Service, ConfigMap), а некоторые — кластерные (Node, PersistentVolume, Namespace).

    Посмотреть namespaces и текущий namespace

    По умолчанию, если не указать namespace явно, kubectl использует namespace из текущего контекста kubeconfig (часто это default).

    Чтобы выполнять команду в конкретном namespace, используйте -n:

    Или полный флаг --namespace:

    Установить namespace по умолчанию для текущего контекста

    Это уменьшает риск случайно развернуть ресурсы “не туда”:

    Проверить:

    Быстрые проверки “почему я ничего не вижу?”

    Частая ситуация: ресурсы “пропали”, но на самом деле вы смотрите не в тот namespace.

    Минимальный набор команд:

    -A (или --all-namespaces) полезен для диагностики, но в ежедневной работе лучше явно указывать -n или выставить namespace в контексте.

    Контексты и kubeconfig: как не перепутать кластеры

    kubeconfig — конфигурационный файл, который говорит kubectl:

  • какие кластеры существуют (endpoint API, CA);
  • какие пользователи/учётные данные использовать (сертификаты, токены, exec-провайдер);
  • какие контексты доступны.
  • Контекст — связка:

  • cluster (куда подключаемся);
  • user (кем подключаемся);
  • namespace (куда по умолчанию смотрим и применяем ресурсы).
  • !Иллюстрация, как контекст связывает кластер, пользователя и namespace

    Посмотреть текущий контекст и список контекстов

    Переключиться:

    Выполнить одну команду в другом контексте, не переключая глобально:

    Где хранится kubeconfig и как объединять несколько файлов

    По умолчанию kubectl читает ~/.kube/config. Но часто у DevOps несколько конфигов (разные облака/кластеры).

    Варианты:

  • использовать переменную окружения KUBECONFIG со списком файлов;
  • временно указывать --kubeconfig.
  • Пример объединения через KUBECONFIG:

    Важно: в таком режиме kubectl склеивает конфиги при чтении. Чтобы сохранить “слитый” конфиг в файл, можно сделать так:

    Практики безопасности при работе с контекстами

  • Давайте контекстам говорящие имена: company-prod-admin, company-prod-readonly, company-stage-admin.
  • Для продакшена держите отдельный “read-only” доступ и используйте его по умолчанию.
  • Перед apply привыкайте проверять: kubectl config current-context и целевой namespace.
  • Базовые команды kubectl для диагностики

    Эти команды нужны каждый день, независимо от того, каким способом вы деплоите (CI/CD, GitOps или руками).

    Просмотр ресурсов

    Полезные флаги:

  • -o wide — больше колонок (нода, IP и т.д.)
  • -o yaml — посмотреть объект как YAML
  • --show-labels — увидеть labels
  • Пример:

    Подробности и события

    describe показывает состояние и события (Events), часто это самый быстрый путь понять проблему:

    События по namespace:

    Логи и выполнение команд внутри контейнера

    Логи контейнера:

    Если в Pod несколько контейнеров:

    Выполнить команду внутри контейнера:

    Проброс порта на локальную машину (удобно для отладки сервисов без Ingress):

    Манифесты Kubernetes: как устроены YAML-объекты

    Манифест — это декларативное описание ресурса, которое вы отправляете в Kubernetes API.

    Типовая структура YAML:

  • apiVersion — версия API-группы ресурса
  • kind — тип ресурса (Deployment, Service и т.д.)
  • metadata — имя, namespace, labels, annotations
  • spec — желаемое состояние (что Kubernetes должен поддерживать)
  • Минимальный пример Pod (для обучения, в продакшене обычно используют Deployment):

    Пояснения:

  • metadata.name — уникально внутри namespace.
  • metadata.labels — ключевой механизм выбора (selectors) для Service и контроллеров.
  • spec.containers[].image — образ контейнера.
  • containerPort — информационный порт (сам по себе не публикует сервис наружу).
  • Декларативный подход: apply, diff, dry-run

    В Kubernetes для управляемых сред почти всегда выбирают декларативный подход: “вот файл, сделай так”.

    apply: применить манифест

    Применить директорию с несколькими манифестами:

    dry-run: проверить без реального применения

    Полезно для CI и для самопроверки:

  • --dry-run=client означает, что проверка делается на стороне клиента (kubectl).
  • Вывод -o yaml помогает увидеть итоговый объект, который будет отправлен в API.
  • Для проверки на стороне API (с учётом admission-контроллеров и ограничений кластера) используйте:

    diff: увидеть, что изменится

    diff снижает риск неожиданного изменения: вы заранее видите различия между тем, что “в кластере”, и тем, что “в файлах”.

    Императивный подход и генерация манифестов

    Иногда быстрее создать ресурс командой, но при этом сохранить декларативность.

    Пример: сгенерировать YAML Deployment без применения:

    Дальше этот файл можно положить в репозиторий и применять через kubectl apply или GitOps.

    Практическое правило:

  • для обучения и быстрых экспериментов допустимы императивные команды;
  • для продакшена предпочитайте манифесты в репозитории и декларативное применение.
  • Как kubectl помогает “разобраться в API”: explain, api-resources, api-versions

    Когда вы видите новый ресурс или не помните поля — не обязательно гуглить.

    Посмотреть доступные ресурсы:

    Посмотреть версии API:

    Посмотреть схему ресурса (очень полезно при написании манифестов):

    Справка по командам:

    Паттерн “безопасного применения” в реальной работе

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

  • Проверьте контекст: kubectl config current-context.
  • Проверьте namespace: либо kubectl config view --minify, либо явно используйте -n.
  • Сделайте предварительный просмотр: kubectl diff -f ....
  • Выполните apply.
  • Проверьте rollout/состояние (для Deployment):
  • Что важно запомнить

  • kubectl работает через kubeconfig и контексты: контекст определяет кластер, пользователя и namespace по умолчанию.
  • Namespace влияет на большинство “обычных” ресурсов, поэтому -n и корректный namespace в контексте — базовая гигиена.
  • Манифесты — ваш основной интерфейс к Kubernetes: apiVersion, kind, metadata, spec.
  • Для безопасных изменений используйте kubectl diff и --dry-run.
  • kubectl explain и kubectl api-resources — быстрый способ понять API без лишнего поиска.
  • 3. Основные объекты: Pods, Deployments, Services, Ingress

    Основные объекты: Pods, Deployments, Services, Ingress

    В прошлых статьях курса мы закрепили две ключевые идеи:

  • Kubernetes управляется декларативно через API-объекты.
  • kubectl отправляет манифесты в API, а контроллеры приводят фактическое состояние к желаемому.
  • Теперь соберём “скелет” большинства продакшен-развёртываний: Pod, Deployment, Service, Ingress. Понимание их связки даёт вам 80% практики эксплуатации приложений в Kubernetes.

    Официальные источники:

  • Pods
  • Deployments
  • Service
  • Ingress
  • Как эти объекты связаны

    Типовой путь “описал — получил работающий HTTP-сервис” выглядит так:

  • Deployment поддерживает нужное число Pod (реплик) и обновляет их.
  • Service даёт стабильную точку доступа и балансирует трафик на Pod по labels/selectors.
  • Ingress маршрутизирует входящий HTTP/HTTPS-трафик на Service по правилам host/path.
  • !Связка Deployment → Pods, Service → Pods (по селекторам), Ingress → Service

    Дальше разберём каждый объект и затем соберём минимальный набор манифестов.

    Pod

    Pod — минимальная единица запуска в Kubernetes. Обычно это один контейнер приложения, но иногда внутри Pod живёт несколько контейнеров.

    Что важно про Pod в эксплуатации:

  • Pod эфемерен: его можно пересоздать, и он получит новый IP.
  • Pod обычно не создают “вручную” для продакшена: им управляет контроллер (например, Deployment).
  • Контейнеры внутри Pod разделяют сеть (один IP) и могут разделять тома (volumes).
  • Когда в Pod бывает несколько контейнеров

    Это полезно, когда рядом с приложением нужен вспомогательный процесс:

  • sidecar для проксирования (например, mTLS-прокси)
  • sidecar для доставки логов
  • контейнер-инициализатор (init container) для подготовки (миграции, прогрев кэша, ожидание зависимости)
  • Минимальный Pod-манифест (для обучения и отладки)

    Поля, которые важно понимать:

  • metadata.labels — метки, по которым Service и контроллеры “находят” Pod.
  • spec.containers[].ports[].containerPortописание порта контейнера (само по себе ничего наружу не публикует).
  • Полезные команды:

    Deployment

    Deployment — основной объект для stateless приложений (API, веб, воркеры без состояния на локальном диске).

    Deployment управляет:

  • количеством реплик (spec.replicas)
  • обновлением Pod (rolling update)
  • откатом на предыдущую версию
  • Технически Deployment создаёт и контролирует ReplicaSet, а ReplicaSet поддерживает нужное число Pod.

    Важные части Deployment-манифеста

    Ниже пример, который уже похож на реальную эксплуатацию: есть реплики и readiness-probe (проверка готовности).

    Ключевые моменты:

  • spec.selector.matchLabels должен соответствовать spec.template.metadata.labels.
  • readinessProbe влияет на то, будет ли Pod считаться “готовым” для получения трафика через Service.
  • Обновление образа (image) обычно приводит к rolling update.
  • Практика управления Deployment

    Проверить состояние:

    Посмотреть прогресс обновления:

    Сделать откат:

    Service

    Service решает главную сетевую проблему Kubernetes: Pod’ы “смертны” и их IP меняются. Service даёт стабильную точку доступа к группе Pod.

    Service делает две вещи:

  • создаёт стабильный виртуальный адрес и DNS-имя внутри кластера
  • распределяет трафик на Pod, выбранные по selector
  • Как Service выбирает Pod

    Service использует spec.selector и сопоставляет его с metadata.labels Pod.

    Практический вывод: если метки не совпали, у Service не будет “живых” backend’ов.

    Типы Service

    Чаще всего вы встретите:

  • ClusterIP — доступен только внутри кластера (тип по умолчанию)
  • NodePort — открывает порт на каждой ноде
  • LoadBalancer — создаёт внешний балансировщик у облачного провайдера (если интеграция настроена)
  • Пример Service для Deployment из примера выше

    Как читать ports:

  • port — порт Service (на который ходят клиенты внутри кластера)
  • targetPort — порт на Pod (контейнер), куда реально пойдёт трафик
  • Диагностика Service

    Проверить Service и его “подключения” к Pod:

    Проверить, нашлись ли endpoints (то есть конкретные Pod’ы):

    Если endpoints пустые, почти всегда причина одна из двух: неправильный selector или Pod не Ready.

    !Как Service даёт стабильную сеть поверх меняющихся Pod

    Ingress

    Ingress — это правила L7-маршрутизации (обычно HTTP/HTTPS): по какому домену и пути отправлять запросы в какой Service.

    Критически важное уточнение:

  • Ingress — это объект с правилами.
  • Чтобы эти правила работали, в кластере должен быть установлен Ingress Controller (например, NGINX Ingress Controller, Traefik и т.д.).
  • Без контроллера Ingress-объекты будут создаваться, но реального входа снаружи не появится.

    IngressClass

    В современном Kubernetes часто используется ingressClassName, чтобы указать, какой контроллер должен обслуживать Ingress.

    Пример Ingress, который ведёт на Service demo-web

    Как это работает:

  • клиент приходит на demo.example.com/
  • Ingress Controller принимает запрос (обычно имеет внешний адрес)
  • по правилу отправляет его в Service demo-web
  • Service балансирует запрос на один из Pod
  • Диагностика:

    Частая причина “Ingress не работает”: Ingress Controller не установлен, либо ingressClassName не соответствует имеющемуся классу.

    Минимальный набор манифестов “приложение наружу”

    Ниже практический порядок действий, который стыкуется с тем, что вы уже делали в статье про kubectl apply/diff/dry-run.

  • Создайте namespace (если нужно):
  • Сохраните три файла (Deployment, Service, Ingress) в директорию manifests/ и проверьте изменения:
  • Примените манифесты:
  • Убедитесь, что Deployment успешно развернулся:
  • Проверьте Service и endpoints:
  • Проверьте Ingress и адрес контроллера (если контроллер установлен):
  • Если Ingress Controller не настроен, для проверки приложения всё равно можно временно использовать port-forward:

    После этого приложение будет доступно на http://localhost:8080.

    Типовые ошибки и как их быстро распознать

  • Service не отправляет трафик никуда: у Service пустые endpoints.
  • Pod живой, но трафик не идёт: Pod не Ready (смотрите readinessProbe и события в describe).
  • Ingress создан, но снаружи не доступен: нет Ingress Controller или неверный ingressClassName.
  • Всё “пропало”: вы в неправильном контексте или namespace (проверяйте kubectl config current-context и -n).
  • Что важно запомнить

  • Pod — единица запуска, но в продакшене его почти всегда “держит” контроллер.
  • Deployment — стандарт для stateless: реплики, rolling update, rollback.
  • Service — стабильный адрес и балансировка на Pod по labels/selectors.
  • Ingress — HTTP/HTTPS-правила маршрутизации на Service, но требует установленный Ingress Controller.
  • Следующий логичный шаг (в рамках подготовки к продакшену) — углубиться в конфигурацию приложений (ConfigMap/Secret), probes, ресурсы (requests/limits) и практики безопасных обновлений.

    4. Хранение данных и конфигурация: PV/PVC, ConfigMap, Secret

    Хранение данных и конфигурация: PV/PVC, ConfigMap, Secret

    В предыдущих статьях мы собрали основу развёртывания приложений в Kubernetes: Deployment управляет репликами Pod, Service даёт стабильную сеть, Ingress добавляет входящий HTTP/HTTPS. Следующий шаг к продакшену — правильно работать с данными и конфигурацией.

    В Kubernetes важно разделять:

  • данные приложения, которые должны переживать пересоздание Pod и перенос на другую ноду
  • конфигурацию (нечувствительную) и секреты (чувствительную), которые должны быть управляемы и безопасны
  • Официальные источники:

  • Volumes
  • Persistent Volumes
  • Storage Classes
  • ConfigMaps
  • Secrets
  • Почему нельзя полагаться на файловую систему контейнера

    Файлы внутри контейнера живут в файловой системе Pod, которая по умолчанию эфемерна:

  • Pod может быть пересоздан (обновление Deployment, падение контейнера, переселение на другую ноду)
  • при пересоздании локальные файлы обычно теряются
  • даже если файлы сохранились на ноде, Kubernetes не обязан вернуть Pod на ту же ноду
  • Отсюда практическое правило:

  • всё, что должно сохраняться (база данных, очередь, загрузки пользователей, кэш с требованием сохранности) — через персистентное хранилище
  • всё, что является конфигурацией — через ConfigMap
  • всё, что является секретом — через Secret
  • Хранение данных: Volumes, PV, PVC, StorageClass

    Базовые определения

  • Volume — способ подключить хранилище в Pod. Volume может быть временным (например, emptyDir) или постоянным.
  • PersistentVolume (PV) — ресурс кластера, который представляет конкретный “кусок” хранилища.
  • PersistentVolumeClaim (PVC) — запрос на хранилище со стороны приложения.
  • StorageClass — шаблон, по которому кластер умеет динамически выдавать PV под PVC.
  • Главная идея для DevOps: приложение почти всегда работает с PVC, а не с PV напрямую.

    !Как PVC связывает приложение с PV через StorageClass

    Как происходит привязка PVC к PV

    Когда вы создаёте PVC, Kubernetes пытается удовлетворить запрос:

  • Если в кластере уже есть подходящий PV, он будет привязан к PVC.
  • Если указан storageClassName и включено динамическое выделение, Kubernetes создаст новый PV через StorageClass.
  • Если подходящего PV нет и динамика не настроена, PVC останется в состоянии Pending.
  • Проверочные команды:

    StorageClass и динамическое выделение

    StorageClass описывает:

  • какой драйвер хранилища использовать (обычно через CSI)
  • какие параметры нужны (тип диска, репликация, IOPS и т.д. — зависит от провайдера)
  • политику выделения и иногда — возможность расширения тома
  • Частый сценарий: в кластере есть StorageClass по умолчанию. Тогда PVC можно создать, не указывая storageClassName, и он возьмёт default-класс.

    Доступы к томам: AccessModes

    В PVC (и PV) вы увидите accessModes. Это заявление о том, как том может быть примонтирован:

  • ReadWriteOnce — том доступен на запись, обычно “с одной ноды” (частый вариант для облачных дисков)
  • ReadOnlyMany — чтение с нескольких мест
  • ReadWriteMany — запись с нескольких мест (часто требует NFS/файловые системы, или специфичные storage-решения)
  • Практическая связь с эксплуатацией:

  • если у вас Deployment с несколькими репликами и один PVC с ReadWriteOnce, то одновременная запись из нескольких Pod часто невозможна или приведёт к проблемам планирования
  • для “общей папки” между репликами чаще нужен ReadWriteMany или другой паттерн (например, объектное хранилище вне кластера)
  • Что будет с данными при удалении PVC: Reclaim Policy

    У PV есть политика “что делать с физическим хранилищем, если PVC удалили”. Это зависит от PV/StorageClass и реализации провайдера.

    На практике встречаются:

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

    Практика: минимальный PVC и Deployment с томом

    Ниже пример PVC на 1Gi и Deployment, который пишет данные в /data. Такой шаблон часто используется для stateful-компонентов, но и для stateless приложений бывает полезен, если им нужен небольшой “переживающий рестарт” каталог.

    PVC

    Пояснения:

  • resources.requests.storage — сколько места вы запрашиваете
  • storageClassName — какой класс хранилища использовать (имя должно существовать в кластере)
  • Deployment, который монтирует PVC

    Проверка:

    Если Pod не стартует, смотрите:

    ConfigMap: управляемая конфигурация без секретов

    ConfigMap предназначен для конфигурации, которая не является чувствительной:

  • переменные окружения (например, LOG_LEVEL, FEATURE_FLAG)
  • конфиги приложений (например, app.yaml, nginx.conf)
  • Важно: ConfigMap — это API-объект. Его удобно хранить в репозитории как YAML, изменять через PR и применять декларативно.

    Способы использования ConfigMap

    Основные варианты:

  • передать значения как переменные окружения
  • смонтировать как файлы в контейнер
  • Пример ConfigMap

    ConfigMap как переменные окружения

    Нюанс эксплуатации: значения окружения “впекаются” в Pod при создании. При изменении ConfigMap Pod сам по себе не перезапустится.

    Обычно делают управляемый рестарт:

    ConfigMap как файлы

    Если смонтировать ConfigMap как volume, Kubernetes создаст файлы (по ключам) внутри каталога.

    Практический плюс: файл может обновляться без пересоздания Pod (зависит от того, как приложение читает конфиг). Но многие приложения всё равно требуют reload или рестарт.

    Immutable ConfigMap

    Если конфигурация должна быть неизменяемой (безопасность, предсказуемость релизов), можно включить immutable: true.

    Ссылка: ConfigMaps

    Secret: чувствительные данные

    Secret — объект Kubernetes для хранения чувствительных данных:

  • пароли
  • токены
  • ключи
  • сертификаты
  • Ключевой нюанс: Secret в Kubernetes не является “магически защищённым” сам по себе. Он требует правильной настройки доступа и хранения.

    Важные свойства Secret

  • Secret хранится в etcd и обычно представлен как base64 в YAML. Base64 — это не шифрование.
  • доступ к Secret нужно ограничивать через RBAC
  • в продакшене часто включают шифрование данных в etcd на уровне API Server
  • Документация:

  • Secrets
  • Encrypting Secret Data at Rest
  • Пример Secret (с использованием stringData)

    Поле stringData удобно тем, что вы пишете обычные строки, а Kubernetes сам преобразует их в нужный формат.

    Нюансы эксплуатации:

  • не коммитьте реальные секреты в Git, если репозиторий не предназначен для этого
  • чаще используют внешние системы (Vault, облачные Secret Manager) и механизмы доставки секретов в кластер
  • Secret как переменные окружения

    Риск: переменные окружения проще “случайно засветить” в логах или при отладке. На практике нередко предпочитают монтирование в файлы.

    Secret как файлы

    Сборка вместе: PVC + ConfigMap + Secret в одном приложении

    Ниже пример “типовой продакшен-связки” для приложения:

  • PVC для данных
  • ConfigMap для настроек
  • Secret для пароля
  • Запуск и проверка:

    !Как PVC, ConfigMap и Secret подключаются в Pod

    Типовые проблемы и диагностика

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

    Частые причины:

  • неверный storageClassName
  • в кластере нет StorageClass по умолчанию и вы не указали класс
  • нет провиженера (CSI-драйвера) или он не работает
  • Диагностика:

    Pod не стартует из-за тома

    Признаки:

  • Pod “зависает” в ContainerCreating
  • в describe pod видно ошибки mount
  • Команды:

    Service работает, но приложение “не видит конфиг”

    Частые причины:

  • вы смонтировали ConfigMap не туда, куда приложение читает
  • ключи ConfigMap не совпадают с ожидаемыми именами файлов
  • приложение читает конфиг только при старте и требует перезапуска
  • Секреты “утекли” в логи или в вывод отладки

    Практические правила:

  • не выводите секреты в логах
  • предпочитайте readOnly: true для монтирования Secret
  • ограничивайте доступ к Secret через RBAC
  • включайте шифрование в etcd, если это ваша зона ответственности
  • Что важно запомнить

  • PVC — основной интерфейс приложения к персистентному хранилищу; PV обычно управляется кластером/провайдером.
  • StorageClass включает динамическое выделение томов и задаёт свойства хранилища.
  • AccessModes критичны для дизайна: один PVC не всегда можно безопасно использовать для нескольких реплик.
  • ConfigMap — для несекретной конфигурации; Secret — для чувствительных данных, но безопасность зависит от RBAC и хранения.
  • Изменение ConfigMap/Secret не гарантирует автоматический рестарт Pod: для контролируемого обновления часто используют kubectl rollout restart или более продвинутые механизмы деплоя.
  • 5. Сеть и DNS в кластере: CNI, Service discovery, NetworkPolicy

    Сеть и DNS в кластере: CNI, Service discovery, NetworkPolicy

    В предыдущих статьях курса мы уже использовали Service и Ingress как “сетевой фасад” для ваших приложений. Теперь разберём, почему это работает и что находится под капотом: как Kubernetes организует сеть между Pod’ами и нодами, как работает DNS и Service discovery, и как вводить сетевую изоляцию с помощью NetworkPolicy.

    Полезные первоисточники:

  • Cluster Networking
  • Services, Load Balancing, and Networking
  • DNS for Services and Pods
  • Network Policies
  • CNI Specification
  • CoreDNS
  • Сетевая модель Kubernetes: базовые обещания

    Kubernetes придерживается модели “каждый Pod имеет свой IP”, и сеть должна вести себя предсказуемо.

    Основные ожидания (инварианты) от сети кластера:

  • Каждый Pod получает свой IP-адрес.
  • Pod’ы на разных нодах могут общаться друг с другом напрямую, без NAT между Pod’ами.
  • Агент на ноде (kubelet) и компоненты сети обеспечивают, чтобы маршрутизация до Pod IP работала.
  • Service даёт стабильную точку доступа к группе Pod’ов, потому что Pod IP эфемерны.
  • !Как Pod IP, Node и Service связаны в сетевой модели Kubernetes

    CNI: как в Pod появляется сеть

    CNI (Container Network Interface) — это стандарт, по которому Kubernetes (через runtime и kubelet) подключает сеть контейнерам.

    Что делает CNI-плагин в практическом смысле:

  • Выдаёт Pod’у IP-адрес.
  • Настраивает сетевой интерфейс в Pod (обычно eth0).
  • Обеспечивает маршрутизацию между Pod’ами на одной ноде и на разных нодах.
  • Часто (в зависимости от реализации) отвечает за применение NetworkPolicy.
  • Важно различать роли:

  • CNI отвечает за соединяемость Pod-to-Pod.
  • kube-proxy (или замена в некоторых CNI) отвечает за виртуализацию Service (как трафик на Service попадёт на конкретные Pod).
  • Основные подходы CNI к межнодовой связности

    Вам не обязательно знать внутренности каждого решения, но полезно понимать, что есть разные методы:

  • Оверлей-сеть: Pod’ы соединяются через туннелирование (часто проще в установке).
  • Роутинг на L3: ноды обмениваются маршрутами до Pod CIDR (часто более “прозрачно” и эффективно).
  • eBPF-подход: часть логики (включая сервисную балансировку и политики) реализуется через eBPF, уменьшая зависимость от iptables.
  • Примеры популярных реализаций:

  • Calico
  • Cilium
  • Flannel
  • Kubernetes специально не навязывает конкретный CNI: сеть — это “плагинная” зона.

    Service внутри кластера: что именно происходит с трафиком

    Вы уже применяли Service, но теперь посмотрим на его ключевые свойства с точки зрения эксплуатации.

    Service — это VIP + набор backend’ов

    Для клиентов Service выглядит как стабильная точка доступа:

  • ClusterIP (виртуальный IP внутри кластера)
  • DNS-имя (например, api.default.svc.cluster.local)
  • А фактические backend’ы формируются из Pod’ов:

  • по spec.selector (labels/selectors)
  • и только тех, кто находится в состоянии Ready
  • Практическое следствие:

  • Если “Service не работает”, первое что проверяют — Endpoints/EndpointSlice.
  • Команды диагностики:

    kube-proxy и реализация Service

    Во многих кластерах за Service отвечает kube-proxy. Он программирует правила на нодах (iptables или IPVS), чтобы:

  • запрос на ClusterIP:port перенаправлялся на один из Pod IP:targetPort
  • балансировка шла по доступным endpoint’ам
  • Если kube-proxy отсутствует или работает неправильно, у вас часто будут симптомы:

  • DNS имя Service резолвится, но подключение зависает или даёт Connection timed out
  • endpoint’ы есть, но трафик не проходит
  • При этом часть современных CNI может брать роль сервисной балансировки на себя, но с точки зрения пользователя результат один: Service должен маршрутизироваться на Pod’ы.

    Service discovery: как приложения находят друг друга

    В Kubernetes есть два основных способа, как один компонент “находит” другой.

    Service discovery через DNS (основной способ)

    Kubernetes поднимает DNS внутри кластера (обычно CoreDNS) и автоматически создаёт DNS-записи для Service.

    Типичные имена:

  • my-svc (в пределах того же namespace)
  • my-svc.my-namespace
  • my-svc.my-namespace.svc
  • my-svc.my-namespace.svc.cluster.local
  • Правило практики:

  • Внутри одного namespace чаще всего достаточно короткого имени Service.
  • Для кросс-namespace обращений используйте service.namespace.
  • Проверка изнутри кластера:

    Service discovery через переменные окружения (реже используется)

    Kubernetes может инжектировать переменные окружения с адресами Service в Pod при старте (например, MY_SVC_SERVICE_HOST).

    Ограничения:

  • Переменные окружения формируются при создании Pod и не обновляются динамически.
  • DNS обычно гибче и привычнее.
  • DNS в Kubernetes: CoreDNS, search domains и частые проблемы

    Что такое CoreDNS и где он живёт

    Обычно DNS-сервис кластера реализован CoreDNS и работает в namespace kube-system.

    Проверочные команды:

    Как выглядит DNS-конфигурация внутри Pod

    Внутри Pod обычно настроены:

  • DNS-сервер: это ClusterIP сервиса kube-dns
  • search домены: чтобы можно было писать короткие имена
  • Примерный вид /etc/resolv.conf внутри Pod:

    Здесь:

  • nameserver — IP DNS внутри кластера
  • search — список суффиксов, которые будут подставляться при резолвинге коротких имён
  • ndots — правило, когда имя считается “достаточно полным” и перестают активно добавляться search-суффиксы
  • Практическая проблема, которую важно знать:

  • Большое ndots иногда приводит к неожиданным задержкам DNS, когда приложение активно резолвит внешние домены (Kubernetes сначала пытается резолвить их с добавлением внутренних search-суффиксов).
  • Headless Service и прямой доступ к Pod IP

    Обычный Service даёт один ClusterIP и балансирует трафик. Но иногда нужно получить список Pod IP напрямую.

    Headless Service — это Service с clusterIP: None.

  • DNS для такого Service обычно возвращает A-записи на конкретные Pod IP.
  • Часто используется вместе со StatefulSet, где важны стабильные имена.
  • Ссылка: механика описана в DNS for Services and Pods.

    Быстрый чек-лист, если “DNS сломан”

  • Проверить, что Pod вообще видит DNS-сервер:
  • Проверить резолвинг системного имени:
  • Проверить, что CoreDNS жив и есть endpoints у kube-dns:
  • Если DNS резолвит, но трафик до Service не идёт, переходите к проверке endpoint’ов самого Service и сетевых политик.
  • NetworkPolicy: управление доступом между Pod’ами

    По умолчанию в Kubernetes сетевое взаимодействие между Pod’ами обычно разрешено (модель “flat network”). Чтобы ограничивать доступ, используют NetworkPolicy.

    Ключевые понятия:

  • NetworkPolicy — декларативные правила L3/L4 (IP/порт) для трафика между Pod’ами.
  • Правила применяются к Pod’ам, выбранным через podSelector.
  • Правила могут описывать ingress (входящий) и egress (исходящий) трафик.
  • Критически важный нюанс эксплуатации:

  • NetworkPolicy работает только если ваш CNI это поддерживает.
  • Если CNI не поддерживает NetworkPolicy, объекты будут создаваться в API, но фактических ограничений не появится.
  • Ссылка: Network Policies.

    Ментальная модель: политики добавляются, а не заменяют друг друга

    NetworkPolicy действует “добавочно”:

  • Если на Pod не выбрано ни одной NetworkPolicy, обычно действует режим “allow all”.
  • Как только Pod попадает под действие политики с policyTypes: [Ingress], входящий трафик становится “deny by default” кроме явно разрешённого.
  • Аналогично для Egress.
  • Пример: запретить весь входящий трафик в namespace (default deny ingress)

    Это базовый шаг к изоляции. Политика выбирает все Pod’ы в namespace (пустой podSelector) и не разрешает ingress ни откуда.

    После применения:

  • вход к Pod’ам в dev будет закрыт, пока вы не добавите разрешающие правила
  • исходящий трафик (egress) при этом останется разрешённым, потому что мы не включали Egress
  • Пример: разрешить доступ к app=api только от app=web внутри namespace

    Сценарий: у вас есть два Deployment в одном namespace: web и api. Вы хотите, чтобы api принимал трафик только от web.

    Как читать:

  • podSelector выбирает цель политики: Pod’ы app=api
  • from описывает источник: Pod’ы app=web в том же namespace
  • ports ограничивает порты: только TCP/8080
  • Пример: ограничить исходящий трафик (egress) только к DNS и к базе данных

    Egress-контроль важен, когда вы хотите уменьшить риск утечек и ограничить “куда может сходить” скомпрометированный Pod.

    Ниже пример идеи (его нужно адаптировать под ваши labels и адреса):

    Практические нюансы:

  • Разрешите DNS (53/UDP и иногда 53/TCP), иначе приложение может “сломаться” из-за невозможности резолва.
  • Селекторы namespaceSelector и podSelector работают вместе: это удобно, но требует аккуратных labels.
  • Типовые сценарии в продакшене

    Изоляция по namespace

    Частый паттерн:

  • В каждом namespace включают default deny ingress.
  • Дальше точечно разрешают нужные связи “сервис к сервису”.
  • Это дисциплинирует: любые новые взаимодействия должны быть описаны декларативно.

    Защита внутренних компонентов

  • Метрики (например, /metrics) часто должны быть доступны только мониторингу.
  • Админские интерфейсы должны быть закрыты от общего трафика.
  • NetworkPolicy помогает выразить это на сетевом уровне, не полагаясь только на приложение.

    Ограничение egress

  • Разрешать выход только в конкретные внешние зависимости.
  • Запрещать прямой выход в интернет для внутренних сервисов.
  • На практике egress-политики требуют больше внимания, потому что легко случайно заблокировать системные зависимости (DNS, NTP, доступ к API серверам облака, sidecar’ы, агенты).

    Диагностика сетевых проблем: порядок действий

    Когда “что-то не работает”, важно быстро сузить область.

    Рекомендуемый порядок:

  • Проверить Pod и его готовность (иначе Service не будет иметь endpoint’ов):
  • Проверить Service и endpoints:
  • Проверить DNS изнутри Pod:
  • Проверить сетевую политику:
  • Если проблема на уровне кластера, проверить CoreDNS и kube-proxy (или соответствующие компоненты CNI):
  • Что важно запомнить

  • CNI обеспечивает Pod IP и связность Pod-to-Pod. Kubernetes полагается на CNI для сетевой “основы”.
  • Service даёт стабильную точку доступа к группе Pod’ов; его работоспособность почти всегда проверяется через endpoints/endpointslices.
  • DNS (обычно CoreDNS) — главный механизм service discovery; “короткие имена” работают благодаря search domains.
  • NetworkPolicy — сетевые ограничения L3/L4, которые работают только при поддержке со стороны CNI; политики включают режим “deny by default” для выбранных Pod’ов.
  • В следующих темах курса (приближаясь к продакшену) логично соединить сеть с безопасностью и эксплуатацией: RBAC для доступа к API, Ingress/TLS, а также практики наблюдаемости (метрики, логи, трассировка), которые сильно зависят от корректной сетевой и DNS-конфигурации.

    6. Безопасность и доступ: RBAC, ServiceAccounts, Pod Security

    Безопасность и доступ: RBAC, ServiceAccounts, Pod Security

    Kubernetes из предыдущих тем курса уже выглядит как рабочая платформа: вы деплоите приложения через Deployment, открываете доступ через Service/Ingress, подключаете конфигурацию через ConfigMap/Secret и умеете диагностировать сеть и DNS. Но до продакшена не хватает ключевого слоя: контроль доступа и безопасность выполнения Pod.

    В этой статье разберём три опорные темы:

  • RBAC: кто и что может делать в Kubernetes API
  • ServiceAccount: кем является Pod при обращении к API
  • Pod Security: какие “опасные” параметры Pod запрещать или ограничивать
  • Официальные источники:

  • RBAC Authorization
  • Service Accounts
  • Configure Service Accounts for Pods
  • Pod Security Standards
  • Pod Security Admission
  • Security Context for a Pod or Container
  • Ментальная модель безопасности Kubernetes

    Безопасность в Kubernetes удобно раскладывается на два контура:

  • Доступ к Kubernetes API
  • - Аутентификация: кто ты? - Авторизация: что тебе разрешено? (здесь основной механизм — RBAC)
  • Безопасность запуска workload
  • - Что именно Pod может делать на ноде: привилегии, capabilities, запуск от root, hostNetwork и т.д. - В современных кластерах это обычно контролируется через Pod Security Admission и настройки securityContext

    Связь с предыдущими статьями:

  • Даже идеально написанные манифесты и сетевые политики не спасут, если у Pod есть избыточные права в API или он может запуститься как privileged.
  • NetworkPolicy ограничивает сетевое взаимодействие Pod-to-Pod, а RBAC ограничивает “управленческое” взаимодействие с API. Это разные уровни контроля.
  • !Диаграмма показывает, как запрос проходит через аутентификацию и RBAC-авторизацию

    RBAC: как Kubernetes решает, что вам можно

    RBAC (Role-Based Access Control) — механизм авторизации Kubernetes. Он определяет, какие действия (verbs) разрешены над какими ресурсами (resources) в каких областях (namespace или весь кластер).

    Базовые сущности RBAC

  • Role: набор правил в рамках одного namespace
  • ClusterRole: набор правил на уровне всего кластера (или как “шаблон”, который можно привязать и в namespace)
  • RoleBinding: привязка Role или ClusterRole к субъекту в конкретном namespace
  • ClusterRoleBinding: привязка ClusterRole к субъекту на уровне кластера
  • Субъекты, которым выдаются права:

  • user (внешний пользователь)
  • group (группа)
  • ServiceAccount (учётка для Pod)
  • Из чего состоит правило

    Правило RBAC описывается четырьмя главными измерениями:

  • apiGroups: API-группа ресурса (например, "" для core/v1, apps для Deployments)
  • resources: какие ресурсы (например, pods, deployments, secrets)
  • verbs: какие действия (например, get, list, watch, create, update, patch, delete)
  • опционально resourceNames: ограничение на конкретные имена объектов
  • Практическое правило: выдавайте минимально необходимые права (principle of least privilege).

    Минимальный пример: read-only доступ к Pod в namespace

    Role в namespace dev:

    RoleBinding, который выдаёт эти права ServiceAccount app в dev:

    Пояснения:

  • Role ограничен namespace dev, поэтому даже если ServiceAccount скомпрометирован, радиус ограничен.
  • verbs только чтение, без create/update/delete.
  • Когда нужен ClusterRole

    Типовые случаи для ClusterRole:

  • чтение кластерных ресурсов (например, nodes, persistentvolumes)
  • системные компоненты (ingress-controller, CNI, CSI, мониторинг), которым нужны права в разных namespace
  • когда нужно выдать одинаковый набор прав многим namespace через RoleBinding на ClusterRole
  • В продакшене важно отличать:

  • “кластер-админ” права (очень опасно выдавать приложениям)
  • узкие ClusterRole для конкретной функции
  • Как проверить, что доступ действительно ограничен

    Команда kubectl auth can-i — быстрый способ проверить RBAC:

    Проверка “от имени ServiceAccount”:

    Полезная расшифровка формата:

  • system:serviceaccount:<namespace>:<name> — каноническое имя ServiceAccount
  • ServiceAccount: идентичность Pod при доступе к API

    ServiceAccount (SA) — это учётная запись внутри Kubernetes, которую используют Pod’ы для обращения к kube-apiserver.

    Что происходит по умолчанию

  • В каждом namespace есть ServiceAccount default.
  • Если в Pod не указан serviceAccountName, он использует default.
  • Kubernetes может примонтировать токен ServiceAccount внутрь Pod, чтобы приложение могло ходить в API.
  • Практический риск: если вы случайно выдали права default ServiceAccount, их автоматически получат все Pod без явного serviceAccountName.

    Рекомендуемая практика

  • Создавайте отдельный ServiceAccount на приложение или на класс приложений.
  • Не выдавайте права “на всякий случай”.
  • Там, где приложению не нужен доступ к API, отключайте автомонтирование токена.
  • Пример: ServiceAccount и запрет автомонтирования токена

    Создадим ServiceAccount с отключённым автомонтированием:

    Подключим его в Deployment:

    Пояснения:

  • automountServiceAccountToken: false уменьшает поверхность атаки: украсть токен из контейнера становится сложнее, потому что его нет.
  • Если приложению нужен доступ к API, автомонтирование можно включить, но тогда RBAC должен быть строго минимальным.
  • ServiceAccount и Secrets

    ServiceAccount часто используется вместе с Secret:

  • Для доступа Pod к API — токен ServiceAccount
  • Для доступа Pod к внешним системам — ваши прикладные токены в Secret
  • Важно не смешивать эти роли: токен ServiceAccount — это “ключ” к Kubernetes API, а не универсальный секрет для приложения.

    Pod Security: как ограничить опасные возможности Pod

    Даже если у приложения нет прав в Kubernetes API (RBAC), оно всё ещё может быть опасным на уровне ноды, если Pod запускается с избыточными привилегиями.

    Pod Security Standards

    Kubernetes описывает три уровня требований безопасности:

  • privileged: почти без ограничений (обычно только для системных компонентов)
  • baseline: базовая защита от очевидно опасных настроек
  • restricted: строгий профиль (как правило, предпочтителен для обычных приложений)
  • Источник: Pod Security Standards

    Pod Security Admission

    Pod Security Admission (PSA) — встроенный admission-контроллер, который применяет Pod Security Standards через labels namespace.

    Источник: Pod Security Admission

    Ключевая идея:

  • Вы маркируете namespace лейблами уровня политики.
  • API сервер при создании/обновлении Pod (и контроллеров, создающих Pod) проверяет соответствие.
  • Основные режимы PSA:

  • enforce: запрещать несоответствующие Pod
  • audit: не запрещать, но писать события
  • warn: не запрещать, но предупреждать клиента
  • Пример: включить baseline в enforce для namespace

    Практика внедрения в продакшене обычно постепенная:

  • Сначала включают warn и audit, чтобы увидеть, что сломается.
  • Исправляют манифесты и образы.
  • Переводят в enforce.
  • Что чаще всего нарушает restricted/baseline

    Типовые “опасные” настройки Pod:

  • privileged: true
  • hostNetwork: true, hostPID: true, hostIPC: true
  • монтирование чувствительных hostPath
  • запуск контейнера от root без необходимости
  • отсутствие readOnlyRootFilesystem, когда это возможно
  • allowPrivilegeEscalation: true
  • securityContext: как сделать Pod совместимым с restricted

    Помимо политик на уровне namespace, вы почти всегда настраиваете securityContext в Pod/Container.

    Источник: Security Context

    Минимальный шаблон “безопаснее по умолчанию”

    Пример фрагмента для контейнера:

    Пояснения:

  • runAsNonRoot: true требует, чтобы процесс в контейнере не был root.
  • allowPrivilegeEscalation: false запрещает повышение привилегий внутри контейнера.
  • capabilities.drop: ["ALL"] убирает Linux capabilities (добавлять стоит точечно и осознанно).
  • readOnlyRootFilesystem: true уменьшает риск модификации файловой системы контейнера (если приложению нужен write-доступ, используйте volume).
  • Практический нюанс: некоторые образы по умолчанию запускаются от root. В таком случае нужно либо использовать “non-root” вариант образа, либо задать runAsUser и убедиться, что файловые права внутри образа это позволяют.

    Как это собрать в понятную эксплуатационную модель

    Ниже рабочий “чек-лист” для DevOps-практики, который связывает темы курса.

    Для доступа к API

  • Для людей и CI/CD:
  • - выдавайте отдельные kubeconfig/учётки - ограничивайте права RBAC до нужного namespace и нужных ресурсов
  • Для приложений:
  • - отдельный ServiceAccount на workload - права только на то, что действительно нужно - отключайте автомонтирование токена там, где доступ к API не нужен

    Для запуска workload

  • Включайте PSA на namespace:
  • - начните с warn/audit, затем enforce
  • Стандартизируйте securityContext в Helm chart или базовых манифестах
  • Сочетайте с NetworkPolicy из прошлой статьи:
  • - PSA/RBAC ограничивают “внутреннюю” опасность - NetworkPolicy ограничивает сетевую связность

    Типовые ошибки и быстрая диагностика

  • Ошибка доступа (Forbidden) при kubectl или внутри приложения:
  • - проверьте RBAC: kubectl auth can-i ... - проверьте, какой ServiceAccount использует Pod: kubectl get pod -n <ns> <pod> -o yaml
  • Pod не создаётся из-за политики безопасности:
  • - смотрите события: kubectl get events -n <ns> --sort-by=.lastTimestamp - проверьте labels namespace для PSA
  • Случайно “раздали админа” приложению:
  • - ищите ClusterRoleBinding на cluster-admin - проверьте права default ServiceAccount

    Что важно запомнить

  • RBAC отвечает на вопрос “что можно делать в Kubernetes API” и выражается через Role/ClusterRole и (Cluster)RoleBinding.
  • ServiceAccount — идентичность Pod для обращения к API; по умолчанию Pod использует default, что может быть опасно.
  • Pod Security защищает ноды и кластер от опасных параметров Pod; современный путь — Pod Security Admission + стандартизированный securityContext.
  • В продакшене безопасность — это слой поверх всего, что вы изучили ранее: деплой, сеть, конфигурация и наблюдаемость должны жить в рамках чётких политик доступа.
  • 7. Эксплуатация и продакшен: autoscaling, observability, upgrades, backup

    Эксплуатация и продакшен: autoscaling, observability, upgrades, backup

    Вы уже умеете деплоить приложения через Deployment, публиковать их через Service и Ingress, подключать конфигурацию через ConfigMap и Secret, работать с PV и ограничивать сетевой доступ через NetworkPolicy и права через RBAC. В продакшене этого недостаточно: кластер нужно масштабировать, наблюдать, обновлять и восстанавливать.

    Эта статья соединяет предыдущие темы в практическую эксплуатационную модель:

  • Autoscaling: как автоматически масштабировать приложения и сам кластер
  • Observability: как видеть состояние, находить причины инцидентов и строить алерты
  • Upgrades: как безопасно обновлять кластер и workloads
  • Backup: что и как бэкапить, чтобы восстановление было реальным, а не теоретическим
  • Полезные первоисточники:

  • Horizontal Pod Autoscaler
  • Vertical Pod Autoscaler
  • Cluster Autoscaler
  • Metrics Server
  • Logging Architecture
  • Debug Running Pods
  • Ephemeral Containers
  • Safely Drain a Node
  • Kubernetes Version Skew Policy
  • Backup an etcd cluster
  • Volume Snapshots
  • Velero
  • Autoscaling

    Autoscaling в Kubernetes почти всегда упирается в три вопроса:

  • какую метрику считать сигналом нагрузки
  • что именно масштабировать
  • есть ли у платформы ресурсы, чтобы новое масштабирование реально произошло
  • В Kubernetes обычно используют три уровня масштабирования:

  • HPA: масштабирует количество Pod
  • VPA: подбирает requests и limits для контейнеров
  • Cluster Autoscaler: масштабирует количество нод
  • !Как три уровня autoscaling связаны между собой

    Базовые требования перед включением autoscaling

    Если не соблюсти эти требования, autoscaling будет либо нестабилен, либо бесполезен.

  • В манифестах workload должны быть заданы resources.requests (как минимум CPU), иначе планировщик и autoscaler принимают решения вслепую.
  • В кластере должен быть источник метрик.
  • - Для HPA по CPU и memory обычно нужен Metrics Server. - Для кастомных метрик чаще используют Prometheus-экосистему, но это отдельная инженерная задача.

    HPA: Horizontal Pod Autoscaler

    HPA увеличивает или уменьшает spec.replicas у Deployment, StatefulSet или ReplicaSet, опираясь на метрики.

    Ключевые особенности:

  • HPA работает в цикле согласования: периодически смотрит метрики и корректирует число реплик.
  • HPA опирается на readiness: неготовые Pod не должны становиться backend для Service, поэтому корректные readinessProbe напрямую влияют на стабильность масштабирования.
  • Без resources.requests.cpu HPA по CPU обычно не имеет корректной базы для расчёта и может работать непредсказуемо.
  • Пример HPA по CPU для Deployment demo-web:

    Как читать ключевые поля:

  • minReplicas и maxReplicas задают коридор масштабирования.
  • averageUtilization: 70 означает целевую среднюю загрузку CPU в процентах от requests.cpu по Pod.
  • Команды диагностики:

    Типовые проблемы HPA:

  • HPA не масштабирует: нет метрик или не установлен Metrics Server.
  • HPA масштабирует, но трафик всё равно деградирует: Pod не успевают становиться Ready, неверно настроены probes, или контейнер ограничен слишком маленькими limits.
  • HPA нарастил реплики, но Pod стали Pending: не хватает ресурсов кластера, нужен Cluster Autoscaler или ручное расширение.
  • VPA: Vertical Pod Autoscaler

    VPA подбирает requests и limits по фактическому потреблению ресурсов. Это полезно, когда:

  • команды не могут быстро подобрать requests вручную
  • в кластере много приложений с ошибочно завышенными или заниженными requests
  • Важно понимать эксплуатационный эффект:

  • VPA часто требует пересоздания Pod, чтобы применить новые requests, значит он влияет на доступность.
  • VPA и HPA на одном и том же ресурсе часто конфликтуют: один меняет количество Pod, другой меняет размеры Pod.
  • Документация и статус проекта: Vertical Pod Autoscaler.

    Практический подход:

  • Начинайте с режима рекомендаций, чтобы VPA выдавал советы, а не менял всё автоматически.
  • После анализа переводите часть workload на автоматическое управление, где допустимы рестарты.
  • Cluster Autoscaler

    Cluster Autoscaler добавляет или удаляет ноды в кластере. Основной сигнал на увеличение:

  • появляются Pod в состоянии Pending из-за нехватки CPU, memory или других ресурсов
  • Ключевые зависимости:

  • Cluster Autoscaler принимает решения на основе requests Pod, поэтому корректные resources.requests критичны.
  • В облачных кластерах он обычно управляет node group или autoscaling group.
  • Документация проекта: Cluster Autoscaler.

    Типовая диагностика:

    Если вы видите Insufficient cpu или Insufficient memory, это обычно означает, что:

  • либо requests действительно превышают доступные ресурсы
  • либо в кластере нет автомасштабирования нод
  • либо есть ограничения на размещение Pod, например node affinity или taints, и новые ноды не подходят
  • Observability

    Observability в Kubernetes состоит из трёх основных потоков данных:

  • Metrics: численные ряды, которые подходят для алертов и трендов
  • Logs: детализация событий и ошибок
  • Traces: цепочки запросов между сервисами
  • С точки зрения DevOps цель observability проста: быстро ответить на вопросы что сломалось, где и почему.

    !Как собираются метрики, логи и трейсы из Kubernetes

    Что Kubernetes даёт из коробки

  • Состояние объектов через API: kubectl get и kubectl describe.
  • События: kubectl get events.
  • Логи контейнеров: kubectl logs.
  • Пробы: livenessProbe и readinessProbe.
  • Это фундамент, который нужно уметь использовать до подключения внешних платформ.

    Базовый набор команд для расследования инцидента:

    --previous полезен, когда контейнер уже перезапустился, а вам нужны логи падения.

    Метрики

    В Kubernetes есть два самых частых потребителя метрик:

  • HPA и kubectl top: обычно через Metrics Server
  • мониторинг и алерты: чаще через Prometheus
  • Что важно в практике:

  • Метрики без labels становятся бесполезными. Договоритесь о стандарте labels, например app, component, team, env.
  • Обязательно снимайте системные метрики кластера: ноды, kubelet, API server, состояние Deployments.
  • Если нужен только минимум для HPA и просмотра:

  • установите Metrics Server
  • Проверка:

    Логи

    Продакшен-подход в Kubernetes:

  • приложение пишет логи в stdout и stderr
  • платформа собирает их агентом на ноде и отправляет в централизованное хранилище
  • Официальная модель описана в Logging Architecture.

    Практические правила:

  • Не пишите логи в файлы внутри контейнера как основной механизм. Это усложняет сбор, ротацию и отладку.
  • Делайте логи структурированными, чтобы их можно было фильтровать по полям.
  • Следите за объёмом: лог-шторм может убить и стоимость, и производительность.
  • Трейсинг

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

    Современный стандарт для инструментирования и транспорта трейсов: OpenTelemetry.

    Практика внедрения:

  • Начните с одного критичного сервиса и одного критичного пути запроса.
  • Обеспечьте передачу trace context между сервисами.
  • Добавляйте семантические атрибуты: имя сервиса, эндпоинт, код ответа.
  • Отладка внутри кластера

    В продакшене полезно уметь дебажить не меняя образ приложения.

    Основные инструменты:

  • Временный Pod с утилитами:
  • Эфемерные контейнеры и kubectl debug: Ephemeral Containers и Debug Running Pods.
  • Upgrades

    Обновления в Kubernetes неизбежны: новые версии закрывают уязвимости, улучшают стабильность и добавляют функциональность. Но обновления опасны тем, что затрагивают одновременно control plane, ноды и API-совместимость манифестов.

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

    !Безопасное обновление нод без простоя

    Подготовка к обновлению

    Рекомендуемый порядок подготовки:

  • Проверьте политику совместимости версий: Kubernetes Version Skew Policy.
  • Прочитайте release notes и обратите внимание на deprecations и удалённые API.
  • Проверьте, какие API версии используются в ваших манифестах.
  • - Частый риск: старые версии Ingress или устаревшие поля.
  • Убедитесь, что приложения готовы к кратковременным пересозданиям Pod.
  • - Несколько реплик. - Корректные readinessProbe. - Наличие PodDisruptionBudget для критичных компонентов.

    PodDisruptionBudget

    PodDisruptionBudget (PDB) ограничивает, сколько Pod можно одновременно вывести из работы при плановых нарушениях, например при drain.

    Пример PDB, который требует, чтобы хотя бы один Pod приложения оставался доступным:

    Практический смысл:

  • Если у вас одна реплика и вы делаете drain, то downtime почти неизбежен.
  • Если реплик несколько и PDB настроен, Kubernetes постарается сохранить доступность.
  • Обновление ноды: cordon и drain

    Ключевой административный сценарий для безопасного обслуживания ноды описан в Safely Drain a Node.

    Базовый порядок:

    Как читать флаги:

  • --ignore-daemonsets нужно, потому что DaemonSet-поды обычно нельзя безопасно эвакуировать обычным способом.
  • --delete-emptydir-data удаляет данные из emptyDir, потому что они живут на ноде и не мигрируют.
  • Типовые причины, почему drain зависает:

  • нет свободных ресурсов на других нодах
  • слишком строгие ограничения размещения Pod
  • PDB не позволяет эвакуацию из-за недостаточного числа доступных реплик
  • Практика обновлений в продакшене

  • Обновляйте окружения последовательно: dev, stage, prod.
  • Перед обновлением делайте бэкап критичных данных и убедитесь, что есть план отката.
  • Держите инфраструктурные компоненты в зоне внимания: CNI, CSI, Ingress Controller, DNS.
  • После обновления прогоняйте проверки:
  • - состояние нод - состояние системных компонентов в kube-system - доступность критичных сервисов через Service и Ingress

    Backup и восстановление

    Бэкап в Kubernetes часто проваливается не потому, что никто не умеет делать snapshot, а потому что люди не договорились, что именно считается бэкапом.

    У Kubernetes есть два класса данных:

  • Состояние кластера: объекты API, хранящиеся в etcd
  • Данные приложений: содержимое томов, баз данных, объектные хранилища
  • Что стоит включить в стратегию бэкапа

  • Снимки etcd или эквивалентный механизм у провайдера.
  • Экспорт и хранение манифестов в Git как источник правды.
  • Бэкапы томов:
  • - CSI VolumeSnapshot, если поддерживается - или бэкап на уровне внешнего хранилища
  • Регулярные тесты восстановления.
  • Бэкап etcd

    Если вы управляете control plane сами, etcd критичен: потеря etcd означает потерю состояния кластера.

    Официальная процедура: Backup an etcd cluster.

    Смысл бэкапа etcd:

  • сохранить снимок базы состояния Kubernetes
  • иметь возможность восстановить control plane после катастрофы
  • Практический нюанс:

  • Бэкап etcd сам по себе не возвращает данные приложений на PV.
  • Бэкап PV сам по себе не вернёт объекты Kubernetes, если у вас нет манифестов или снапшота состояния.
  • VolumeSnapshot для PV

    Если хранилище поддерживает CSI snapshots, Kubernetes умеет описывать снапшоты декларативно.

    Документация: Volume Snapshots.

    В эксплуатации важно:

  • поддержка зависит от CSI драйвера и провайдера
  • снапшоты нужно регулярно проверять восстановлением
  • Velero как практический инструмент

    Velero часто используют как единый инструмент для:

  • бэкапа объектов Kubernetes
  • снапшотов PV через CSI или через интеграции провайдера
  • восстановления namespace или всего кластера
  • Правильная эксплуатационная модель Velero:

  • Определите, что вы бэкапите: namespace, конкретные ресурсы, PV.
  • Настройте место хранения бэкапов вне кластера.
  • Разделите права доступа RBAC для Velero по принципу минимально необходимых.
  • Запланируйте регулярные тесты восстановления на отдельном окружении.
  • Практический чек-лист продакшен-готовности

    Ниже краткая таблица, которая связывает темы курса в эксплуатационные артефакты.

    | Область | Что должно быть сделано | Как проверить | | --- | --- | --- | | Масштабирование Pod | HPA настроен на ключевые сервисы, есть requests | kubectl get hpa, kubectl top pods | | Масштабирование кластера | Включён Cluster Autoscaler или есть процесс расширения | отсутствие массовых Pending при нагрузке | | Наблюдаемость | Метрики, логи, события, базовые дашборды | метрики доступны, логи централизованы | | Доступность при обслуживании | Реплики, probes, PDB для критичных сервисов | kubectl get pdb, kubectl rollout status | | Безопасность | RBAC минимален, PSA включён, NetworkPolicy изолирует | kubectl auth can-i, события PSA, тест сетей | | Восстановление | Бэкап etcd и данных, регулярные restore тесты | успешный restore на тестовом кластере |

    Что важно запомнить

  • Autoscaling всегда упирается в корректные resources.requests и наличие метрик.
  • HPA масштабирует Pod, Cluster Autoscaler масштабирует ноды, VPA подбирает размеры Pod.
  • Observability в Kubernetes строится вокруг метрик, логов, трейсов и базовой диагностики через kubectl.
  • Upgrades требуют подготовки: совместимость версий, deprecations, PDB, корректный drain.
  • Backup должен включать и состояние кластера, и данные приложений, а также регулярные тесты восстановления.