Kubernetes CKA: Архитектура, администрирование и подготовка к сертификации

Углубленный курс-интенсив для систематизации знаний по K8s, ориентированный на подготовку к экзамену CKA и техническим интервью. Программа охватывает внутреннюю логику компонентов, управление ресурсами, сетевую безопасность и включает разбор 30 практических задач.

1. Архитектура Kubernetes и глубокий разбор компонентов Control Plane

Архитектура Kubernetes и глубокий разбор компонентов Control Plane

Парадокс Kubernetes заключается в том, что сам оркестратор не запускает ни одного контейнера и не маршрутизирует ни одного байта пользовательского трафика. По своей сути Kubernetes — это гигантская, распределенная машина состояний. Вы просто описываете желаемое состояние системы (Desired State), а компоненты кластера бесконечно сверяют его с текущим состоянием (Actual State) и пытаются устранить разницу.

Для успешной сдачи CKA и прохождения технических интервью недостаточно знать, как создать Pod. Вы должны понимать, кто именно в кластере принимает решение о его создании, где хранится информация об этом и как компоненты общаются между собой.

Две половины мозга: Control Plane и Worker Nodes

Архитектуру Kubernetes можно разделить на две фундаментальные части.

  • Control Plane (Управляющий слой) — мозг кластера. Он принимает глобальные решения (например, на каком узле запустить приложение), обнаруживает события и реагирует на них.
  • Worker Nodes (Рабочие узлы) — мускулы кластера. Это серверы, на которых физически работают ваши контейнеры.
  • !Логическая архитектура Kubernetes

    Чтобы кластер работал как единый механизм, компоненты должны иметь строгую специализацию. Давайте разберем Control Plane под микроскопом.

    Анатомия Control Plane

    В классическом кластере (созданном через kubeadm) компоненты Control Plane запускаются в виде статических подов (Static Pods) в пространстве имен kube-system.

    > CKA Cheat: Манифесты статических подов Control Plane по умолчанию лежат в директории /etc/kubernetes/manifests/. Если вы измените YAML-файл в этой папке, kubelet автоматически перезапустит соответствующий компонент. Это ключевой навык для траблшутинга на экзамене.

    1. kube-apiserver (Центральный коммутатор)

    kube-apiserver — это единственный компонент кластера, с которым взаимодействуете вы (через kubectl) и все остальные компоненты системы.

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

  • Stateless (не хранит состояние): Сам API-сервер не запоминает данные. Он масштабируется горизонтально простым добавлением новых реплик за балансировщиком нагрузки.
  • Единая точка входа: Ни один компонент кластера (кроме API-сервера) не имеет прямого доступа к базе данных etcd.
  • Функции: Аутентификация, авторизация (RBAC), валидация запросов (Admission Control) и маршрутизация манифестов.
  • 2. etcd (Абсолютная память)

    etcd — это высокодоступное распределенное хранилище пар «ключ-значение» (key-value store). Это единственный stateful-компонент в Control Plane.

    Если kube-apiserver — это коммутатор, то etcd — это единственный источник истины (Single Source of Truth). В нем хранятся все конфигурации, секреты и состояния объектов.

    Что нужно помнить для CKA:

  • etcd использует алгоритм консенсуса Raft. Для обеспечения отказоустойчивости кластер etcd должен состоять из нечетного количества узлов (обычно 3 или 5).
  • Если данные в etcd потеряны, кластер Kubernetes фактически перестает существовать, даже если контейнеры все еще работают на узлах.
  • На экзамене CKA обязательно будет задача на резервное копирование и восстановление (Backup & Restore) etcd с использованием утилиты etcdctl.
  • 3. kube-scheduler (Распределитель ресурсов)

    Многие думают, что scheduler запускает поды на узлах. Это ошибка, на которой часто ловят на интервью.

    kube-scheduler ничего не запускает. Его единственная задача — заметить новый Pod без назначенного узла (nodeName пустое), проанализировать доступные ресурсы кластера и выбрать оптимальный узел для этого пода.

    Процесс принятия решения состоит из двух этапов:

  • Filtering (Фильтрация): Отсеиваются узлы, которые не подходят аппаратно (не хватает CPU/RAM) или логически (Taints, Node Selectors).
  • Scoring (Оценка): Оставшимся узлам выставляются баллы по ряду критериев (например, приоритет отдается узлу, где уже есть нужные образы контейнеров). Узел с максимальным баллом побеждает.
  • После выбора узла scheduler просто отправляет запрос в kube-apiserver с сообщением: "Привяжи Pod X к Узлу Y".

    4. kube-controller-manager (Неутомимый надзиратель)

    Это набор фоновых процессов (контроллеров), которые непрерывно следят за состоянием кластера через kube-apiserver. Их задача — приводить Actual State к Desired State.

    Внутри kube-controller-manager работают десятки контроллеров. Вот основные:

  • Node Controller: Следит за тем, живы ли рабочие узлы.
  • ReplicaSet Controller: Гарантирует, что работает ровно столько реплик пода, сколько указано в конфигурации.
  • EndpointSlice Controller: Связывает сервисы с подами (заполняет списки IP-адресов).
  • ServiceAccount & Token Controllers: Создают стандартные аккаунты и токены доступа для новых пространств имен.
  • Сводная таблица компонентов

    | Компонент | Роль в кластере | Порт по умолчанию | Состояние | |---|---|---|---| | kube-apiserver | Интерфейс взаимодействия и валидации | 6443 | Stateless | | etcd | База данных, источник истины | 2379, 2380 | Stateful | | kube-scheduler | Выбор узла для запуска Pod | 10259 | Stateless | | kube-controller-manager | Поддержание желаемого состояния | 10257 | Stateless |

    Коротко о Worker Nodes

    Хотя фокус этой статьи — Control Plane, для понимания общей картины необходимо упомянуть агентов, работающих на рабочих узлах:

  • kubelet: "Капитан" узла. Он получает от kube-apiserver спецификации подов (PodSpecs) и приказывает Container Runtime запустить или остановить контейнеры. Также он постоянно рапортует API-серверу о состоянии узла.
  • kube-proxy: Сетевой прокси-сервер. Он обновляет правила маршрутизации операционной системы (через iptables или IPVS), чтобы сетевой трафик правильно доходил до подов.
  • Container Runtime: Программное обеспечение, ответственное за непосредственный запуск контейнеров (containerd, CRI-O).
  • Жизненный цикл создания Pod: Как они общаются?

    Понимание того, как компоненты взаимодействуют между собой — это ключ к успешному траблшутингу. Рассмотрим классический сценарий: вы выполняете команду kubectl apply -f pod.yaml.

    !Пошаговое создание Pod в Kubernetes

    Вот текстовая расшифровка этого процесса (идеальный ответ на техническом интервью):

  • kubectl валидирует YAML локально и отправляет HTTP POST запрос в kube-apiserver.
  • kube-apiserver аутентифицирует вас, проверяет права (RBAC), валидирует манифест и записывает объект Pod в etcd со статусом Pending (узел еще не назначен).
  • kube-apiserver подтверждает kubectl, что Pod успешно создан в базе.
  • kube-scheduler непрерывно опрашивает API-сервер. Он замечает новый Pod без привязки к узлу.
  • kube-scheduler вычисляет лучший узел для пода и отправляет запрос Binding обратно в kube-apiserver.
  • kube-apiserver обновляет запись в etcd, добавляя имя узла в спецификацию пода.
  • kubelet на выбранном узле (который тоже непрерывно слушает API-сервер) замечает, что ему назначен новый Pod.
  • kubelet обращается к Container Runtime (например, containerd) с командой скачать образ и запустить контейнер.
  • После успешного запуска kubelet отправляет статус Running обратно в kube-apiserver, который финально обновляет данные в etcd.
  • В этой цепочке никто не общается друг с другом напрямую. Все коммуникации происходят исключительно через подписки (watches) на изменения в kube-apiserver.

    Понимание этой архитектуры позволит вам на экзамене CKA быстро локализовать проблему. Если Pod висит в статусе Pending, проблема, скорее всего, в scheduler или нехватке ресурсов. Если Pod создается, но контейнер не стартует (статус ContainerCreating или CrashLoopBackOff), проблема на стороне kubelet или Container Runtime на конкретном узле.

    10. Практикум: 30 типовых экзаменационных вопросов с подробными решениями

    Практикум: 30 типовых экзаменационных вопросов с подробными решениями

    Экзамен Certified Kubernetes Administrator (CKA) длится 2 часа и состоит исключительно из практических задач в "живой" консоли. У вас не будет времени вспоминать структуру YAML-файлов или искать базовые концепции в документации — здесь решает мышечная память. Технические же интервью, напротив, проверяют глубину понимания: почему система ведет себя именно так, а не иначе.

    В этой финальной статье курса мы объединим оба подхода. Мы разберем 30 типовых вопросов, разделив их на архитектурные (для интервью) и практические (для экзамена).

    1. Архитектура и Control Plane (Вопросы для интервью)

    На интервью от вас ждут понимания механики работы кластера под капотом.

    1. Что произойдет с подами, если Worker Node внезапно выйдет из строя (отключится питание)? Сразу — ничего. API-сервер потеряет связь с kubelet этого узла. Спустя время (по умолчанию 40 секунд) узел перейдет в статус NotReady. Еще через 5 минут (параметр pod-eviction-timeout) kube-controller-manager начнет процесс вытеснения (eviction). Поды получат статус Terminating, а ReplicaSet создаст новые поды на здоровых узлах.

    2. Как etcd защищен от проблемы "Split-Brain" (расщепления мозга) при сетевом разделении? etcd использует алгоритм консенсуса Raft. Для записи данных требуется подтверждение от большинства узлов кластера (кворума). Формула кворума: , где — количество узлов etcd. Если кластер из 3 узлов разделяется на 2 и 1, часть с двумя узлами сохраняет кворум () и продолжает работу, а изолированный узел перестает принимать запись.

    3. В чем фундаментальная разница между обычным Pod и Static Pod? Обычный Pod создается через API-сервер, сохраняется в etcd и планируется kube-scheduler. Static Pod управляется исключительно локальным kubelet на конкретном узле. API-сервер лишь отображает его статус ("зеркальный под"), но не может его удалить или изменить.

    4. Как kube-proxy маршрутизирует трафик к подам при обращении к Service? По умолчанию kube-proxy работает в режиме iptables. Он следит за объектами Service и Endpoints через API-сервер и создает правила брандмауэра Linux. Когда пакет обращается к виртуальному IP сервиса (VIP), iptables перехватывает его и с помощью вероятностного алгоритма подменяет IP-адрес назначения (DNAT) на IP-адрес одного из реальных подов.

    5. Зачем нужны Custom Resource Definitions (CRD)? CRD позволяют расширить стандартный API Kubernetes. Если вам не хватает встроенных объектов (Pod, Deployment), вы можете создать свой (например, Database или SSLConfig). После применения CRD API-сервер начинает принимать YAML-манифесты с вашим новым kind, а для управления их жизненным циклом пишутся кастомные контроллеры (Operators).

    2. Экзаменационная среда и контексты (CKA)

    На экзамене CKA вы работаете не с одним, а с несколькими кластерами. Самая частая ошибка — выполнить правильную задачу не в том кластере.

    !Архитектура экзаменационной среды CKA

    > Перед каждым заданием на экзамене вам будет дана команда для переключения контекста. Никогда не игнорируйте ее. > > kubectl config use-context k8s-c1-H

    6. Как посмотреть все доступные контексты и текущий кластер?

    7. Как найти узел с ролью Control Plane и узнать его версию ОС?

    3. Быстрые императивные команды (CKA)

    На экзамене нет времени писать YAML с нуля. Вы должны генерировать их императивно. Ниже — таблица-шпаргалка с типовыми задачами (Вопросы 8–15).

    | Задача (Вопрос) | Решение (Команда) | | :--- | :--- | | 8. Создать Pod nginx с меткой env=prod | kubectl run nginx --image=nginx --labels=env=prod | | 9. Сгенерировать YAML для Deployment без его создания | kubectl create deploy web --image=nginx --dry-run=client -o yaml > deploy.yaml | | 10. Масштабировать Deployment api до 5 реплик | kubectl scale deploy api --replicas=5 | | 11. Обновить образ в Deployment и записать это в историю | kubectl set image deploy/api nginx=nginx:1.19.2 --record | | 12. Проверить статус раскатки (rollout) | kubectl rollout status deploy/api | | 13. Откатить Deployment на предыдущую версию | kubectl rollout undo deploy/api | | 14. Создать Service типа NodePort для пода | kubectl expose pod nginx --port=80 --type=NodePort | | 15. Извлечь IP-адреса всех подов (JSONPath) | kubectl get pods -o jsonpath='{.items[*].status.podIP}' |

    4. Управление рабочими нагрузками и YAML (CKA)

    Здесь проверяется умение комбинировать объекты и редактировать манифесты.

    16. Создайте многоконтейнерный Pod (паттерн Sidecar). Основной контейнер busybox пишет логи в файл, второй busybox читает их. Решение: Генерируем базовый под: kubectl run multi --image=busybox --dry-run=client -o yaml > pod.yaml. Затем редактируем YAML, добавляя emptyDir и второй контейнер:

    17. Запустите Pod на конкретном узле node02. Решение: В спецификацию пода (spec) нужно добавить nodeName.

    18. Найдите под, потребляющий больше всего CPU, и запишите его имя в файл. Решение: Используем Metrics Server.

    5. Хранилище: PV и PVC (CKA)

    19. Создайте PersistentVolume pv-log объемом 1Gi, режимом ReadWriteMany, используя hostPath /opt/volume. Решение: PV нельзя создать императивно одной строкой. Пишем YAML (можно подсмотреть структуру через kubectl explain pv.spec или в документации).

    20. Создайте PVC, который свяжется с PV из предыдущего шага, и подключите его к поду. Решение: Создаем PVC с совпадающими требованиями (1Gi, ReadWriteMany).

    В поде монтируем так:

    6. Безопасность, Конфигурация и RBAC (CKA)

    21. Создайте Secret из литерала и пробросьте его в Pod как переменную окружения DB_PASS. Решение: Шаг 1: kubectl create secret generic db-secret --from-literal=password=supersecret Шаг 2: В манифесте пода:

    22. Создайте ServiceAccount deployer, роль deploy-role (с правом создавать deployments) и свяжите их в неймспейсе dev. Решение: Это легко делается императивно.

    23. Проверьте, может ли созданный ServiceAccount удалять поды? Решение: Используем механизм auth can-i.

    24. Настройте NetworkPolicy, которая запрещает весь входящий трафик в неймспейсе secure, кроме трафика на порт 80 от подов с меткой access=true. Решение:

    7. Обслуживание узлов и Траблшутинг (CKA)

    Это самые "дорогие" по баллам задания на экзамене.

    25. Сделайте резервную копию базы данных etcd и сохраните ее в /opt/etcd-backup.db. Решение: Для работы с etcd нужен клиент etcdctl и сертификаты Control Plane.

    26. Восстановите etcd из созданного бэкапа в директорию /var/lib/etcd-restore. Решение:

    Важно: После восстановления нужно изменить путь к data-dir в манифесте статического пода /etc/kubernetes/manifests/etcd.yaml.

    27. Выведите узел node01 из эксплуатации для обслуживания, убедившись, что поды безопасно перенесены. Решение: Используем команду drain. Флаг --ignore-daemonsets обязателен, так как DaemonSet нельзя вытеснить обычным способом.

    28. Верните узел node01 обратно в работу. Решение:

    29. Узел node02 находится в статусе NotReady. Как найти причину? Решение: Воронка траблшутинга.

  • Проверяем статус узла: kubectl describe node node02 (смотрим секцию Conditions).
  • Заходим на сам узел по SSH: ssh node02.
  • Проверяем статус агента: systemctl status kubelet.
  • Читаем логи агента: journalctl -u kubelet -f. Обычно проблема кроется в неверной конфигурации или упавшем Container Runtime.
  • 30. Обновите кластер (kubeadm) с версии 1.28.0 до 1.28.1. Решение (краткий алгоритм для Control Plane):

  • Обновляем пакетный менеджер: apt-get update && apt-get install -y kubeadm=1.28.1-00.
  • Планируем апгрейд: kubeadm upgrade plan.
  • Применяем апгрейд: kubeadm upgrade apply v1.28.1.
  • Дрейним узел: kubectl drain <node-name> --ignore-daemonsets.
  • Обновляем компоненты узла: apt-get install -y kubelet=1.28.1-00 kubectl=1.28.1-00.
  • Перезапускаем агент: systemctl daemon-reload && systemctl restart kubelet.
  • Возвращаем узел в работу: kubectl uncordon <node-name>.
  • > Главный совет на экзамен: Не застревайте на одном вопросе. Если траблшутинг занимает больше 7-10 минут, ставьте флажок (Flag) и идите дальше. Сдают те, кто быстро забирает легкие баллы с императивными командами и RBAC.

    2. Объекты API и управление рабочими нагрузками: Pods, Deployments, StatefulSets

    Объекты API и управление рабочими нагрузками: Pods, Deployments, StatefulSets

    Контейнер смертен, и чаще всего — внезапно. Если запустить «голый» Docker-контейнер на сервере, то при сбое узла он исчезнет навсегда. Kubernetes не работает с контейнерами напрямую именно по этой причине: ему нужны более высокие уровни абстракции, которые позволяют описывать желаемое состояние системы (Desired State) и автоматически восстанавливать его при сбоях.

    В этой статье мы разберем иерархию рабочих нагрузок (Workloads) — от атомарной единицы до сложных контроллеров, управляющих приложениями без сохранения состояния (Stateless) и с сохранением состояния (Stateful).

    Pod: Атомарная единица Kubernetes

    Pod (Под) — это минимальный развертываемый объект в Kubernetes. Вы не можете развернуть половину пода или отдельный контейнер через API.

    Почему Kubernetes использует поды, а не контейнеры? Под создает «логический хост» для одного или нескольких контейнеров, обеспечивая им общее пространство имен (Namespaces). Все контейнеры внутри одного пода делят:

  • Сетевое пространство (Network): у них один IP-адрес и один набор портов. Они могут общаться друг с другом через localhost.
  • Хранилище (Storage): они могут монтировать одни и те же тома (Volumes) и обмениваться файлами.
  • IPC (Inter-Process Communication): могут использовать общую разделяемую память.
  • Паттерн Sidecar (Многоконтейнерный под)

    На экзамене CKA часто встречается задача на добавление второго контейнера в существующий под. Это классический паттерн Sidecar (прицепная коляска). Основной контейнер выполняет бизнес-логику (например, веб-сервер Nginx), а вспомогательный — расширяет его функционал (например, агент Fluentd, собирающий логи Nginx из общей папки и отправляющий их на сервер).

    !Структура многоконтейнерного пода с общим хранилищем и сетью

    Пример манифеста многоконтейнерного пода:

    Жизненный цикл пода (Pod Phases)

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

  • Pending: API-сервер принял манифест, но под еще не запущен (например, планировщик ищет узел или скачивается тяжелый образ).
  • Running: Под привязан к узлу, все контейнеры созданы, минимум один работает.
  • Succeeded: Все контейнеры успешно завершили работу (код возврата ) и не будут перезапущены.
  • Failed: Все контейнеры завершили работу, но хотя бы один завершился с ошибкой (код возврата ).
  • CrashLoopBackOff (статус, а не фаза): Контейнер постоянно падает при старте, и kubelet увеличивает паузу между попытками перезапуска.
  • ReplicaSet: Страж количества

    Сам по себе Pod уязвим. Если узел упадет, под умрет вместе с ним. Чтобы приложение было отказоустойчивым, подами управляют контроллеры. Базовый контроллер — ReplicaSet.

    Его единственная задача — поддерживать математическое равенство: (Желаемое количество реплик равно фактическому).

    ReplicaSet не привязан к подам жестко. Он находит «свои» поды с помощью Label Selectors (селекторов меток). Если вы вручную создадите под с меткой app: frontend, а ReplicaSet настроен на поддержание 3 подов с такой меткой, он посчитает ваш под своим. Если подов станет 4, он безжалостно удалит один случайный.

    Примечание: В современной практике ReplicaSet почти никогда не создают напрямую. Ими управляет контроллер более высокого уровня — Deployment.

    Deployment: Эволюция Stateless-приложений

    Deployment — это декларативный способ управления ReplicaSet и подами. Он предназначен для Stateless приложений (веб-серверы, API-шлюзы, микросервисы), где все реплики абсолютно идентичны и взаимозаменяемы.

    > «Stateless-приложения — это стадо (cattle). Если одна овца заболела, вы не везете ее к ветеринару. Вы избавляетесь от нее и покупаете новую. Deployments автоматизируют этот процесс».

    Главная суперсила Deployment — безопасное обновление версий приложения (Rollout) и откат назад (Rollback).

    Стратегии обновления

  • Recreate: Сначала удаляются все старые поды, затем создаются новые. Плюс: нет конфликтов версий. Минус: простой (Downtime) приложения.
  • RollingUpdate (по умолчанию): Плавная замена старых подов на новые.
  • При RollingUpdate используются два важных параметра:

  • maxUnavailable: сколько подов от желаемого количества могут быть недоступны во время обновления (по умолчанию 25%).
  • maxSurge: на сколько подов можно превысить желаемое количество в процессе обновления (по умолчанию 25%).
  • !Процесс Rolling Update в Deployment

    Шпаргалка CKA: Управление Deployment

    На экзамене вам часто придется обновлять образы и откатывать изменения. Делайте это императивными командами для экономии времени:

    StatefulSet: Укрощение состояния

    Если Deployments управляют «стадом», то StatefulSet предназначен для «домашних питомцев» (pets) — баз данных (PostgreSQL, MongoDB), брокеров сообщений (Kafka) и систем кэширования (Redis).

    Для базы данных поды не взаимозаменяемы. Базе данных критически важно знать, кто является Master-узлом, а кто Replica. У них должны быть постоянные имена и постоянные диски.

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

  • Стабильная сетевая идентичность: Поды получают предсказуемые имена с порядковыми индексами от до . Если StatefulSet называется mysql, поды будут называться mysql-0, mysql-1, mysql-2. При перезапуске имя сохраняется.
  • Строгий порядок запуска и удаления: Под mysql-1 не начнет создаваться, пока mysql-0 не перейдет в состояние Running. Удаление происходит в обратном порядке: от до .
  • Стабильное хранилище (VolumeClaimTemplates): Каждый под получает свой собственный независимый Persistent Volume. Если под mysql-0 падает и пересоздается на другом узле, StatefulSet гарантирует, что к нему будет подключен тот же самый диск с его старыми данными.
  • Сравнение Deployment и StatefulSet

    | Характеристика | Deployment (Stateless) | StatefulSet (Stateful) | | :--- | :--- | :--- | | Имена подов | Случайный хэш (web-7b9c...) | Индексные (db-0, db-1) | | Порядок создания | Параллельно (все сразу) | Строго последовательно () | | Хранилище данных | Общее или эфемерное | Индивидуальное для каждого пода (через PVC) | | Сетевой доступ | Балансировка через обычный Service | Прямой доступ к подам через Headless Service | | Типичный сценарий | Nginx, Node.js, Spring Boot | PostgreSQL, Elasticsearch, RabbitMQ |

    О том, как именно StatefulSet обеспечивает прямой сетевой доступ к конкретному поду через Headless Service, мы подробно поговорим в следующей главе, посвященной сетевому взаимодействию.

    3. Сетевое взаимодействие, сервисы и маршрутизация трафика в кластере

    Сетевое взаимодействие, сервисы и маршрутизация трафика в кластере

    Представьте мегаполис, в котором дома постоянно перемещаются, исчезают и отстраиваются заново на других улицах, но почтальон всегда доставляет письма точно по адресу. Это ваш кластер Kubernetes. Поды эфемерны: они создаются, умирают (CrashLoopBackOff) и пересоздаются контроллерами (Deployments) с совершенно новыми IP-адресами. Если IP-адреса постоянно меняются, как компоненты микросервисной архитектуры находят друг друга?

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

    Базовая сетевая модель Kubernetes (CNI)

    Прежде чем говорить о сервисах, необходимо понять фундамент. Kubernetes не реализует сеть самостоятельно. Он делегирует эту задачу плагинам CNI (Container Network Interface) — таким как Calico, Flannel или Cilium.

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

  • Каждый Pod получает собственный уникальный IP-адрес в рамках кластера.
  • Все Pods могут общаться друг с другом напрямую без использования NAT (Network Address Translation), даже если они находятся на разных узлах (Worker Nodes).
  • Агенты узла (kubelet) могут общаться со всеми подами на этом узле.
  • > Сетевая модель K8s устраняет необходимость проброса портов (port mapping) между контейнером и хостом, как это делалось в чистом Docker. Внутри кластера сеть выглядит как огромный плоский коммутатор.

    Service: Стабильный якорь в море хаоса

    Поскольку напрямую обращаться к IP-адресу пода бессмысленно (он изменится при следующем перезапуске), Kubernetes предлагает абстракцию — объект Service.

    Service предоставляет единый, статический IP-адрес (VIP — Virtual IP) и DNS-имя для набора подов. Связь между Service и подами осуществляется через уже знакомый нам механизм Label Selectors. Service постоянно отслеживает поды с нужными метками и автоматически обновляет свой список конечных точек (Endpoints).

    !Динамическая балансировка трафика Service при падении подов

    Основной манифест Service

    Типы Service: От внутреннего к внешнему

    В зависимости от того, откуда должен приходить трафик, Service может принимать один из четырех типов.

    | Тип Service | Зона видимости | Как работает | Применение | | :--- | :--- | :--- | :--- | | ClusterIP (по умолчанию) | Только внутри кластера | Выдает внутренний статический IP. Недоступен извне. | Связь между микросервисами (например, Backend Database). | | NodePort | Внешний доступ | Открывает статический порт (диапазон 30000-32767) на каждом Worker Node. | Прямой доступ к приложению извне (чаще для отладки). | | LoadBalancer | Внешний доступ | Автоматически заказывает балансировщик нагрузки у облачного провайдера (AWS, GCP). | Продакшн-доступ в публичных облаках. | | ExternalName | Внешний ресурс | Работает как CNAME-запись в DNS, перенаправляя трафик на внешнее доменное имя. | Доступ из кластера к внешней managed-базе данных. |

    Headless Service (Обещание из прошлой главы)

    В прошлой статье мы упоминали, что для контроллера StatefulSet (базы данных, брокеры сообщений) требуется особый подход. Базам данных часто нужно знать точные адреса своих соседей для репликации, а не общаться через единый балансировщик.

    Для этого используется Headless Service. В манифесте указывается clusterIP: None. Такой сервис не получает виртуального IP и не балансирует трафик. Вместо этого при DNS-запросе к имени сервиса CoreDNS возвращает список A-записей — реальных IP-адресов всех подов, попадающих под селектор.

    Под капотом: Как работает kube-proxy

    Service — это не физический маршрутизатор и не отдельный контейнер. Это абстракция, реализованная компонентом kube-proxy, который работает на каждом Worker Node.

    Kube-proxy слушает Control Plane (kube-apiserver) на предмет появления новых Service и Endpoints, а затем конфигурирует сетевые правила операционной системы для перехвата трафика.

    Существует два основных режима работы kube-proxy:

  • iptables (по умолчанию): Kube-proxy создает правила iptables. Трафик перехватывается ядром Linux и перенаправляется на один из подов случайным образом. Проблема в том, что правила обрабатываются последовательно. При тысячах сервисов время поиска нужного правила растет линейно: , где — количество правил.
  • IPVS (IP Virtual Server): Более современный режим, использующий хэш-таблицы в ядре Linux. Время маршрутизации остается константным: . Это критически важно для производительности в огромных кластерах.
  • Ingress: Умная маршрутизация L7 (HTTP/HTTPS)

    NodePort и LoadBalancer работают на 4-м уровне модели OSI (L4 — транспортный). Они умеют маршрутизировать только TCP/UDP трафик по IP и портам.

    Если у вас 10 веб-приложений, использование 10 LoadBalancer будет стоить дорого, а использование NodePort потребует от клиентов указывать нестандартные порты (например, example.com:31204).

    Решение — Ingress. Это объект API, который управляет внешним доступом к сервисам в кластере, обычно по HTTP/HTTPS (L7 — прикладной уровень). Ingress позволяет настроить маршрутизацию на основе URL-путей или доменных имен.

    !Сравнение архитектуры NodePort и Ingress

    Чтобы объект Ingress заработал, в кластере должен быть установлен Ingress Controller (например, NGINX Ingress Controller, Traefik или HAProxy). Контроллер — это под, который принимает весь внешний трафик на стандартные порты (80 и 443) и проксирует его нужным Service согласно правилам.

    Пример манифеста Ingress (маршрутизация по пути)

    Service Discovery: Роль CoreDNS

    Как поды узнают IP-адрес нужного Service? Через встроенный в кластер DNS-сервер — CoreDNS.

    При создании Service, CoreDNS автоматически генерирует для него DNS-запись по строгому шаблону: <название-сервиса>.<пространство-имен>.svc.cluster.local

    Например, если вы создали Service с именем db-master в namespace production, любой под в кластере сможет обратиться к нему по адресу: db-master.production.svc.cluster.local

    Если обращающийся под находится в том же namespace (production), он может использовать короткое имя: просто db-master.

    > Шпаргалка для траблшутинга (CKA): Если поды не могут связаться по DNS-имени, первым делом проверьте статус подов CoreDNS в пространстве имен kube-system: kubectl get pods -n kube-system -l k8s-app=kube-dns.

    4. Управление хранилищами данных: Persistent Volumes и механизмы CSI

    Управление хранилищами данных: Persistent Volumes и механизмы CSI

    Если контейнер внутри пода аварийно завершит работу, kubelet перезапустит его, но все файлы, созданные или измененные за время его жизни, исчезнут. Контейнер запустится с «чистого листа». В мире stateless приложений это норма, но для баз данных, очередей сообщений и файловых хранилищ потеря состояния — это катастрофа. Kubernetes решает эту проблему, вынося хранение данных за пределы жизненного цикла пода.

    Эволюция хранения: от Volumes к PV и PVC

    Базовый объект Volume (том) решает проблему обмена данными между контейнерами в одном поде (например, через emptyDir), но его существование жестко привязано к жизни самого пода. Если под удаляется, удаляется и том.

    Для независимого хранения данных Kubernetes ввел абстракцию Persistent Volume (PV) и Persistent Volume Claim (PVC). Этот паттерн разделяет ответственность:

  • Администратор кластера (или автоматика) управляет физическими дисками и создает объекты PersistentVolume.
  • Разработчик приложения запрашивает нужный объем и тип доступа через PersistentVolumeClaim, не вникая в то, какой именно массив хранения (NFS, AWS EBS, Ceph) используется под капотом.
  • > PersistentVolume (PV) — это ресурс кластера (не привязан к namespace), представляющий собой физический или виртуальный диск. > > PersistentVolumeClaim (PVC) — это запрос на выделение хранилища (привязан к namespace), который делает приложение.

    !Архитектура взаимодействия PV, PVC и Pod

    Жизненный цикл тома (Статическое выделение)

    При статическом подходе администратор заранее создает пул PV. Когда разработчик создает PVC, Kubernetes ищет подходящий PV и связывает их. Этот процесс называется Binding.

    Логика связывания (Binding)

    Контроллер PersistentVolumeController непрерывно следит за новыми PVC. Чтобы PVC успешно связался с PV, должны совпасть следующие условия:

  • Емкость (Capacity): Объем PV должен быть больше или равен запрошенному в PVC ().
  • Режим доступа (Access Modes): PV должен поддерживать режимы, запрошенные в PVC.
  • Класс хранилища (StorageClassName): Если в PVC указан класс, PV должен иметь такой же.
  • Метки (Label Selectors): Если в PVC указан селектор, PV должен иметь соответствующие метки.
  • Связь PV и PVC эксклюзивна: один PV может быть привязан только к одному PVC.

    Режимы доступа (Access Modes)

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

    | Режим | Аббревиатура | Описание | Типичный Use-Case | |---|---|---|---| | ReadWriteOnce | RWO | Том монтируется на чтение и запись только одним узлом (Node). | Базы данных (AWS EBS, GCE PD). | | ReadOnlyMany | ROX | Том монтируется только для чтения множеством узлов. | Раздача статики, конфигураций. | | ReadWriteMany | RWX | Том монтируется на чтение и запись множеством узлов. | Файловые серверы (NFS, CephFS). | | ReadWriteOncePod | RWOP | Том монтируется на чтение и запись строго одним подом (появилось в K8s 1.22+). | Максимальная изоляция данных пода. |

    Политики возврата (Reclaim Policy)

    Что происходит с диском (PV), когда пользователь удаляет заявку (PVC)? Это определяется политикой persistentVolumeReclaimPolicy:

  • Retain (Сохранение): PV переходит в статус Released, но данные остаются нетронутыми. Том нельзя использовать повторно до ручной очистки администратором.
  • Delete (Удаление): Удаляется и объект PV в Kubernetes, и сам физический диск во внешнем хранилище (например, удаляется EBS-том в AWS).
  • ~~Recycle~~: Устаревший метод (выполнял rm -rf /thevolume/*). Сейчас заменен динамическим выделением.
  • Пример статического манифеста (для экзамена CKA)

    На экзамене часто просят создать локальный PV (тип hostPath). Помните, что hostPath подходит только для тестов на одном узле.

    Container Storage Interface (CSI) и Динамическое выделение

    Статическое выделение не масштабируется. В крупных кластерах администраторы не создают диски вручную. Здесь на сцену выходит Dynamic Provisioning (динамическое выделение) и объект StorageClass.

    Что такое CSI?

    Исторически код для интеграции с облачными дисками (AWS, GCP, VMware) был вшит прямо в исходный код Kubernetes (in-tree плагины). Это замедляло разработку и раздувало ядро системы.

    > CSI (Container Storage Interface) — это стандартный API, который позволяет провайдерам хранилищ писать свои драйверы как независимые приложения (out-of-tree), разворачиваемые в кластере в виде обычных подов (часто через DaemonSet).

    StorageClass: автоматизация создания дисков

    StorageClass — это профиль хранилища, который описывает, какой CSI-драйвер использовать и с какими параметрами (например, тип диска SSD или HDD, зона доступности).

    Важное свойство: volumeBindingMode: WaitForFirstConsumer. По умолчанию диск создается в момент создания PVC. Но если кластер размазан по нескольким зонам доступности (AZ), диск может создаться в Zone A, а планировщик (kube-scheduler) решит запустить под в Zone B. Возникнет конфликт. WaitForFirstConsumer заставляет контроллер хранилища ждать, пока планировщик не выберет узел для пода, и только тогда создает диск в нужной зоне.

    !Процесс динамического выделения диска

    Шпаргалка администратора: Траблшутинг хранилищ

    На экзамене CKA и в реальной работе вы часто будете сталкиваться с проблемами монтирования.

    1. Проверка статусов:

    Идеальное состояние PVC — Bound. Если PVC висит в статусе Pending, значит контроллер не может найти подходящий PV или StorageClass не может его создать.

    2. Анализ причин Pending:

    Ищите секцию Events. Типичные ошибки:

  • FailedBinding: Нет PV с нужным capacity или accessModes.
  • WaitForFirstConsumer: Это не ошибка. PVC ждет, пока вы создадите Pod, который использует этот PVC.
  • 3. Безопасное удаление: Если вы удалите PVC, который сейчас смонтирован в работающий Pod, Kubernetes включит защиту Storage Object in Use Protection. PVC перейдет в статус Terminating и зависнет в нем, пока вы не удалите Pod.

    5. Конфигурация приложений: использование ConfigMaps, Secrets и переменных окружения

    Конфигурация приложений: использование ConfigMaps, Secrets и переменных окружения

    Представьте ситуацию: вы собрали идеальный Docker-образ вашего приложения, развернули его в кластере, и всё работает. Но вдруг администратор базы данных сообщает, что пароль или URL для подключения изменились. Если эти данные «зашиты» внутри образа, вам придется пересобрать образ, перетестировать его и заново развернуть. Это долго, неэффективно и нарушает один из главных принципов методологии Twelve-Factor App: строгое разделение кода и конфигурации.

    В Kubernetes эта проблема решается элегантно: контейнеры остаются неизменными (stateless-шаблонами), а конфигурация внедряется в них на этапе запуска (в момент создания Pod) с помощью специальных объектов API — ConfigMaps и Secrets.

    ConfigMap: хранилище открытых данных

    ConfigMap — это объект Kubernetes, предназначенный для хранения неконфиденциальных данных в формате «ключ-значение» (key-value).

    Чаще всего в ConfigMap хранят:

  • Переменные окружения (например, LOG_LEVEL=DEBUG).
  • Конфигурационные файлы целиком (например, nginx.conf или application.properties).
  • Аргументы командной строки для запуска контейнера.
  • > Важный инсайт для CKA: Максимальный размер одного ConfigMap (как и Secret) ограничен . Это связано с ограничениями хранилища etcd. Если ваша конфигурация больше, её следует хранить во внешнем хранилище или разбивать на части.

    Декларативный и императивный подходы

    Вы можете создать ConfigMap через YAML-манифест:

    Однако на экзамене CKA время ограничено. Намного быстрее использовать императивные команды:

    Secrets: работа с чувствительными данными

    Secret работает точно так же, как ConfigMap, но предназначен для хранения конфиденциальной информации: паролей, OAuth-токенов, SSH-ключей и TLS-сертификатов.

    Главное отличие на уровне манифеста заключается в том, что данные в Secret (в секции data) должны быть закодированы в формате Base64.

    Разрушение мифа о безопасности Secrets

    > Base64 — это кодирование, а не шифрование. Любой, кто имеет доступ к манифесту Secret, может декодировать его значения командой echo "YWRtaW4=" | base64 --decode.

    Почему же тогда используется Base64? Исключительно для того, чтобы безопасно передавать бинарные данные (например, сертификаты) или спецсимволы внутри текстовых форматов JSON/YAML, с которыми работает API Kubernetes.

    По умолчанию объекты Secret хранятся в etcd в виде обычного (незашифрованного) текста. Для реальной защиты на уровне кластера администраторы настраивают Encryption at Rest (шифрование данных в покое для etcd) и строго ограничивают доступ к ресурсам Secret через RBAC.

    Способы доставки конфигурации в Pod

    Создать ConfigMap или Secret — это только половина дела. Их нужно передать внутрь контейнера. Kubernetes предлагает два основных механизма: переменные окружения и монтирование томов (Volumes).

    !Способы доставки конфигурации в Pod

    1. Переменные окружения (Environment Variables)

    Идеально подходят для одиночных значений (URL, порты, флаги).

    Точечное внедрение (valueFrom): Вы можете выбрать конкретный ключ из ConfigMap/Secret и назначить его переменной окружения.

    Массовое внедрение (envFrom): Если в ConfigMap 10 ключей, описывать каждый долго. Можно импортировать их все разом. Ключи из ConfigMap станут именами переменных окружения.

    2. Монтирование как файлы (Volumes)

    Этот способ обязателен, если вам нужно передать целый файл конфигурации (например, prometheus.yml или tls.crt). Kubernetes создает временный том, заполняет его данными из ConfigMap/Secret и монтирует в файловую систему контейнера. Каждый ключ становится именем файла, а значение — содержимым этого файла.

    Динамическое обновление: Env vs Volumes

    Это один из самых частых вопросов на технических интервью: «Что произойдет с приложением, если я изменю ConfigMap, который уже используется запущенным подом?»

    Ответ зависит от способа доставки:

    | Характеристика | Переменные окружения (env) | Тома (volumeMounts) | | :--- | :--- | :--- | | Обновление при изменении источника | НЕТ. Процессы в Linux читают переменные окружения только при старте. | ДА. kubelet периодически синхронизирует примонтированные файлы. | | Требуется ли рестарт Pod? | Да, Pod нужно пересоздать, чтобы он подхватил новые значения. | Нет, файл обновится «на лету» (но само приложение должно уметь перечитывать файл, например, по Webhook или inotify). |

    !Синхронизация обновлений ConfigMap

    Неизменяемые конфигурации (Immutable)

    С версии Kubernetes 1.21 появилась возможность помечать ConfigMaps и Secrets как неизменяемые, добавив поле immutable: true в манифест.

    Зачем это нужно? Когда конфигурация монтируется как том, kubelet на каждой Worker Node вынужден регулярно опрашивать API-сервер, чтобы узнать, не изменился ли ConfigMap. В кластерах с тысячами подов это создает колоссальную нагрузку на kube-apiserver. Установка immutable: true отключает этот поллинг (опрос), радикально снижая нагрузку на Control Plane. Если конфигурацию нужно изменить, создается новый ConfigMap (например, app-config-v2), и Deployment обновляется для его использования.

    Резюме для подготовки к CKA

  • Используйте императивные команды (kubectl create configmap ..., kubectl create secret generic ...) для экономии времени.
  • Помните синтаксис проброса: env -> valueFrom -> configMapKeyRef / secretKeyRef.
  • Четко понимайте разницу: переменные окружения статичны после запуска пода, файлы в томах обновляются динамически силами kubelet.
  • Base64 в Secrets — это не безопасность, это кодирование для передачи данных.
  • 6. Управление доступом (RBAC), безопасность контекста и сетевые политики

    Управление доступом (RBAC), безопасность контекста и сетевые политики

    Представьте себе крепость с титановой входной дверью, внутри которой все межкомнатные двери открыты настежь, а каждый гость носит в кармане универсальную отмычку. Именно так выглядит кластер Kubernetes «из коробки». API-сервер надежно аутентифицирует входящие запросы, но по умолчанию любой под может отправить сетевой запрос любому другому поду, а контейнеры часто запускаются с правами root. В этой статье мы разберем три фундаментальных механизма, которые превращают эту открытую систему в безопасную среду с нулевым доверием (Zero Trust).

    1. RBAC: Кто, Как и Что может делать

    Управление доступом на основе ролей (Role-Based Access Control) в Kubernetes решает проблему авторизации. После того как пользователь или приложение прошли аутентификацию, RBAC определяет, разрешен ли им конкретный API-запрос.

    Архитектура RBAC строится на трех китах:

  • Subject (Субъект)Кто запрашивает доступ (User, Group или ServiceAccount).
  • Role (Роль)Что разрешено делать (набор правил).
  • Binding (Привязка)Как они связаны (назначение роли субъекту).
  • Если бы мы назначали права каждому пользователю напрямую, сложность системы росла бы лавинообразно по формуле , где — количество пользователей, а — количество разрешений. Ролевая модель снижает эту сложность, группируя разрешения.

    !Архитектура связей RBAC в Kubernetes

    Пространство имен (Namespace) против Кластера (Cluster)

    Объекты RBAC строго делятся по области видимости. Это частая ловушка на экзамене CKA.

    | Область действия | Роль | Привязка | Применение | | :--- | :--- | :--- | :--- | | Namespace | Role | RoleBinding | Доступ к ресурсам внутри одного неймспейса (Pods, Services, PVC). | | Cluster | ClusterRole | ClusterRoleBinding | Доступ к кластерным ресурсам (Nodes, PV) или ко всем неймспейсам сразу. |

    > Экзаменационный лайфхак (CKA): > Вы можете использовать RoleBinding в конкретном неймспейсе, чтобы привязать субъекта к ClusterRole. Это даст пользователю права, описанные в ClusterRole, только в рамках этого неймспейса. Это избавляет от необходимости дублировать одинаковые Role в каждом неймспейсе.

    Практика: Манифесты и проверка прав

    Рассмотрим создание сервисного аккаунта для CI/CD системы, которой нужно только читать логи подов в неймспейсе backend.

    Для проверки прав на экзамене и в жизни используется императивная команда auth can-i. Она позволяет задать вопрос API-серверу от лица любого субъекта:

    2. Security Context: Ограничение привилегий контейнера

    Если RBAC защищает API Kubernetes, то Security Context защищает узлы кластера (Worker Nodes) от вредоносного кода внутри контейнеров.

    По умолчанию процесс в контейнере запускается от имени пользователя root (UID 0). Если злоумышленник найдет уязвимость выхода из контейнера (container breakout), он получит root-доступ к самому узлу.

    Security Context можно применять на двух уровнях:

  • Pod level (spec.securityContext): применяется ко всем контейнерам и томам в поде.
  • Container level (spec.containers[].securityContext): переопределяет настройки пода для конкретного контейнера.
  • Ключевые параметры

  • runAsUser / runAsGroup: Принудительный запуск процессов от непривилегированного пользователя (например, UID 1000).
  • runAsNonRoot: Запрещает запуск контейнера, если образ требует root-прав.
  • privileged: Если true, контейнер получает почти все права хостовой машины (опасно!).
  • capabilities: Управление возможностями ядра Linux. Вместо выдачи полных root-прав, можно точечно добавить или забрать системные вызовы.
  • Пример защиты пода с веб-сервером:

    3. Network Policies: Внутренний файрвол кластера

    Как мы помним из главы про сетевое взаимодействие, CNI-плагины по умолчанию реализуют плоскую сеть: любой под может установить соединение с любым другим подом.

    NetworkPolicy — это объект API, который позволяет ограничить сетевой трафик на уровнях L3 (IP-адреса) и L4 (TCP/UDP порты).

    > Важно: NetworkPolicy работает только если ваш CNI-плагин (например, Calico, Cilium, Weave Net) поддерживает их. Если вы создадите политику в кластере с Flannel, API-сервер ее примет, но трафик фильтроваться не будет.

    Логика работы и Default Deny

    Политики оперируют двумя направлениями:

  • Ingress (входящий трафик к поду).
  • Egress (исходящий трафик от пода).
  • По умолчанию в неймспейсе действует правило Default Allow. Но как только вы применяете хотя бы одну NetworkPolicy, которая выбирает под (через podSelector), для этого пода включается режим изоляции, и весь трафик, не описанный явно в правилах, отбрасывается.

    Лучшая практика информационной безопасности — создание политики Default Deny для всего неймспейса:

    После применения этого манифеста неймспейс production становится полностью изолированным.

    !Визуализация работы сетевых политик

    Анатомия правил (Матрица доступа)

    Рассмотрим классическую задачу CKA: разрешить доступ к поду базы данных (порт 3306) только от подов с меткой app=backend из неймспейса с меткой env=prod.

    Осторожно, частая ошибка! Обратите внимание на структуру массива from в YAML: Если namespaceSelector и podSelector находятся под одним дефисом (-), они работают по логике AND (И). Трафик разрешен только если под соответствует И метке, И находится в нужном неймспейсе. Если бы они были с разными дефисами, они бы работали по логике OR (ИЛИ), разрешая доступ всем подам из нужного неймспейса ПЛЮС любым подам с нужной меткой из текущего неймспейса.

    Выводы для подготовки к CKA

    На экзамене от вас потребуется быстро находить дыры в безопасности. Запомните алгоритм:
  • Проверьте права через kubectl auth can-i.
  • Изучите securityContext в манифесте пода на предмет privileged: true или запуска от root.
  • Убедитесь, что в неймспейсе есть NetworkPolicy, ограничивающая трафик к критичным компонентам.
  • 7. Планирование ресурсов, квоты и стратегии распределения нагрузки

    Планирование ресурсов, квоты и стратегии распределения нагрузки

    Представьте ситуацию: вы разворачиваете в кластере небольшой вспомогательный скрипт. Через час на этом же узле внезапно падает production-база данных, а сам узел переходит в статус NotReady. Причина банальна — скрипт содержал утечку памяти, а Kubernetes позволил ему забрать всю доступную оперативную память узла. Чтобы кластер оставался стабильным, предсказуемым и отказоустойчивым, необходимо жестко управлять двумя аспектами: сколько ресурсов потребляет приложение и где именно оно должно работать.

    Управление ресурсами Pod: Requests и Limits

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

    * Requests (Запросы) — это гарантированный минимум ресурсов, необходимый контейнеру. Эта цифра используется только kube-scheduler на этапе планирования (Binding). Если на узле нет свободного объема ресурсов, равного сумме Requests всех подов плюс новый под, планировщик туда его не назначит. * Limits (Лимиты) — это жесткий максимум, который контейнер не может превысить. За соблюдением лимитов следит kubelet (через механизмы cgroups в Linux ядра) уже во время выполнения.

    Математика ресурсов

    В манифестах ресурсы измеряются в специфических единицах:

    * CPU (Процессорное время): Измеряется в ядрах или милликорах (millicores). Где эквивалентен одному гиперпотоку (vCPU) на облачной ВМ или одному физическому ядру на bare-metal. Значение означает половину ядра. * Memory (Память): Измеряется в байтах, но обычно используются мебибайты (Mi) или гибибайты (Gi). Важно не путать с мегабайтами (MB, где множитель 1000). В K8s стандарт — степени двойки.

    Сжимаемые и несжимаемые ресурсы

    Разница между CPU и RAM критична при достижении лимитов:

  • CPU — сжимаемый ресурс (Compressible). Если контейнер пытается превысить свой CPU Limit, он не падает. Kubelet просто начинает искусственно замедлять его работу (CPU Throttling). Приложение работает медленнее, но продолжает жить.
  • Memory — несжимаемый ресурс (Incompressible). Память нельзя «замедлить». Если контейнер превышает Memory Limit, ядро Linux немедленно убивает процесс. Под переходит в состояние OOMKilled (Out Of Memory).
  • !Визуализация OOMKilled и CPU Throttling

    Классы обслуживания (QoS Classes)

    На основе того, как вы задаете Requests и Limits, Kubernetes автоматически присваивает поду класс обслуживания (Quality of Service). Это критически важно в ситуации, когда узел исчерпал ресурсы и kubelet должен решить, кого «убить» первым (Eviction).

    | Класс QoS | Условие присвоения | Приоритет выживания | | :--- | :--- | :--- | | Guaranteed | Requests строго равны Limits для CPU и RAM во всех контейнерах пода. | Самый высокий. Убиваются последними. | | Burstable | Заданы Requests, но Limits либо больше Requests, либо не заданы вообще. | Средний. Убиваются, если нет BestEffort. | | BestEffort | Не заданы ни Requests, ни Limits. | Самый низкий. Первые кандидаты на удаление. |

    > Правильно настроенные классы QoS — основа стабильности. Критичные компоненты БД всегда должны быть Guaranteed, а фоновые задачи по обработке логов можно оставить Burstable.

    Контроль на уровне Namespace: LimitRange и ResourceQuota

    Если вы администратор кластера (CKA), вы не можете доверять разработчикам ручное прописывание лимитов. Люди склонны либо забывать о них (создавая BestEffort поды), либо запрашивать слишком много. Для защиты неймспейсов используются два объекта.

    LimitRange: Политики по умолчанию для одного Pod

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

    ResourceQuota: Глобальный лимит на Namespace

    Если LimitRange контролирует каждый отдельный под, то ResourceQuota ограничивает суммарное потребление всего неймспейса.

    Важный нюанс для экзамена: Если в неймспейсе создана ResourceQuota на CPU/RAM, создание любого пода без явного указания ресурсов (или без LimitRange в неймспейсе) будет отклонено API-сервером.

    Продвинутый шедулинг: Taints и Tolerations

    До этого мы обсуждали ресурсы. Теперь поговорим о размещении. Механизм Taints (пятна) и Tolerations (допуски) работает по принципу отторжения.

    Узел получает Taint («запах» или «замок»). Поды по умолчанию избегают таких узлов. Чтобы под смог запуститься на узле с Taint, у него должен быть соответствующий Toleration («противогаз» или «ключ»).

    !Механизм Taints и Tolerations

    Эффекты Taints

    При установке Taint указывается эффект, определяющий строгость правила:

  • NoSchedule: Жесткий запрет. Новые поды без Toleration не будут запланированы на узел. Уже запущенные поды продолжат работать.
  • PreferNoSchedule: Мягкий запрет. Планировщик постарается не помещать сюда поды, но если других вариантов нет — поместит.
  • NoExecute: Безжалостный запрет. Новые поды не планируются, а уже запущенные поды без Toleration будут немедленно выселены (Evicted) с узла.
  • Императивная команда установки Taint: kubectl taint nodes node1 gpu=true:NoSchedule

    Декларативный Toleration в спецификации Pod:

    > Инсайт архитектуры: Control Plane узлы по умолчанию имеют Taint node-role.kubernetes.io/control-plane:NoSchedule. Именно поэтому обычные поды разработчиков там не запускаются.

    Притяжение рабочих нагрузок: Affinity и Anti-Affinity

    Если Taints отталкивают поды, то механизмы Affinity (родство) их притягивают.

    Node Affinity (Родство к узлам)

    Это эволюция простого nodeSelector. Позволяет использовать логические операторы (In, NotIn, Exists) и задавать мягкие или жесткие правила.

    * requiredDuringSchedulingIgnoredDuringExecutionЖесткое правило (Hard). Если подходящего узла нет, под останется в состоянии Pending. * preferredDuringSchedulingIgnoredDuringExecutionМягкое правило (Soft). Планировщик попытается найти узел, но если не найдет, запустит под где-нибудь еще.

    (Обратите внимание на суффикс IgnoredDuringExecution — если метка узла изменится после того, как под уже запущен, под не будет выселен).

    Pod Affinity и Anti-Affinity (Родство между подами)

    Часто нужно планировать поды не относительно свойств узлов, а относительно других подов.

    * Pod Affinity: "Размести этот под там же, где работает под X". Пример: веб-сервер и локальный кэш должны быть на одном узле для минимальной сетевой задержки. * Pod Anti-Affinity: "Никогда не размещай этот под там, где уже работает под X". Пример: разнесение реплик базы данных по разным серверам для отказоустойчивости.

    !Топология Pod Anti-Affinity

    Магия topologyKey

    Ключевой параметр в правилах Pod (Anti)Affinity — это topologyKey. Он определяет границы домена отказа (failure domain).

    Если topologyKey: kubernetes.io/hostname, планировщик будет разносить поды по разным физическим серверам. Если topologyKey: topology.kubernetes.io/zone, планировщик будет разносить поды по разным дата-центрам (зонам доступности), даже если в одной зоне много свободных узлов. Это основа построения Multi-AZ (Availability Zone) кластеров.

    Комбинируя Requests/Limits (защита от перегрузки), LimitRange/ResourceQuota (административный контроль) и Taints/Affinity (интеллектуальное размещение), администратор Kubernetes создает самобалансирующуюся систему, устойчивую к отказам оборудования и ошибкам в коде приложений.

    8. Методология траблшутинга, логирование и мониторинг состояния кластера

    Методология траблшутинга, логирование и мониторинг состояния кластера

    Представьте: вы на экзамене CKA, таймер неумолимо отсчитывает время, а развернутое приложение упорно выдает 502 Bad Gateway. Паника — ваш главный враг в этой ситуации. Хаотичный ввод команд в терминал редко приводит к успеху. Эффективный администратор Kubernetes отличается от новичка не тем, что знает наизусть все возможные ошибки, а тем, что владеет строгим алгоритмом поиска первопричины.

    В этой статье мы разберем системный подход к диагностике кластера, научимся читать «следы», которые оставляют компоненты, и рассмотрим инструменты мониторинга.

    Воронка траблшутинга: принцип Top-Down

    > Главное правило диагностики Kubernetes: двигайтесь от общего к частному. Никогда не начинайте с чтения логов приложения, если вы не убедились, что узел, на котором оно запущено, вообще жив.

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

    !Воронка траблшутинга Kubernetes

    | Уровень | Что проверяем | Ключевые команды | Типичные проблемы | | :--- | :--- | :--- | :--- | | 1. Cluster / Node | Состояние узлов кластера, системные сервисы | kubectl get nodes, systemctl status kubelet | Узел в статусе NotReady, исчерпаны ресурсы диска, упал kubelet. | | 2. Pod | Статус пода, события планировщика | kubectl get pods, kubectl describe pod | Pending, ImagePullBackOff, CrashLoopBackOff, ошибки монтирования томов. | | 3. Container | Логи самого приложения внутри пода | kubectl logs | Ошибки в коде приложения, неверные переменные окружения, падение процесса. | | 4. Network | Маршрутизация, DNS, Endpoints | kubectl get svc, kubectl get endpoints | Сервис не видит поды, не работает CoreDNS, блокировка NetworkPolicy. |

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

    Уровень 1: Диагностика Worker Node и Kubelet

    Если kubectl get nodes показывает, что один из узлов находится в статусе NotReady, планировщик (kube-scheduler) перестанет назначать на него новые поды.

    Первый шаг — посмотреть события узла:

    Ищите секцию Conditions (MemoryPressure, DiskPressure, PIDPressure, Ready). Если причина не очевидна, проблема почти всегда кроется в агенте узла — kubelet.

    Поскольку kubelet работает как обычный системный сервис Linux (systemd), а не как контейнер, диагностировать его нужно средствами ОС:

    Частые причины падения kubelet: неверный путь к сертификатам, ошибка конфигурации в /var/lib/kubelet/config.yaml или выключенный swap (если не задан флаг --fail-swap-on=false).

    Уровень 2: Жизнь, смерть и события Pod'ов

    Если узлы здоровы, но приложение не работает, переходим на уровень Pod. Статус пода — ваш главный индикатор.

    Механика CrashLoopBackOff

    Один из самых раздражающих статусов — CrashLoopBackOff. Он означает, что контейнер запускается, сразу же падает (завершается с ошибкой), kubelet его перезапускает, и цикл повторяется.

    Чтобы не перегружать систему (например, если приложение падает из-за недоступности БД), Kubernetes использует экспоненциальную задержку между перезапусками.

    Формула задержки выглядит так:

    Где — время ожидания перед следующим запуском в секундах, — порядковый номер перезапуска, а — жесткий лимит в 5 минут (максимальная задержка).

    !Динамика CrashLoopBackOff

    Использование Events (событий)

    События (Events) — это хроника того, что Control Plane делал с вашим объектом. Если под висит в статусе Pending или ImagePullBackOff, логи контейнера вам не помогут (контейнер еще не создан!). Вам нужны события.

    В самом низу вывода будет таблица Events. Именно здесь вы увидите сообщения от default-scheduler (например, нет узлов, удовлетворяющих nodeAffinity) или от kubelet (ошибка скачивания образа, ошибка монтирования Secret).

    Связь с предыдущими темами: В главе 7 мы упоминали статус OOMKilled. Если под был убит ядром Linux за превышение лимита памяти, в kubectl describe pod в секции Containers -> State вы увидите Reason: OOMKilled.

    Уровень 3: Логирование контейнеров

    Когда под находится в статусе Running, но ведет себя некорректно (например, отдает HTTP 500), мы спускаемся на уровень приложения.

    Особенность многоконтейнерных подов: Если в поде работает паттерн Sidecar (например, основное приложение и сборщик метрик), команда kubectl logs выдаст ошибку, попросив указать конкретный контейнер:

    Если контейнер упал и перезапустился, вы можете посмотреть логи его предыдущего (мертвого) инстанса, добавив флаг -p (previous):

    Уровень 4: Сетевая связность и Service Discovery

    Сценарий: поды Running, логи чистые, но веб-интерфейс недоступен. Проблема на уровне сети.

    Самая частая ошибка новичков — неправильные Label Selectors в манифесте Service. Service ищет поды по меткам. Если он их находит, он создает объект Endpoints.

    > Золотое правило сетевого траблшутинга: Всегда проверяйте Endpoints. Если у Service нет Endpoints, трафик никуда не пойдет.

    Если список IP-адресов пуст, проверьте совпадение selector в Service и labels в Pod.

    Если Endpoints есть, но связи по DNS-имени нет, проверяем работу CoreDNS. Для этого на экзамене удобно запустить временный под с утилитами nslookup или dig:

    Базовый мониторинг: Metrics Server

    Для принятия решений о масштабировании и планировании ресурсов (Requests/Limits, которые мы разбирали ранее) кластеру необходимо знать текущее потребление CPU и памяти.

    Сам по себе kube-apiserver эти метрики не хранит. Для этого требуется установить аддон Metrics Server. Он собирает данные с kubelet каждого узла и предоставляет их через Metrics API.

    Без Metrics Server команды семейства kubectl top работать не будут.

    Знание этих команд критически важно для CKA: вас могут попросить найти под, потребляющий больше всего памяти, и записать его имя в файл.

    9. Справочник по командам kubectl и шаблоны ключевых YAML-манифестов

    Справочник по командам kubectl и шаблоны ключевых YAML-манифестов

    На экзамене Certified Kubernetes Administrator (CKA) у вас есть ровно минут на решение практических задач. Это означает, что на одну задачу отводится в среднем минут. Если вы начнете писать YAML-манифесты с чистого листа, вспоминая правильные отступы и названия полей, шансы на успешную сдачу стремятся к нулю. Главный навык администратора в стрессовой ситуации — умение заставить кластер написать базовый код за вас.

    В этой статье мы систематизируем инструментарий kubectl, превратив его из простого клиента в мощный генератор кода и поисковую систему по кластеру.

    Философия скорости: Императивный подход для декларативных целей

    Хотя Kubernetes построен на декларативной парадигме (мы описываем желаемое состояние в YAML, а кластер его достигает), на экзамене и в траблшутинге правит императивный подход.

    Ваш главный инструмент — связка флагов --dry-run=client и -o yaml.

    > Золотое правило CKA > Никогда не пишите манифесты с нуля. Генерируйте каркас императивной командой, сохраняйте его в файл, а затем редактируйте только специфические требования задачи.

    !Анатомия команды kubectl и процесс генерации манифеста

    Как это работает на практике:

  • Вы отдаете команду создать объект, но добавляете --dry-run=client. Это говорит kubectl: «Сформируй запрос, но не отправляй его на API-сервер».
  • Флаг -o yaml приказывает вывести сформированный объект в консоль в формате YAML.
  • Оператор > перенаправляет этот вывод в файл.
  • Навигация и контекст: Защита от фатальных ошибок

    На экзамене вы будете работать с несколькими кластерами. Выполнение правильной команды в неправильном контексте (кластере) оценивается в баллов за задачу.

    | Задача | Команда | Комментарий | |---|---|---| | Узнать текущий контекст | kubectl config current-context | Выполняйте перед каждой новой задачей. | | Посмотреть все контексты | kubectl config get-contexts | Показывает кластеры, пользователей и неймспейсы. | | Сменить контекст | kubectl config use-context <name> | Имя контекста всегда дается в начале задания. | | Задать неймспейс по умолчанию | kubectl config set-context --current --namespace=<ns> | Избавляет от необходимости писать -n <ns> в каждой команде. |

    Императивные генераторы: Шпаргалка

    Ниже собраны команды, которые мгновенно создают нужные ресурсы. Запомните глаголы: run (только для подов), create (для большинства объектов) и expose (для сервисов).

    1. Управление рабочими нагрузками (Workloads)

    2. Сеть и сервисы (Networking)

    Команда expose берет существующий объект (Pod или Deployment) и автоматически создает Service, копируя селекторы.

    3. Конфигурация и доступы (Config & RBAC)

    Искусство выборки: JSONPath и Custom Columns

    Часто в задачах просят найти узел с наибольшим потреблением ресурсов или извлечь конкретный IP-адрес пода и записать его в файл. Искать глазами в выводе kubectl describe — долго и чревато ошибками.

    Для точной выборки используется флаг -o jsonpath.

    !Интерактивный фильтр JSONPath

    Синтаксис базового запроса выглядит так: -o jsonpath='{.путь.к.полю}'. Если элементов несколько (список), используются скобки [*].

    Примеры применения на экзамене:

    Документация под рукой: kubectl explain

    На экзамене у вас есть доступ к официальной документации (kubernetes.io/docs), но поиск по сайту занимает время. Встроенная команда kubectl explain — это ваш оффлайн-справочник по структуре любого YAML-манифеста.

    Если вы забыли, куда вписать securityContext или как настроить livenessProbe, используйте:

    Каркасы ключевых YAML-манифестов

    Даже с императивными командами некоторые вещи (например, монтирование томов или сложный nodeAffinity) придется дописывать руками. Ниже представлены минималистичные, очищенные от лишнего мусора шаблоны, которые нужно уметь быстро модифицировать.

    1. Pod с ресурсами и томами

    Этот шаблон покрывает задач на модификацию подов: лимиты, переменные окружения и базовые тома.

    2. NetworkPolicy (Default Deny & Allow Specific)

    Сетевые политики нельзя сгенерировать императивно. Их структуру нужно понимать. Этот шаблон закрывает неймспейс и открывает только порт для подов с меткой role: frontend.

    3. PersistentVolume (PV) и PersistentVolumeClaim (PVC)

    Связка хранилища. Запомните: PV — это ресурс кластера (нет namespace), PVC — ресурс проекта (есть namespace).

    Освоив генерацию каркасов и точечную навигацию по документации через explain, вы сэкономите десятки минут на экзамене и сможете сфокусироваться на архитектурной логике задач, а не на борьбе с синтаксисом YAML.