1. Архитектура Kubernetes: компоненты Control Plane и узлов инфраструктуры
Вы вводите в терминале команду kubectl run web --image=nginx и нажимаете Enter. Через пару секунд терминал сообщает: pod/web created. Для пользователя это выглядит как мгновенная магия, но под капотом разворачивается сложнейшая хореография распределенной системы. Десятки компонентов обмениваются сертификатами, опрашивают базы данных, оценивают свободную оперативную память на серверах и настраивают правила маршрутизации ядра Linux. Понимание того, кто именно, в какой последовательности и на каком сервере выполняет эту работу — фундаментальный навык для сдачи экзамена CKA и ежедневного администрирования Kubernetes.
Kubernetes не является монолитным приложением. Это набор независимых бинарных файлов (процессов), которые общаются друг с другом исключительно через REST API. Концептуально кластер разделен на две большие части: Control Plane (плоскость управления, или управляющие узлы) и Worker Nodes (рабочие узлы).
Control Plane принимает глобальные решения по кластеру (например, на каком узле запустить приложение), обнаруживает события и реагирует на них. Worker Nodes — это «рабочие лошадки», которые непосредственно запускают контейнеры с вашим кодом и обеспечивают их сетевую доступность.
!Архитектура компонентов Kubernetes
Компоненты Control Plane: мозг кластера
В Production-средах компоненты Control Plane обычно разворачиваются на нескольких выделенных серверах для обеспечения отказоустойчивости (High Availability). Если падает один управляющий узел, кластер продолжает работу. В рамках подготовки к CKA важно досконально знать зону ответственности каждого из четырех главных компонентов Control Plane.
kube-apiserver: центральный узел связи
kube-apiserver — это фасад всего кластера. Это единственный компонент, с которым взаимодействует администратор (через утилиту kubectl), и единственный компонент, который имеет право напрямую читать и писать в базу данных состояния кластера (etcd).
Все остальные компоненты, будь то планировщик, контроллеры или агенты на рабочих узлах, не общаются друг с другом напрямую. Они постоянно опрашивают API-сервер (механизм watch) на предмет изменений.
Ключевые функции kube-apiserver:
API-сервер спроектирован так, чтобы масштабироваться горизонтально. Он не хранит состояние внутри себя (stateless). Вы можете запустить 2, 3 или 10 экземпляров kube-apiserver за балансировщиком нагрузки, и они будут работать корректно, так как единым источником истины выступает внешнее хранилище. По умолчанию API-сервер слушает защищенный порт 6443.
etcd: память кластера
Если kube-apiserver — это мозг, то etcd — это его память. Это распределенное, строго согласованное (strongly consistent) хранилище типа «ключ-значение» (key-value store). В нем хранится абсолютно всё состояние кластера: какие узлы подключены, какие поды должны работать, какие секреты и конфигурации существуют.
Для обеспечения отказоустойчивости etcd работает в кластерном режиме (обычно 3 или 5 узлов) и использует алгоритм консенсуса Raft. Чтобы кластер etcd мог принимать решения (например, записывать новые данные), необходимо, чтобы большинство узлов (кворум) были живы и могли договориться. Формула кворума: , где — общее количество узлов etcd. При трех узлах кворум равен 2. Если два узла из трех выйдут из строя, etcd перейдет в режим «только чтение», и API-сервер Kubernetes не сможет создавать или изменять объекты.
Особенности etcd в контексте администрирования:
etcd между собой.etcd означает полную потерю кластера Kubernetes, даже если все контейнеры на рабочих узлах продолжают физически работать.kube-scheduler: логистика и планирование
Когда вы просите Kubernetes создать Pod (минимальную единицу развертывания), API-сервер просто сохраняет запись об этом в etcd. У этого Pod'а в поле nodeName (имя узла) изначально пусто.
kube-scheduler — это компонент, который непрерывно следит за API-сервером в поисках Pod'ов без назначенного узла. Как только он находит такой Pod, его задача — выбрать оптимальный сервер для запуска.
Процесс выбора узла состоит из двух этапов:
Узел с максимальным баллом выбирается победителем. Планировщик отправляет API-серверу запрос на обновление Pod'а (операция Binding), вписывая имя выбранного сервера в поле nodeName. На этом работа планировщика заканчивается — он не запускает контейнеры.
kube-controller-manager: поддержание желаемого состояния
В Kubernetes применяется декларативный подход: вы описываете желаемое состояние системы (Desired State), а кластер сам приводит текущее состояние (Current State) к желаемому. За эту работу отвечает kube-controller-manager.
Это единый бинарный файл, внутри которого в виде отдельных потоков (goroutines) работают десятки различных контроллеров. Каждый контроллер отвечает за свой тип объектов. Они работают в бесконечном цикле (Control Loop), постоянно сравнивая желаемое состояние с текущим. Если , контроллер предпринимает действия для устранения разницы.
Ключевые контроллеры внутри менеджера:
kubelet на узле перестает присылать сигналы жизни (heartbeats), Node Controller ждет определенное время (по умолчанию 40 секунд), помечает узел как NotReady, а еще через 5 минут начинает процесс принудительного удаления (eviction) Pod'а с этого узла.Компоненты Worker Node: исполнители на местах
Рабочие узлы — это серверы, на которых выполняется полезная нагрузка. Компоненты на этих узлах отвечают за поддержание работы Pod'ов и обеспечение сетевой связности.
kubelet: капитан узла
kubelet — это главный агент Kubernetes, который работает на каждом узле кластера (включая управляющие узлы). В отличие от большинства других компонентов, которые запускаются в виде контейнеров, kubelet обычно устанавливается как системный сервис (systemd daemon) прямо в операционную систему сервера.
Его главная задача — убедиться, что контейнеры, описанные в спецификации Pod'а, запущены и здоровы.
Как работает kubelet:
kube-scheduler назначает Pod на его узел, kubelet скачивает спецификацию этого Pod'а (PodSpec).Важный нюанс для экзамена CKA: kubelet может запускать Pod'ы не только по команде от API-сервера. Если положить YAML-манифест Pod'а в специальную директорию на сервере (обычно /etc/kubernetes/manifests/), kubelet прочитает файл и запустит так называемый Static Pod. Именно таким образом утилита kubeadm разворачивает компоненты Control Plane (kube-apiserver, etcd, kube-scheduler, kube-controller-manager) — как статические поды, которыми управляет локальный kubelet на мастер-узле.
Container Runtime: двигатель контейнеров
Сам по себе Kubernetes не умеет запускать контейнеры. Ему нужен сторонний софт, который умеет работать с пространствами имен Linux (namespaces) и контрольными группами (cgroups). Для стандартизации взаимодействия kubelet с различными средами выполнения был создан интерфейс CRI (Container Runtime Interface).
Исторически Kubernetes использовал Docker, но сейчас поддержка Docker как среды выполнения (Dockershim) удалена. В современных кластерах используются среды, напрямую реализующие CRI:
Container Runtime отвечает за стягивание образов из реестров (например, Docker Hub), распаковку слоев, настройку изоляции на уровне ядра ОС и непосредственный запуск процессов.
kube-proxy: сетевой регулировщик
Каждый Pod в Kubernetes получает свой собственный IP-адрес. Однако Pod'ы эфемерны: они удаляются, пересоздаются на других узлах и получают новые IP-адреса. Чтобы приложения могли стабильно общаться друг с другом, используются Сервисы (Services) — абстракции, предоставляющие постоянный виртуальный IP-адрес (ClusterIP), балансирующий трафик на группу динамических Pod'ов.
За реализацию этой магии отвечает kube-proxy. Это сетевой агент, работающий на каждом узле.
Он следит за API-сервером на предмет создания новых Сервисов или изменения Endpoints (IP-адресов Pod'ов). Когда происходит изменение, kube-proxy не маршрутизирует трафик сам (он не является прокси-сервером в классическом понимании). Вместо этого он программирует сетевой стек ядра Linux на своем узле.
kube-proxy может работать в нескольких режимах:
Симфония компонентов: жизненный цикл создания Pod'а
Чтобы по-настоящему понять архитектуру, нужно проследить, как компоненты взаимодействуют во времени. Рассмотрим пошагово, что происходит после выполнения команды kubectl run.
!Процесс создания Pod'а: взаимодействие компонентов
kubectl формирует JSON-объект, описывающий Pod, и отправляет POST-запрос на порт 6443 компоненту kube-apiserver.etcd. На этот момент статус Pod'а — Pending (в ожидании), а поле nodeName пустое. API-сервер отвечает kubectl, что Pod успешно создан (хотя контейнеры еще не запущены).kube-scheduler через механизм watch видит новый Pod без узла. Он выполняет фильтрацию и оценку, выбирает, например, worker-node-2, и отправляет API-серверу запрос на привязку (Binding).etcd, указывая, что Pod теперь привязан к worker-node-2.kubelet на узле worker-node-2 через свой watch-канал замечает, что ему назначен новый Pod.kubelet обращается к Container Runtime (например, containerd) через интерфейс CRI с командой запустить контейнеры.kubelet отправляет API-серверу обновление статуса: Pod переходит в состояние Running. API-сервер сохраняет этот статус в etcd.На протяжении всего этого процесса ни один компонент не общался с другим напрямую. Все взаимодействия происходили исключительно через kube-apiserver.
Диагностика компонентов: взгляд администратора
На экзамене CKA вам часто придется сталкиваться со сломанными кластерами. Понимание архитектуры позволяет быстро локализовать проблему.
Если вы создаете Deployment, но Pod'ы даже не появляются в списке (kubectl get pods ничего не выдает), проблема скорее всего в kube-controller-manager. Именно он должен был увидеть Deployment и создать ReplicaSet, который в свою очередь создал бы Pod'ы.
Если Pod'ы появились, но висят в статусе Pending, это классический симптом проблем с kube-scheduler (он не работает) или нехватки ресурсов в кластере (планировщик работает, но фильтрация отбросила все узлы).
Если Pod назначен на узел (поле NODE в выводе kubectl get pods -o wide заполнено), но статус застрял на ContainerCreating, проблема находится на конкретном рабочем узле. Виноват либо kubelet (не может связаться с API-сервером), либо Container Runtime (не может скачать образ из интернета), либо сетевой плагин CNI (не может выдать IP-адрес).
В кластерах, развернутых с помощью kubeadm, компоненты Control Plane работают как статические поды в пространстве имен kube-system. Вы можете проверить их статус обычной командой:
kubectl get pods -n kube-system
Если API-сервер недоступен, команда kubectl перестанет работать. В этом случае диагностику нужно проводить прямо на сервере Control Plane. Так как kubelet управляет статическими подами, его логи — первый источник правды. На узле с ОС Linux это делается командой systemd:
journalctl -u kubelet -f
Также можно проверить статус контейнеров компонентов напрямую через утилиту crictl (клиент командной строки для CRI), которая работает в обход Kubernetes:
crictl ps
Архитектура Kubernetes, несмотря на кажущуюся сложность, построена на элегантном принципе разделения обязанностей и декларативного управления состоянием. Понимание роли каждого винтика в этом механизме — от kube-apiserver до kube-proxy — превращает кластер из «черного ящика» в предсказуемую и управляемую систему, готовую к любым операционным вызовам.