Kubernetes: архитектура кластера и ключевые объекты API | AdminWiki

Kubernetes: архитектура кластера и ключевые объекты API

16 августа 2026 9 мин. чтения

Введение в Kubernetes: зачем нужна оркестрация контейнеров

Контейнеры решили проблему воспроизводимости окружения: приложение запускается одинаково на ноутбуке разработчика и на сервере. Но как только контейнеров становится десятки и сотни, ручное управление превращается в хаос. Нужно следить за тем, на каких узлах что запущено, перезапускать упавшие процессы, балансировать нагрузку, обновлять версии без простоя. Kubernetes решает эти задачи автоматически.

Kubernetes - это система оркестрации контейнеров, которая стала де-факто стандартом в индустрии. Она берет на себя планирование запуска контейнеров, обеспечивает отказоустойчивость и поддерживает желаемое состояние системы. Вы описываете, как должна выглядеть работающая система, а Kubernetes приводит реальность в соответствие с этим описанием.

Для системного администратора и DevOps-инженера понимание архитектуры Kubernetes - базовый навык. Без него сложно диагностировать проблемы, проектировать отказоустойчивые конфигурации и эффективно использовать возможности оркестратора. Этот материал дает фундамент: устройство кластера, роли компонентов, назначение ключевых объектов API.

Если вы только начинаете работать с Kubernetes, рекомендуем сначала изучить структуру YAML-манифестов - это упростит понимание примеров в статье.

Архитектура кластера Kubernetes: обзор

Кластер Kubernetes состоит из двух логических частей: control plane и worker nodes. Control plane управляет кластером, принимает решения о размещении рабочих нагрузок, хранит состояние. Worker nodes выполняют полезную работу - запускают контейнеры. Все компоненты общаются через API, что обеспечивает единый интерфейс управления.

Такое разделение ответственности позволяет масштабировать части независимо: добавлять worker nodes под нагрузку, не трогая управляющий слой, или дублировать control plane для высокой доступности.

Control Plane: мозг кластера

Control plane - это набор компонентов, которые управляют кластером и поддерживают его желаемое состояние. В production-окружениях эти компоненты обычно разворачиваются на выделенных узлах, отдельно от рабочих нагрузок.

kube-apiserver - центральная точка взаимодействия. Все запросы: от kubectl, от внутренних компонентов, от внешних систем - проходят через API-сервер. Он валидирует запросы, проверяет права доступа и записывает изменения в etcd. Без API-сервера кластер не управляется.

etcd - распределенное хранилище «ключ-значение», в котором хранится все состояние кластера: какие объекты созданы, какие узлы доступны, какие поды запущены. etcd - критически важный компонент. Потеря данных etcd означает потерю конфигурации кластера, поэтому в production его разворачивают в кластере из трех или пяти узлов с обязательным резервным копированием.

scheduler - планировщик. Когда создается новый Pod, scheduler выбирает, на каком worker node его запустить. Он учитывает доступные ресурсы узла, заданные в манифесте requests и limits, правила affinity и anti-affinity, taints и tolerations. Scheduler не запускает контейнеры сам - он только назначает под на узел, а запуском занимается kubelet.

controller manager - набор контроллеров, каждый из которых отвечает за определенный тип объектов. Контроллер Deployment следит за количеством реплик, контроллер Node следит за состоянием узлов, контроллер Service управляет сетевыми правилами. Все контроллеры работают по одному принципу: сравнивают текущее состояние с желаемым и вносят изменения для их сближения.

Worker Nodes: где работают контейнеры

Worker node - это сервер, на котором запускаются контейнеры с приложениями. Каждый узел содержит три ключевых компонента.

kubelet - агент, работающий на каждом узле. Он получает от API-сервера список подов, назначенных на узел, и обеспечивает их запуск и работу. kubelet запускает контейнеры через container runtime, следит за их состоянием и сообщает об изменениях в control plane. Если контейнер упал, kubelet перезапускает его.

kube-proxy - сетевой компонент. Он реализует сетевые правила, которые обеспечивают доступ к Service. Когда вы создаете Service, kube-proxy на каждом узле настраивает правила iptables или IPVS, чтобы трафик на виртуальный IP Service перенаправлялся на поды, которые этот Service объединяет.

container runtime - среда выполнения контейнеров. Kubernetes поддерживает несколько реализаций через Container Runtime Interface (CRI): containerd, CRI-O и другие. Docker использовался как runtime до версии 1.24, после чего его поддержка была удалена в пользу containerd.

Взаимодействие простое: control plane решает, что и где должно работать, а worker nodes выполняют. kubelet на каждом узле постоянно сверяется с API-сервером и приводит фактическое состояние узла в соответствие с назначенным.

Ключевые объекты API Kubernetes

Все в Kubernetes описывается в YAML-манифестах. Каждый манифест определяет объект API: Pod, Deployment, Service, ConfigMap или другой ресурс. Вы отправляете манифест через kubectl apply, API-сервер сохраняет его в etcd, а контроллеры начинают работу по приведению системы к описанному состоянию.

Объекты API - это строительные блоки. Комбинируя их, вы описываете приложение, его конфигурацию, сетевой доступ и изоляцию. Разберем пять ключевых объектов, с которых начинается работа с Kubernetes.

Pod: минимальная единица развертывания

Pod - минимальная единица, которую Kubernetes запускает и которой управляет. Pod содержит один или несколько контейнеров, которые разделяют сеть и хранилище. Контейнеры внутри пода всегда запускаются на одном узле.

Простой пример Pod с одним контейнером Nginx:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.25
    ports:
    - containerPort: 80

Несколько контейнеров в поде используют, когда они тесно связаны и должны работать вместе. Классический пример - sidecar-паттерн: основной контейнер обрабатывает запросы, а sidecar собирает логи или обновляет конфигурацию. Контейнеры в поде общаются через localhost и разделяют тома.

Pod - эфемерная сущность. Он создается, умирает, заменяется. Его IP-адрес меняется при пересоздании. Поэтому напрямую управлять подами в production не принято - для этого есть контроллеры более высокого уровня.

Deployment: управление репликацией и обновлениями

Deployment - контроллер, который управляет жизненным циклом подов. Он создает ReplicaSet, который поддерживает заданное количество реплик. Если под удален или упал, ReplicaSet автоматически создает новый.

Пример Deployment для веб-приложения с тремя репликами:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx:1.25
        ports:
        - containerPort: 80

Deployment поддерживает стратегии обновления. По умолчанию используется RollingUpdate: новые поды создаются постепенно, старые удаляются только после того, как новые готовы принимать трафик. Это обеспечивает обновление без простоя. Альтернатива - Recreate: сначала удаляются все старые поды, затем создаются новые. Такой подход быстрее, но вызывает downtime.

Масштабирование сводится к изменению поля replicas: kubectl scale deployment web-app --replicas=5. Deployment и ReplicaSet сделают все остальное.

Подробнее о стратегиях обновления, health-проверках и production-манифестах читайте в полном руководстве по Kubernetes Deployment.

Service: стабильный доступ к подам

Поды эфемерны, их IP-адреса меняются при пересоздании. Service решает эту проблему: он предоставляет стабильный IP-адрес и DNS-имя для группы подов. Service использует селектор, чтобы определить, какие поды входят в группу.

Пример Service для Deployment выше:

apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 80
  type: ClusterIP

Типы Service определяют доступность:

  • ClusterIP - значение по умолчанию. Service доступен только внутри кластера.
  • NodePort - открывает порт на каждом узле, через который Service доступен извне.
  • LoadBalancer - создает внешний балансировщик нагрузки в облачном провайдере.

kube-proxy на каждом узле настраивает правила, которые направляют трафик с IP Service на поды. При изменении набора подов правила обновляются автоматически.

ConfigMap: отделение конфигурации от кода

ConfigMap хранит конфигурационные данные в виде пар «ключ-значение». Это позволяет менять настройки приложения без пересборки образа.

Пример ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  DATABASE_URL: "postgres://db:5432/app"
  LOG_LEVEL: "info"
  nginx.conf: |
    server {
      listen 80;
      server_name example.com;
    }

Использование в поде через переменные окружения:

spec:
  containers:
  - name: app
    image: myapp:1.0
    envFrom:
    - configMapRef:
        name: app-config

Или через volume, смонтированный как файл. Второй способ удобен для конфигурационных файлов: при изменении ConfigMap файл обновляется автоматически, без перезапуска пода.

Для чувствительных данных используйте Secret - объект, аналогичный ConfigMap, но с кодированием в base64 и возможностью шифрования в etcd.

Namespace: логическое разделение ресурсов

Namespace - виртуальный кластер внутри кластера. Он логически изолирует объекты: поды, сервисы, конфигмапы. Имена объектов должны быть уникальны только в пределах namespace, что позволяет разным командам использовать одинаковые имена без конфликтов.

Типичный сценарий - разделение окружений:

kubectl create namespace dev
kubectl create namespace prod

При работе с объектами указывайте namespace:

kubectl get pods -n dev
kubectl apply -f deployment.yaml -n prod

Namespace также позволяет ограничивать доступ через RBAC и задавать квоты на ресурсы. Это базовый механизм мультитенантности в Kubernetes.

Как Kubernetes поддерживает желаемое состояние

Ключевой принцип Kubernetes - reconciliation loop. Вы описываете желаемое состояние в манифесте, а контроллеры непрерывно сравнивают его с текущим и вносят изменения для устранения расхождений.

Пример: вы создали Deployment с тремя репликами. Контроллер Deployment видит, что подов нет, и создает три. Один под падает - контроллер замечает расхождение и создает новый. Вы удаляете под вручную через kubectl - контроллер снова создает его, потому что желаемое состояние требует три реплики.

Этот механизм называется self-healing. Он работает для всех контроллеров: Deployment следит за репликами, Node контроллер следит за узлами, Service контроллер - за сетевыми правилами. Controller manager координирует работу всех встроенных контроллеров.

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

Практический пример: развертывание веб-приложения

Соберем все объекты в единый сценарий. Развернем веб-приложение Nginx с конфигурацией из ConfigMap и доступом через Service.

Шаг 1. Создаем Namespace:

kubectl create namespace web

Шаг 2. Создаем ConfigMap с конфигурацией Nginx:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  namespace: web
data:
  default.conf: |
    server {
      listen 80;
      location / {
        root /usr/share/nginx/html;
        index index.html;
      }
    }

Сохраните в файл configmap.yaml и примените: kubectl apply -f configmap.yaml.

Шаг 3. Создаем Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config
          mountPath: /etc/nginx/conf.d
      volumes:
      - name: config
        configMap:
          name: nginx-config

Примените: kubectl apply -f deployment.yaml.

Шаг 4. Создаем Service:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: web
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
  type: ClusterIP

Примените: kubectl apply -f service.yaml.

Шаг 5. Проверяем результат:

kubectl get all -n web
kubectl describe deployment nginx -n web
kubectl get pods -n web -o wide

Вы увидите три пода, распределенных по worker nodes, и Service с внутренним IP. Обратитесь к Service из любого пода внутри кластера - трафик будет распределен между тремя репликами.

Для управления инфраструктурой Kubernetes как кодом рекомендуем изучить сравнение kubectl, Helm, Terraform и Crossplane.

Заключение и следующие шаги

Вы изучили архитектуру кластера Kubernetes: control plane с kube-apiserver, etcd, scheduler и controller manager, worker nodes с kubelet, kube-proxy и container runtime. Разобрали пять ключевых объектов API: Pod, Deployment, Service, ConfigMap, Namespace. Поняли принцип reconciliation loop, который лежит в основе самовосстановления и поддержания желаемого состояния.

Дальше стоит углубиться в темы: Ingress для внешнего доступа по HTTP/HTTPS, PersistentVolumes для хранения данных, StatefulSets для stateful-приложений, Helm для управления пакетами. Для проектирования production-кластеров изучите руководство по проектированию промышленных кластеров Kubernetes.

Если вы еще не уверены, подходит ли Kubernetes для вашей инфраструктуры, прочитайте сравнение Kubernetes и Docker Swarm.

Для практики разверните кластер в облаке. Timeweb Cloud предоставляет управляемый Kubernetes с гибким масштабированием ресурсов - подходит для первых экспериментов и production-нагрузок.

Поделиться:
Сохранить гайд? В закладки браузера