← Kubernetes: основы
5 мин · intro · Урок 3 из 11

Архитектура кластера

Кто с кем общается в кластере. Большая схема и короткие описания компонентов.

Kubernetes — не одна программа, а семь-восемь процессов, которые разнесены по нодам и разговаривают по сети. У них одно правило общения: всё идёт через apiserver. Никто никому напрямую.

Карта

kubectl CLI на твоём ноуте control plane kube-apiserver REST, единственная дверь etcd состояние кластера kube-scheduler выбирает ноду поду controller-mgr цикл сверки cloud-ctrl-mgr managed only HTTPS состояние watch + bind облачные ресурсы worker-нода kube-proxy nftables/iptables для Service kubelet агент ноды containerd runtime CNI plugin pod network svc + endpoints pods + status CRI CNI

kubectl — просто CLI

kubectl читает ~/.kube/config, берёт оттуда адрес и сертификат, делает обычный HTTPS-запрос к kube-apiserver. Никакой магии внутри нет: то же самое можно дёрнуть через curl и получить тот же JSON. Всю настоящую работу делает apiserver, kubectl только удобно печатает ответ.

Сам манифест kubectl всё же читает: разбирает YAML, ругается на битый отступ и на отсутствующие apiVersion или kind. А вот схему полей с версии 1.27 проверяет apiserver — раньше это делал kubectl по скачанной OpenAPI-схеме, но та врала на части полей, и опечатки проскакивали. Поэтому contaienrs вместо containers теперь отвергает сервер.

Кто за что отвечает

kube-apiserver

REST-фасад поверх etcd, валидация, аутентификация, RBAC. Все остальные компоненты ходят сюда и больше никуда. На прод-кластерах apiserver почти всегда дублируется (обычно 3 инстанса за балансировщиком) ради HA.

etcd

Распределённая key-value база на Raft, держит всё состояние кластера: объекты, секреты, ConfigMap, RBAC. apiserver сам stateless, реальные данные лежат тут. В проде запускают 3 или 5 нод для кворума по Raft, в локалке хватит одной.

kube-scheduler

Watch'ит поды без nodeName и решает, на какую ноду их положить. Учитывает запрошенные ресурсы, taint'ы, affinity, приоритеты. Когда нашёл место, делает bind через apiserver, дальше под подхватывает kubelet нужной ноды.

controller-manager

Один бинарник, внутри десятки контроллеров: Deployment, ReplicaSet, Job, Node, Endpoints. Каждый сравнивает желаемое (5 реплик) с реальным (3 реплики) и докручивает разницу через apiserver. По-английски это называется reconcile loop, по-русски обычно говорят «цикл сверки». На нём держится весь куб.

cloud-controller-manager

Появляется только на managed-кластерах (Yandex Managed Kubernetes, Selectel, EKS, GKE, AKS) и на кластерах с настроенным cloud-provider. Превращает k8s-объекты в облачные ресурсы: Service type=LoadBalancer становится облачным балансировщиком (Yandex Network LB, AWS NLB, GCP LB), PersistentVolume цепляет облачный диск (Yandex Compute Disk, EBS, GCE PD), маршруты к подам прописываются в VPC. На bare-metal этого процесса просто нет.

kubelet

Агент на каждой ноде. Watch'ит «свои» поды через apiserver, говорит контейнерному рантайму запустить образ, монтирует тома, шлёт обратно heartbeat и статус. Если heartbeat не приходит около 50 секунд, нода уходит в Unknown. Порог задаётся флагом --node-monitor-grace-period у controller-manager и настраивается.

kube-proxy

Тоже на каждой ноде. Слушает Service и Endpoints через apiserver и переписывает правила ядра так, чтобы ClusterIP резолвился в реальные поды через DNAT.

Режимов у него три. iptables — исторический дефолт, с 1.33 он переведён в режим поддержки: новых возможностей не будет, чинят только баги. ipvs появился как ответ на медленную работу iptables на больших кластерах. nftables дошёл до GA в 1.33 и стал тем, куда развитие идёт дальше: правила обновляются быстрее, и деградации на тысячах Service нет.

Эту работу всё чаще заменяют на Cilium с eBPF — быстрее, скейлится лучше, без iptables-боли.

container runtime

Реально запускает контейнеры. kubelet общается с ним по CRI (gRPC-протокол), runtime тянет образ из registry и стартует процесс через runc. Стандарт сегодня containerd, альтернатива CRI-O. В k8s 1.24 убрали dockershim (прослойку для общения с Docker), но образы, собранные через Docker, работают как и раньше — это обычные OCI-образы.

CNI plugin

Выдаёт каждому поду уникальный IP и прописывает маршруты между нодами. В простом случае kubelet зовёт CNI-плагин через exec (Calico, Cilium и подобные часто работают как агент-демон и общаются иначе). Реализаций много: Calico, Cilium, Flannel, AWS VPC CNI. Без CNI поды не общаются между нодами.

CNI и kube-proxy — разные слои: CNI даёт pod-сеть, kube-proxy поверх делает Service. Но Cilium и Calico в eBPF-режиме умеют делать обе работы сразу — в таких кластерах отдельный kube-proxy не запускают, всё закрывает eBPF-датаплейн CNI-плагина.

Hub-and-spoke

Все стрелки на схеме идут через apiserver. etcd и kubelet никогда не общаются напрямую, scheduler не лезет в kubelet, controller-manager не лезет в etcd. Любой обмен — REST к apiserver и watch на изменения.

Из этого следует две вещи. Apiserver самая нагруженная часть control plane, поэтому в проде его обычно 3 инстанса за LB. И apiserver самая важная точка отказа: лёг он, и кластером нельзя управлять, хотя поды на нодах продолжают работать сами по себе.

Managed vs bare-metal

На Yandex Managed Kubernetes, Selectel, EKS, GKE, AKS control plane спрятан целиком — платишь облаку, видишь только worker-ноды и endpoint apiserver'а. На bare-metal-кластере ты сам поднимаешь и обслуживаешь весь control plane, и cloud-controller-manager обычно не запускаешь.

Дальше разбираем Pod: что внутри, зачем контейнеры объединяют в один Pod и как kubelet его собирает.

Дрилл · вопросы как на собесе

Проверь себя без подсказок

Сформулируй ответ вслух или письменно, потом раскрой и честно отметь: знал или нет.

01

Что такое узел (нода) в кластере?

K8S-009

Прошли материал до конца? Отметьте урок пройденным.