Kubernetes часто называют сложной системой, в которой легко запутаться. Control Plane, etcd, scheduler, worker nodes — когда сталкиваешься с этим в первый раз, кажется, что разобраться невозможно. Но на самом деле за громкими названиями скрываются простые и логичные компоненты. Каждый из них отвечает за свою задачу, и вместе они собирают работающий кластер.

Вместе с Антоном Бондаром, экспертом команды SRE Databases во ВКонтакте, мы подготовили простую теоретическую подводку и ранбук по запуску своего кластера с нуля. 

Антон Бондар

Эксперт команды SRE Databases во ВКонтакте. Помогал с подготовкой материала.

Так вы не просто разберётесь в архитектуре, а пройдёте весь путь своими руками и увидите, как работают все компоненты. Вы установите инструменты, создадите локальный Kubernetes с помощью Minikube, развернёте приложение, научитесь управлять репликами, откроете доступ к сервисам и даже поработаете с хранилищем и секретами. Материал подойдёт всем, кто хоть немного знаком с контейнерами и хочет понять, что происходит после команды kubectl apply.

Никакой магии — только архитектура, жизненные циклы, живые примеры и пара схем для наглядности. Поехали ↓

Для навигации

Зачем вам Kubernetes, если вы ещё сомневаетесь

Прежде чем лезть в состав компонентов, давайте сначала ответим на вопрос: а нужен ли вам Kubernetes. Если вы запускаете один-два контейнера на одном сервере и вас всё устраивает — возможно, оркестратор пока не нужен. Но как только проектов становится больше, появляются требования к отказоустойчивости, автоматическому масштабированию и бесшовным обновлениям, ручное управление начинает напоминать жонглирование тарелками.

Kubernetes берёт на себя рутину: он следит, чтобы нужное количество копий вашего приложения всегда работало, перезапускает упавшие контейнеры, распределяет нагрузку и даже подкладывает подушку безопасности при обновлениях. Всё это он делает благодаря своей особой архитектуре. 

Коротко об архитектуре: кто есть кто в кластере

Любой кластер Kubernetes (даже наш локальный) состоит из двух групп:

  • Control Plane — мозг. Принимает решения, хранит состояние, отвечает на запросы. Сюда входят: kube-apiserver (входные ворота), etcd (база данных), kube-scheduler (планировщик), kube-controller-manager (набор контроллеров).

  • Worker Nodes — мышцы. Запускают контейнеры. На каждой ноде живут: kubelet (агент, который общается с API), kube-proxy (отвечает за сетевые правила) и container runtime (например, containerd).

В production-кластере машин много, control plane обычно дублируется на трёх и более серверах, а worker nodes — это целые фермы. Мы же с помощью Minikube поднимем всё на одном компьютере, но компоненты будут точно такими же. Вы сможете к ним прикоснуться через команды и увидеть, как они работают.

Общая архитектура кластера Kubernetes
Общая архитектура кластера Kubernetes

Подготовка: устанавливаем инструменты

Нам понадобятся три вещи: kubectl (клиент для общения с кластером), Docker (чтобы Minikube мог запускать контейнеры) и сам Minikube. 

Инструкции для Windows, macOS и Linux немного отличаются — следуйте своей ветке.

kubectl

Linux (Debian/Ubuntu)

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/

macOS

Если есть Homebrew:

brew install kubectl

Или вручную (для Intel):

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/

Для Apple Silicon замените amd64 на arm64.

Windows

Через PowerShell:

curl.exe -LO "https://dl.k8s.io/release/$(curl.exe -L -s https://dl.k8s.io/release/stable.txt)/bin/windows/amd64/kubectl.exe"

Переместите kubectl.exe в папку, которая есть в PATH (например, C:\Windows\System32), или добавьте эту папку в PATH.

Если используете Chocolatey:

choco install kubernetes-cli

После установки проверьте:

kubectl version --client

Должна отобразиться версия, например, v1.35.0.

Docker

Minikube умеет запускать кластер либо в виртуальной машине (через VirtualBox, Hyper-V, KVM), либо прямо в контейнере через Docker. Самый простой и кроссплатформенный способ — использовать Docker-драйвер.

Установка Docker:

  • Linux: sudo apt install docker.io (или yum install docker для CentOS). После установки добавьте своего пользователя в группу docker, чтобы не писать sudo каждый раз: sudo usermod -aG docker $USER (потребуется перелогиниться).

  • macOS: скачайте Docker Desktop с официального сайта.

  • Windows: также Docker Desktop (обязательно включите WSL2 во время установки).

Проверьте, что Docker работает:

docker --version

Minikube

Linux

curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube

macOS

brew install minikube

Или вручную:

curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64
sudo install minikube-darwin-amd64 /usr/local/bin/minikube

(для Apple Silicon замените amd64 на arm64)

Windows

Скачайте .exe с официальной страницы или через Chocolatey:

choco install minikube

Запускаем кластер

Всё готово. Выполните команду:

minikube start --driver=docker

Minikube скачает нужные образы, создаст контейнер и развернёт внутри полноценный Kubernetes. Процесс занимает пару минут. Вы увидите много строк — это нормально.

После завершения проверьте статус:

minikube status

Должно быть что-то вроде:

host: Running
kubelet: Running
apiserver: Running

Теперь посмотрим на узлы кластера:

kubectl get nodes

Вы увидите одну ноду с именем minikube и статусом Ready. На этой ноде работают и control plane-компоненты, и наши будущие поды.

Знакомимся с компонентами на живой машине

Minikube — это не чёрный ящик. Давайте заглянем внутрь:

kube-apiserver — это входные ворота. Любая команда kubectl превращается в HTTPS-запрос к API-серверу. Например, когда вы выполнили kubectl get nodes, kubectl обратился к https://192.168.49.2:8443 (или другому адресу) и получил ответ.

etcd — хранилище всех данных кластера. Можно даже залезть в него (но осторожно!). Minikube хранит etcd внутри своего инстанса. Чтобы попасть внутрь, выполните:

minikube ssh

Внутри можно найти etcd, но для повседневной работы это не нужно. Просто знайте: всё, что вы создаёте (поды, сервисы, секреты), попадает в etcd.

Важно: после того как закончите изучать внутренности инстанса, выйдите из него командой exit, чтобы вернуться к терминалу вашего компьютера. Дальнейшие команды мы будем выполнять на хост-машине.

exit

kube-scheduler и kube-controller-manager тоже работают как поды в пространстве имён kube-system. Посмотрим на них:

kubectl get pods -n kube-system

Вы увидите, например, coredns, etcd-minikube, kube-apiserver-minikube, kube-controller-manager-minikube, kube-scheduler-minikube, kube-proxy-xxxx, storage-provisioner. Это и есть наши управляющие компоненты, упакованные в поды.

На рабочих узлах (у нас один) живут:

  • kubelet — его мы не видим, как под, это системная служба. Он запускает контейнеры по заданию от API-сервера.

  • kube-proxy — как раз один из подов в kube-system. Он отвечает за то, чтобы трафик к сервисам попадал на правильные поды. Работает в режиме iptables по умолчанию (хотя современные ядра Linux позволяют использовать nftables, а в Cilium kube-proxy могут вообще заменить на eBPF).

  • container runtime — в Minikube это containerd (современная замена Docker). Docker тоже мог бы быть через прослойку cri-dockerd, но в 2026 году команды всё чаще используют containerd — он легче и быстрее.

Внутреннее устройство рабочей ноды
Внутреннее устройство рабочей ноды

Запускаем первое приложение — nginx

Теперь создадим простой веб-сервер. Для этого подготовим файл deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.26
        ports:
        - containerPort: 80

Применим его:

kubectl apply -f deployment.yaml

Kubernetes получил команду, сохранил желаемое состояние в etcd, и началась магия: контроллер deployment создал ReplicaSet, тот — два пода, scheduler назначил их на ноду, kubelet запустил контейнеры.

Посмотрим результат:

kubectl get pods

Через несколько секунд вы увидите два работающих пода с именами вроде nginx-demo-xxxxx-yyy.

Смотрим, как кластер лечит сам себя

Одна из главных «фишек» Kubernetes — самовосстановление. Давайте сломаем один под и посмотрим, что произойдёт.

Скопируйте имя одного из подов и удалите его:

kubectl delete pod nginx-demo-xxxxx

Сразу же выполните kubectl get pods — вы увидите, что старый под исчез, но появился новый с суффиксом, которого раньше не было. Это Deployment Controller заметил, что количество подов стало меньше желаемого, и создал новый. В production это означает, что если ваше приложение упадёт, оно будет перезапущено автоматически.

Теперь попробуем изменить количество реплик:

kubectl scale deployment/nginx-demo --replicas=3

kubectl get pods покажет три пода. Scheduler назначил новый под на ту же ноду (других нет), и kubelet запустил его.

Важный нюанс: в современных версиях Kubernetes (начиная с 1.27) появилась возможность менять ресурсы (CPU, память) уже работающего пода без перезапуска — это называется In-Place Pod Resize. В версии 1.35 эта функция стала уже стабильной (GA). То есть если бы мы захотели увеличить память для nginx, можно было просто изменить манифест, и изменения применились бы на лету.

Жизненный цикл пода: от команды до контейнера. Источник
Жизненный цикл пода: от команды до контейнера. Источник

Открываем доступ к приложению

Поды живут в своей изолированной сети, и с вашей хост-машины до них не добраться. Нужен Service. Это абстракция, которая даёт стабильный IP и DNS-имя для группы подов.

Создадим файл service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP   # по умолчанию, доступ только внутри кластера

Применим:

kubectl apply -f service.yaml

Посмотрим созданный сервис:

kubectl get services

Вы увидите nginx-service с внутренним IP (например, 10.96.123.45) и портом 80.

Чтобы обратиться к nginx с хоста, временно пробросим порт:

kubectl port-forward service/nginx-service 8080:80

Теперь откройте браузер по адресу http://localhost:8080 — вы увидите приветственную страницу nginx. Нажмите Ctrl+C, чтобы остановить проброс.

Minikube умеет открывать сервис автоматически:

minikube service nginx-service

Эта команда сама найдёт доступный URL и откроет его в браузере.

Немного про сеть: как поды общаются

В Kubernetes каждый под получает уникальный IP-адрес, и поды могут общаться друг с другом напрямую (без NAT).

Это обеспечивает CNI-плагин (Container Network Interface). В Minikube по умолчанию используется плагин kindnet, но в реальных кластерах часто ставят Calico или Cilium. Cilium, например, использует eBPF и может полностью заменить kube-proxy, обеспечивая более высокую производительность и расширенную безопасность.

Если вы захотите ограничить трафик между подами, используйте Network Policies. Например, можно запретить весь входящий трафик к подам с меткой app: nginx. Но учтите: политики работают, только если CNI-плагин их поддерживает (Calico, Cilium — да, Flannel — нет). В Minikube по умолчанию они не включены, но при желании можно запустить Minikube с Calico:

minikube start --cni calico

Но для нашего первого знакомства это излишне.

Хранение данных: делаем том постоянным

По умолчанию данные, записанные только во внутреннюю файловую систему контейнера, не сохраняются. Чтобы данные оставались постоянными, используются PersistentVolume (PV) и PersistentVolumeClaim (PVC).

В классической схеме администратор может заранее создать PV вручную. Но если в кластере настроено dynamic provisioning, достаточно создать PVC — и Kubernetes автоматически создаст подходящий PV. Это наш случай. 

Создадим PVC, который запросит 1 гигабайт хранилища. Файл pvc.yaml:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

И под, который использует этот том, чтобы писать данные. Файл pod-with-volume.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: test
    image: busybox
    command: ["sleep", "3600"]
    volumeMounts:
    - name: storage
      mountPath: /data
  volumes:
  - name: storage
    persistentVolumeClaim:
      claimName: my-pvc

Применим оба:

kubectl apply -f pvc.yaml
kubectl apply -f pod-with-volume.yaml

Теперь внутри пода в папке /data можно создавать файлы, и они сохранятся даже после перезапуска контейнера. Если и под будет удалён — данные в томе обычно сохранятся, потому что PVC/PV живут отдельно от Pod. Они исчезнут, только если удалить соответствующий PVC/PV или если Reclaim Policy настроена на удаление тома.

Конфигурация и секреты (и почему секреты — не совсем секреты)

Хранить настройки в образе контейнера — плохая практика: образы становятся зависимыми от окружения. Для этого в Kubernetes есть ConfigMap и Secret:

  • ConfigMap хранит строки конфигурации;

  • Secret предназначен для чувствительных данных — паролей, токенов, ключей.

Создадим секрет с паролем. Файл secret.yaml:

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  password: cGFzc3dvcmQxMjM=   # это base64 от "password123"

Применим:

kubectl apply -f secret.yaml

Важный нюанс: Secret по умолчанию хранятся в etcd просто в base64-кодировке, что не является шифрованием. Любой, кто имеет доступ к etcd или к API (с правами на чтение секретов), может легко их декодировать. Для настоящего шифрования нужно включать EncryptionConfiguration — это настраивает администратор кластера. В Minikube шифрование не включено по умолчанию, поэтому не храните в секретах ничего критичного для реального использования.

Завершаем эксперимент: удаляем кластер

Когда всё изучено, кластер можно удалить, чтобы освободить ресурсы:

minikube delete

Все созданные поды, тома и конфигурации исчезнут.

Что дальше? Куда расти

Вы прошли базовый путь. Теперь вы знаете, как установить Kubernetes, запустить приложение, управлять репликами, открыть доступ, использовать хранилище и секреты. Это фундамент, на котором строится всё остальное. Для более глубокого изучения можно посмотреть на следующие темы:

  • Gateway API — новый стандарт вместо Ingress. В марте 2026 Kubernetes прекратил поддержку Ingress NGINX Controller — не будет ни релизов, ни патчей безопасности; репозиторий заморожен. Вместо него стоит изучать Gateway API и контроллеры вроде kgateway, NGINX Gateway Fabric, Envoy Gateway. Они позволяют гибко управлять трафиком (маршрутизация, тайм-ауты, зеркалирование, split-трафик).

  • Cilium — продвинутая сеть с eBPF. Он может полностью заменить kube-proxy, обеспечивая лучшую производительность и безопасность. В Cilium встроена поддержка Gateway API и сетевых политик.

  • Операторы — автоматизация сложных приложений (базы данных, очереди). Например, оператор для PostgreSQL сам создаёт и обслуживает кластер БД.

  • GitOps (ArgoCD, Flux) — подход, при котором всё состояние кластера хранится в Git, а синхронизация происходит автоматически.

  • Мониторинг и логирование — Prometheus + Grafana для метрик, Loki или EFK для логов

  • AI/ML на Kubernetes — Kubernetes стал стандартом для ML-платформ. В последних версиях (1.35) появилась alpha-поддержка Gang Scheduling (групповое планирование), необходимого для распределённого обучения моделей. Также полезны инструменты MLOps: Kubeflow, MLflow.

  • Платформенная инженерия (IDP) — построение Internal Developer Platforms поверх Kubernetes, чтобы разработчикам было проще выкатывать свои сервисы.

Шпаргалка команд

Ну и на всякий случай — шпаргалка, чтобы всегда держать нужные команды под рукой: 

Что делаем

Команда

Запустить кластер

minikube start --driver=docker

Посмотреть ноды

kubectl get nodes

Применить конфигурацию

kubectl apply -f file.yaml

Посмотреть поды

kubectl get pods

Посмотреть логи пода

kubectl logs pod-name

Удалить ресурс

kubectl delete -f file.yaml

Пробросить порт

kubectl port-forward service/name 8080:80

Открыть сервис в браузере

minikube service имя-сервиса

Удалить кластер

minikube delete


Чтобы расти, нужно выйти из привычной зоны и сделать шаг к переменам. Можно изучить новое, начав с бесплатных занятий:

Или можно стать востребованным сотрудником и открыть открыть бóльшие перспективы в карьере с профессиональным обучением: