Kubernetes это система, которой ты говоришь, какое состояние хочешь, а она постоянно приводит реальность к нему. На собесе почти всегда просят нарисовать компоненты кластера и рассказать, что происходит после kubectl apply.
Декларативная модель
Ты не командуешь «запусти три контейнера». Ты описываешь объект: «Deployment api, 3 реплики, образ такой-то», и сохраняешь его в кластере. Дальше контроллеры в бесконечном цикле сравнивают желаемое (spec) с текущим (status) и устраняют разницу. Упал под, узел исчез, кто-то удалил реплику: контроллер создаст недостающее. Этот цикл называют reconciliation loop.
У каждого объекта есть apiVersion, kind, metadata (имя, namespace, метки, аннотации), spec (что хотим) и status (что есть, заполняет система).
Control plane
- kube-apiserver: единственная точка входа. Все (kubectl, контроллеры, kubelet) общаются с кластером через его REST API. Он проверяет аутентификацию, авторизацию (RBAC), прогоняет admission-контроллеры и сохраняет объекты в etcd. Других путей к etcd нет.
- etcd: распределённое key-value хранилище на Raft, хранит всё состояние кластера. Для отказоустойчивости 3 или 5 узлов (нужен кворум: большинство). Потерять etcd без бэкапа значит потерять кластер.
- kube-scheduler: смотрит на поды без назначенного узла и выбирает узел: отсеивает неподходящие (ресурсы, nodeSelector, affinity, taints), ранжирует оставшиеся и записывает решение (
nodeName) через API. Сам ничего не запускает. - kube-controller-manager: набор контроллеров: Deployment, ReplicaSet, Node, Job, EndpointSlice, ServiceAccount и другие. Каждый следит за своими объектами и приводит их к спецификации.
- cloud-controller-manager: связь с облаком: балансировщики для Service
LoadBalancer, маршруты, информация об узлах.
Рабочие узлы
- kubelet: агент на каждом узле. Видит поды, назначенные его узлу, и через CRI просит рантайм их запустить. Выполняет probes, монтирует тома, отправляет статус подов и узла в API.
- Container runtime: containerd или CRI-O. Docker как рантайм (dockershim) удалён из Kubernetes в версии 1.24, но образы, собранные Docker, работают: это стандарт OCI.
- kube-proxy: реализует Service на узле: правила iptables или IPVS (или их делает CNI-плагин, например Cilium на eBPF), чтобы трафик на виртуальный IP сервиса уходил на поды.
- CNI-плагин (Calico, Cilium, Flannel и другие): даёт поду IP и связность между подами на разных узлах.
Сетевая модель
Каждый под получает свой IP. Любой под может достучаться до любого пода по его IP без NAT. Реализует это CNI-плагин. Ограничивают трафик NetworkPolicy (если CNI их поддерживает).
Что происходит после kubectl apply
- kubectl отправляет манифест Deployment в API server.
- API server аутентифицирует, авторизует, прогоняет admission (мутации, валидации, политики) и сохраняет объект в etcd.
- Контроллер Deployment видит новый Deployment и создаёт ReplicaSet.
- Контроллер ReplicaSet создаёт объекты Pod (пока без узла).
- Scheduler выбирает узлы и записывает
nodeName. - kubelet на узле видит свой под, через CRI скачивает образ и запускает контейнеры, настраивает сеть через CNI и тома.
- kubelet обновляет статус пода; после readiness probe под попадает в EndpointSlice сервиса.
Все компоненты общаются через API server и watch: подписку на изменения объектов. Никто не вызывает друг друга напрямую.
Namespaces, метки, аннотации
- Namespace делит кластер логически: имена, квоты, права. Не изолирует сеть сам по себе.
- Labels (
app: api,env: prod) нужны для выборки: Service находит поды по селектору, Deployment свои поды,kubectl get pods -l app=api. - Annotations хранят произвольные метаданные для инструментов (не для выборки).
kubectl: основы
kubectl get pods -n prod -o wide
kubectl describe pod api-7c9f -n prod
kubectl apply -f deploy.yaml
kubectl get events -n prod --sort-by=.lastTimestamp
kubectl explain deployment.spec.strategy
kubectl config use-context prod
apply декларативный (создаёт или обновляет по манифесту), create императивный (упадёт, если объект уже есть).
Что будет, если сломается
- Упал API server: работающие поды продолжают работать, но изменения невозможны, контроллеры и scheduler ждут.
- Потерян кворум etcd: кластер только для чтения или недоступен для записи.
- Упал узел: через таймаут контроллер узлов пометит его недоступным, поды будут вытеснены, и ReplicaSet создаст замену на других узлах.
- Упал kubelet: контейнеры на узле работают, но статус не обновляется и узел станет NotReady.
Частые ошибки
- Думать, что scheduler запускает контейнеры (это kubelet).
- Думать, что компоненты ходят в etcd напрямую (только API server).
- Путать namespace с сетевой изоляцией.
- Использовать
createи ручные правки в проде вместо декларативных манифестов в git.
Что спросят на собесе
- Из каких компонентов состоит кластер и что делает каждый.
- Что происходит после
kubectl apply -f deployment.yaml. - Зачем etcd нечётное число узлов.
- Что такое reconciliation loop.
- Что будет с подами, если упадёт control plane.