1. Декларативный подход и архитектура Control Plane: как Kubernetes управляет состоянием системы
Декларативный подход и архитектура Control Plane: как Kubernetes управляет состоянием системы
Представьте, что в вашем кластере работает 100 контейнеров с критически важным приложением. В 3 часа ночи один из серверов физически выходит из строя, унося с собой 15 контейнеров. В традиционной инфраструктуре система мониторинга разбудила бы дежурного инженера, которому пришлось бы вручную запускать упавшие процессы на других серверах. В Kubernetes инженер продолжит спать, а к утру система сама восстановит нужное количество контейнеров. Этот фокус возможен благодаря фундаментальной концепции, лежащей в основе Kubernetes — декларативному подходу к управлению состоянием.
Императивный vs Декларативный подход
Чтобы понять Kubernetes, нужно изменить способ мышления с ответов на вопрос «Как сделать?» на ответ «Что я хочу получить?».
Императивный подход — это последовательность команд. Вы пишете скрипт: скачай образ, создай сеть, запусти контейнер А, затем контейнер Б. Если скрипт прервется на середине, система останется в непредсказуемом состоянии. Скрипт нужно писать с учетом всех возможных ошибок.
Декларативный подход — это описание конечного результата. Вы не говорите системе, как запускать контейнеры. Вы передаете ей манифест (обычно в формате YAML), в котором зафиксировано желаемое состояние (Desired State).
> Декларативность в Kubernetes означает, что администратор описывает, как должна выглядеть система в идеале, а сама платформа непрерывно работает над тем, чтобы привести текущее состояние (Actual State) в соответствие с желаемым.
| Характеристика | Императивный подход (скрипты, CLI) | Декларативный подход (Kubernetes YAML) |
| :--- | :--- | :--- |
| Суть | Инструкция к действию (Do this, then that) | Чертеж результата (Make it look like this) |
| Обработка сбоев | Требует сложной логики if/else в скриптах | Встроена в систему: отклонение от чертежа вызывает автоисправление |
| Идемпотентность | Повторный запуск скрипта может вызвать ошибку (контейнер уже существует) | Повторное применение манифеста безопасно: система скажет «уже сделано» |
Пример декларативного требования:
Здесь мы заявляем: «В любой момент времени должно работать ровно 3 копии web-server». Если их 2 — система создаст еще одну. Если 4 — убьет лишнюю.
Но кто именно читает этот файл и принимает решения? Для этого нам нужно заглянуть под капот кластера.
Архитектура кластера: Мозг и Мышцы
Любой кластер Kubernetes логически разделен на две части: Control Plane (управляющий слой, «мозг») и Worker Nodes (рабочие узлы, «мышцы»).
!Архитектура Kubernetes: компоненты Control Plane и Worker Nodes
Control Plane: Управляющий слой
Control Plane принимает глобальные решения по кластеру (например, планирование) и обнаруживает события кластера (например, запуск новых подов при падении старых). На технических интервью архитектуру Control Plane спрашивают почти всегда. Она состоит из четырех ключевых компонентов.
1. kube-apiserver (API-сервер)
Это входная дверь в кластер. Когда вы выполняете команду kubectl apply -f config.yaml, запрос идет именно сюда.
* Это единственный компонент, который имеет право напрямую читать и писать в базу данных кластера.
* Все остальные компоненты (как управляющие, так и рабочие) общаются друг с другом только через API-сервер. Это обеспечивает единую точку валидации и авторизации запросов.
2. etcd (Хранилище состояний) Это распределенное, надежное key-value хранилище. Это «память» кластера. * Здесь хранится вся конфигурация и всё желаемое состояние системы. * Если данные не сохранены в etcd — для Kubernetes их не существует. Интервью-факт:* etcd использует алгоритм консенсуса Raft, поэтому для обеспечения отказоустойчивости кластера (High Availability) требуется нечетное количество узлов etcd (обычно 3 или 5), чтобы они могли выбрать лидера.
3. kube-controller-manager (Менеджер контроллеров)
Это набор фоновых процессов (контроллеров), которые непрерывно следят за состоянием кластера.
* Именно они реализуют ту самую декларативность. Они сравнивают Desired State (из etcd) с Actual State (реальным положением дел).
* Например, Node Controller следит за тем, живы ли серверы. ReplicaSet Controller следит, чтобы количество запущенных копий приложения совпадало с цифрой replicas в манифесте.
4. kube-scheduler (Планировщик) Его единственная задача — находить дом для новых контейнеров. * Когда вы просите создать новый Pod (группу контейнеров), он изначально не привязан ни к какому серверу. * Scheduler анализирует требования пода (нужно 2 ГБ памяти и 1 ядро CPU), смотрит на свободные ресурсы рабочих узлов и назначает под на наиболее подходящий узел. Сам запускать ничего он не умеет — он только ставит «штамп» с именем узла.
Worker Nodes: Рабочие узлы
Это серверы, на которых непосредственно выполняются ваши приложения.
1. kubelet
«Капитан» рабочего узла. Это агент, который работает на каждом сервере и общается с kube-apiserver. Он получает инструкции (какие поды должны здесь работать) и следит за тем, чтобы контейнеры были запущены и здоровы. Если контейнер падает, kubelet пытается его перезапустить локально.
2. kube-proxy Сетевой прокси-сервер на каждом узле. Он поддерживает сетевые правила (через iptables или IPVS), которые позволяют сетевому трафику достигать ваших контейнеров как изнутри кластера, так и снаружи.
3. Container Runtime (Среда выполнения контейнеров) Программа, которая непосредственно запускает контейнеры (изолирует процессы, выделяет им память и сеть). Kubernetes поддерживает различные среды: containerd, CRI-O.
Сердце системы: Цикл согласования (Reconciliation Loop)
Все эти компоненты не ждут прямых команд друг от друга. Они работают по принципу подписки на события (Watch) и образуют бесконечный цикл согласования — Reconciliation Loop.
Архитектура Kubernetes построена на модели конечных автоматов, работающих асинхронно. Процесс состоит из трех шагов:
!Цикл согласования в Kubernetes
Давайте посмотрим, как компоненты взаимодействуют при развертывании приложения:
replicas: 3 в kube-apiserver.created. Дальше система работает асинхронно.node-1 и node-2).node-1 постоянно слушает API-сервер. Он видит: «О, появился под, назначенный на мой узел!». Kubelet обращается к Container Runtime, скачивает образ и запускает контейнеры.Если node-1 сгорит, kubelet перестанет отправлять сигналы жизни (heartbeats). Controller Manager через некоторое время заметит это, поймет, что Actual State (остался 1 живой под на node-2) больше не совпадает с Desired State (нужно 3), и цикл начнется заново: контроллер создаст новые поды, планировщик найдет для них живые узлы, а новые kubelet-ы их запустят.
Именно этот асинхронный, основанный на событиях дизайн делает Kubernetes такой устойчивой к сбоям системой. В следующих главах мы подробнее разберем, как именно рождается Pod и какие конкретно контроллеры обеспечивают самовосстановление системы.