Модуль 1 / 19
Архитектура, control plane, узел и reconciliation
Содержание
1. Цели и результат модуля
После модуля вы сможете объяснить путь запроса от kubectl до работающего контейнера, различать обязанности API Server, etcd, scheduler, controllers, kubelet и container runtime, а также доказать reconciliation наблюдениями в живом кластере.
- Kubernetes управляет желаемым состоянием через API и control loops
- API Server — единственная поддерживаемая точка входа в состояние кластера
- etcd хранит согласованное состояние, но не запускает контейнеры
- scheduler выбирает узел, controller создаёт намерение, kubelet реализует Pod на узле
- одноузловой кластер подходит для Fundamentals, но не является HA
2. Теория: Kubernetes как система управления состоянием
Пользователь не просит Kubernetes выполнить длинную последовательность императивных действий. Он отправляет объект с desired state. Control plane сохраняет намерение, сравнивает его с observed state и повторяет попытки сблизить состояния. Этот процесс называется reconciliation.
Успешный ответ API означает, что объект принят и сохранён, а не то, что приложение уже доступно. Фактический результат отражают status, conditions, связанные объекты, Events и пользовательская проверка трафика. Разрыв между spec и status — нормальное временное состояние либо диагностический сигнал.
3. Теория: API Server, ресурсы и объекты
kube-apiserver выполняет authentication, authorization, admission и validation, затем читает или изменяет состояние. kubectl — один из клиентов API; тем же контрактом пользуются controllers, operators, CI/CD и другие программы.
Объект имеет apiVersion, kind, metadata, spec и часто status. Resource — API-представление, доступное по endpoint; object — конкретный экземпляр. Namespaced и cluster-scoped ресурсы имеют разную область действия. Версия Kubernetes не равна версии каждого API: стабильность определяется группой и версией ресурса.
Прямое изменение etcd обходит API-инварианты и не является штатным способом управления кластером. Backup etcd важен для восстановления, но логика эксплуатации строится вокруг Kubernetes API.
4. Теория: компоненты control plane
- kube-apiserver — API endpoint и центральная точка проверки запросов
- etcd — консистентное key-value хранилище состояния control plane
- kube-scheduler — назначает unscheduled Pod подходящему Node
- kube-controller-manager — запускает встроенные control loops
- cloud-controller-manager — интегрирует поддерживаемые облачные ресурсы и отсутствует в bare-metal лаборатории
В kubeadm-кластере API Server, scheduler, controller-manager и локальный etcd запускаются как static Pods. Их manifests читает kubelet из /etc/kubernetes/manifests. Они видны через Kubernetes API как mirror Pods, но их исходный lifecycle принадлежит kubelet, а не Deployment.
5. Теория: узел, kubelet, runtime и сеть
kubelet наблюдает назначенные этому Node PodSpecs и через CRI просит containerd создать Pod sandbox и containers. containerd управляет lifecycle контейнеров и вызывает OCI runtime. CNI plugin настраивает сеть Pod, а kube-proxy реализует Service forwarding выбранным backend.
На одном узле control plane и workloads разделяют один failure domain. Снятие taint control-plane разрешает учебным workload планироваться на этот узел, но не создаёт отказоустойчивость. Отказ VM одновременно уничтожит API и вычислительную ёмкость до восстановления.
6. Теория: путь создания Deployment
- kubectl сериализует manifest и отправляет запрос в API Server
- API Server проверяет identity, RBAC, admission и schema
- объект Deployment сохраняется, Deployment controller создаёт ReplicaSet
- ReplicaSet controller создаёт Pod objects
- scheduler записывает nodeName для новых Pod
- kubelet получает назначение и через CRI/CNI запускает sandbox и containers
- readiness определяет готовность Pod принимать трафик
Компоненты не выстраиваются в один синхронный pipeline. Они асинхронно наблюдают API и повторяют работу. Благодаря этому временный отказ registry, runtime или узла обычно оставляет evidence и приводит к новой попытке, а не к потере намерения.
7. Методические указания
- Перед командами подтвердите context, cluster и namespace
- Разделяйте принятие объекта API и готовность приложения
- Сначала читайте spec, status, conditions и ownerReferences, затем Events и logs
- Используйте kubectl explain для schema текущего API Server
- Не исправляйте отказ удалением evidence до describe и Events
- Не редактируйте etcd и static Pod manifests без отдельной задачи
- Не называйте одноузловую лабораторию production или HA
Команды sudo относятся к host-уровню и выполняются только на k8s-fundamentals-1. kubectl-команды работают через kubeconfig пользователя k8slab.
8. Лабораторная работа: карта живого кластера
Зафиксируйте client/server versions, текущий context, адрес API, Node и verbose readiness. Затем сопоставьте Kubernetes Pods с процессами CRI и системными сервисами.
kubectl version
kubectl config current-context
kubectl config view --minify
kubectl cluster-info
kubectl get nodes -o wide
kubectl get --raw='/readyz?verbose'kubectl get pods -n kube-system -o wide
kubectl get pods -n kube-flannel -o wide
sudo systemctl status kubelet --no-pager
sudo systemctl status containerd --no-pager
sudo crictl --runtime-endpoint unix:///run/containerd/containerd.sock ps
sudo ss -lntp | grep -E ':(6443|2379|2380|10250)\b'kubectl api-resources
kubectl api-versions
kubectl explain deployment
kubectl explain deployment.spec
kubectl explain deployment.spec.template.spec.containersКритерий: Node Ready, readyz завершается строкой readyz check passed, все системные Pods Running, а crictl показывает control-plane containers, которыми управляет containerd.
9. Лабораторная работа: наблюдаем reconciliation
Создайте Deployment с двумя replicas и удалите один управляемый Pod. Последняя команда watch блокирует терминал; завершите её через Ctrl+C после появления нового Pod.
kubectl create namespace k8s-m01
kubectl -n k8s-m01 create deployment web --image=nginx:1.29-alpine --replicas=2
kubectl -n k8s-m01 rollout status deployment/web --timeout=120s
kubectl -n k8s-m01 get deployment,replicaset,pod -o wide
old_pod=$(kubectl -n k8s-m01 get pods -l app=web -o jsonpath='{.items[0].metadata.name}')
kubectl -n k8s-m01 delete pod "$old_pod" --wait=false
kubectl -n k8s-m01 get pods -l app=web --watchСравните имя удалённого и нового Pod. Deployment не восстанавливает конкретный экземпляр: ReplicaSet controller создаёт замену, потому что observed replica count стал меньше desired replicas.
10. Диагностика: новый rollout не запускается
Установите несуществующий image tag. Старые replicas останутся доступными, а новый Pod перейдёт через ErrImagePull в ImagePullBackOff. Timeout rollout здесь ожидаем и сохранён через || true, чтобы блок можно было выполнить последовательно.
container=$(kubectl -n k8s-m01 get deployment web -o jsonpath='{.spec.template.spec.containers[0].name}')
kubectl -n k8s-m01 set image deployment/web "$container"=nginx:does-not-exist
kubectl -n k8s-m01 rollout status deployment/web --timeout=20s || true
kubectl -n k8s-m01 get deployment,replicaset,pod
kubectl -n k8s-m01 describe deployment web
kubectl -n k8s-m01 describe pods -l app=web
kubectl -n k8s-m01 get events --sort-by=.metadata.creationTimestamp
kubectl -n k8s-m01 rollout history deployment/web
kubectl -n k8s-m01 rollout undo deployment/web
kubectl -n k8s-m01 rollout status deployment/web --timeout=120s
kubectl -n k8s-m01 get pods -l app=web- Deployment Conditions показывают прогресс верхнего уровня
- ReplicaSet отделяет старую и новую revisions
- Pod status показывает waiting reason
- describe и Events содержат точную ошибку registry
- rollout history связывает проблему с изменением template
- rollback восстанавливает предыдущий Pod template
Не удаляйте failed Pod как исправление: controller создаст такой же из неизменённого template. Исправлять нужно источник desired state — Deployment или систему доставки.
11. Контроль, критерии освоения и cleanup
- Почему успешный kubectl apply не доказывает готовность приложения?
- Как Deployment приводит к появлению Pod?
- Кто выбирает Node и кто запускает контейнер?
- Почему etcd не следует изменять напрямую?
- Чем static Pod отличается от Pod Deployment?
- Почему удалённый управляемый Pod появляется снова?
- Какие evidence доказывают причину ImagePullBackOff?
- Какое ограничение одноузлового кластера нельзя исправить replicas?
kubectl delete namespace k8s-m01 --wait=true
kubectl get namespace k8s-m01 2>&1 || trueМодуль освоен, если вы восстанавливаете путь kubectl → API → controllers → scheduler → kubelet → CRI/CNI, наблюдаете reconciliation и исправляете ошибочный rollout через evidence и rollback.