Установка и настройка кластера Kubernetes с нуля: пошаговое руководство | AdminWiki

Установка и настройка кластера Kubernetes с нуля: пошаговое руководство

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

Введение: что мы будем делать и зачем

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

В результате вы получите production-ready кластер с одним control plane и несколькими worker-узлами. Все команды проверены на Ubuntu 22.04 LTS. Если вы уже работали с Kubernetes и хотите избежать типичных ошибок при настройке, обратите внимание на разбор 10 частых ошибок при эксплуатации кластера.

Минимальные требования к узлам: 2 vCPU, 2 GB RAM и 20 GB диска для control plane; 1 vCPU, 1 GB RAM и 20 GB диска для каждого worker-узла. Для production-нагрузок рекомендуется удвоить эти значения. Все узлы должны работать на одинаковой версии ОС и иметь сетевую связность между собой.

Архитектура кластера и требования к узлам

Кластер Kubernetes делится на два типа узлов: control plane управляет состоянием, worker-узлы запускают рабочие нагрузки. Понимание ролей компонентов помогает быстрее диагностировать проблемы.

Компоненты control plane и worker-узлов

kube-apiserver - единая точка входа для всех операций. Через него проходят kubectl-запросы, аутентификация и валидация объектов. etcd - распределенное key-value хранилище, в котором сохраняется всё состояние кластера: конфигурации, секреты, статусы подов. Потеря данных etcd означает потерю кластера, поэтому резервное копирование этого компонента критично.

kube-scheduler назначает поды на узлы на основе доступных ресурсов и правил affinity. kube-controller-manager запускает контроллеры, которые следят за соответствием текущего состояния желаемому: replication controller, endpoints controller, namespace controller и другие.

На worker-узлах работают два компонента: kubelet - агент, который получает задания от control plane и управляет контейнерами через container runtime; kube-proxy - сетевой прокси, который настраивает правила маршрутизации трафика к сервисам. Container runtime (в нашем случае containerd) непосредственно запускает и останавливает контейнеры.

Минимальные требования к оборудованию и ОС

Для тестового кластера достаточно: control plane - 2 vCPU, 2 GB RAM, 20 GB диска; worker - 1 vCPU, 1 GB RAM, 20 GB диска. Для production-среды закладывайте минимум 4 vCPU и 8 GB RAM на control plane, 4 vCPU и 8 GB RAM на каждый worker. Дисковая подсистема etcd чувствительна к задержкам, поэтому используйте SSD.

ОС: Ubuntu 22.04 LTS или аналогичная. Все узлы должны работать на одной версии ядра и ОС. Смешение версий приводит к несовместимости сетевых модулей и container runtime. Перед началом настройки отключите swap и настройте сетевые параметры ядра - эти шаги описаны в следующем разделе.

Подготовка узлов кластера

Подготовка ОС - этап, на котором чаще всего возникают ошибки. Пропущенный шаг с отключением swap или модулями ядра приводит к падению kubelet на старте. Выполните команды ниже на всех узлах кластера.

Отключение swap и настройка модулей ядра

kubelet требует отключенный swap. При активном swap планировщик Kubernetes не может корректно учитывать доступную память, а поды могут быть вытеснены на диск, что резко деградирует производительность. Отключите swap на постоянной основе:

sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab

Проверьте, что swap отключен:

free -h

В строке Swap должно быть значение 0. Затем загрузите модули ядра overlay и br_netfilter. Первый нужен для работы файловой системы контейнеров, второй - для обработки сетевого трафика через iptables:

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

Проверьте загрузку модулей:

lsmod | grep -E 'overlay|br_netfilter'

Настройка параметров сети (iptables)

Для корректной маршрутизации трафика между подами ядро должно обрабатывать bridge-трафик через iptables. Создайте файл с параметрами sysctl:

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF

sudo sysctl --system

Параметр net.bridge.bridge-nf-call-iptables включает обработку bridge-трафика правилами iptables. Без него сетевые политики Kubernetes не будут применяться к подам. Параметр net.ipv4.ip_forward разрешает пересылку пакетов между сетевыми интерфейсами, что необходимо для работы CNI-плагинов.

Установка и настройка containerd

containerd - container runtime, который Kubernetes использует для запуска контейнеров. Критичный момент - настройка systemd cgroup driver. Несовпадение cgroup driver у containerd и kubelet приводит к нестабильной работе подов и утечкам ресурсов.

Установка containerd и настройка cgroup driver

Установите containerd из репозитория Ubuntu:

sudo apt update
sudo apt install -y containerd

Создайте дефолтный конфиг и измените параметр SystemdCgroup:

sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

Перезапустите сервис:

sudo systemctl restart containerd
sudo systemctl enable containerd
sudo systemctl status containerd

Статус должен показывать active (running). Параметр SystemdCgroup = true указывает containerd использовать systemd как менеджер cgroups. Это согласует управление ресурсами между kubelet и container runtime.

Проверка работоспособности containerd

Установите crictl - CLI для взаимодействия с container runtime через CRI:

VERSION="v1.28.0"
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz
sudo tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin
rm crictl-$VERSION-linux-amd64.tar.gz

Настройте endpoint для crictl:

cat <<EOF | sudo tee /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

Проверьте, что containerd отвечает:

sudo crictl info

Вывод покажет информацию о runtime и версии. Для полной проверки загрузите тестовый образ:

sudo crictl pull nginx:alpine

Образ должен скачаться без ошибок. После этого можно переходить к установке компонентов Kubernetes.

Инициализация control plane с помощью kubeadm

На этом этапе вы установите kubeadm, kubelet и kubectl, затем инициализируете control plane и получите команду для присоединения worker-узлов.

Установка kubeadm, kubelet и kubectl

Добавьте репозиторий Kubernetes и установите пакеты:

sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

Команда apt-mark hold фиксирует версии пакетов, чтобы случайное обновление не сломало кластер. Проверьте установку:

kubeadm version
kubectl version --client

Запуск kubeadm init и настройка kubectl

Инициализируйте control plane с указанием CIDR для pod-сети. Для Flannel используйте 10.244.0.0/16, для Calico - 192.168.0.0/16:

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

Процесс занимает 2-3 минуты. В выводе вы увидите секцию с командой kubeadm join - сохраните её, она понадобится для подключения worker-узлов. Настройте kubectl для текущего пользователя:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

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

kubectl get nodes

Узел будет в статусе NotReady до установки CNI-плагина. Это ожидаемое поведение: без сетевого плагина поды не могут получить IP-адреса.

Настройка сетевого плагина (CNI)

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

Выбор CNI: Flannel или Calico?

Flannel - простой плагин, который создает overlay-сеть на основе VXLAN. Подходит для небольших кластеров до 50 узлов. Calico - более функциональный: поддерживает network policies, BGP-маршрутизацию, шифрование трафика. Для production-среды выбирайте Calico, если вам нужны сетевые политики и изоляция подов.

Для этого руководства используем Flannel как наиболее простой вариант. Если вы планируете масштабировать кластер и внедрять сетевые политики, переходите на Calico сразу - миграция CNI в работающем кластере сложнее, чем выбор правильного плагина на старте.

Установка CNI и проверка статуса

Установите Flannel:

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

Дождитесь, пока все поды в namespace kube-system перейдут в статус Running:

kubectl get pods -n kube-system -w

После этого проверьте статус узла:

kubectl get nodes

Control plane узел должен перейти в статус Ready в течение 1-2 минут. Если статус долго остается NotReady, проверьте логи flannel-пода:

kubectl logs -n kube-system -l app=flannel

Подключение worker-узлов к кластеру

Worker-узлы выполняют рабочие нагрузки. Для их подключения нужно повторить подготовку ОС, установить containerd и компоненты Kubernetes, затем выполнить команду kubeadm join.

Подготовка worker-узла и выполнение kubeadm join

На каждом worker-узле выполните шаги из разделов «Подготовка узлов кластера» и «Установка и настройка containerd», затем установите kubeadm, kubelet и kubectl. После этого выполните команду kubeadm join, сохраненную при инициализации control plane:

sudo kubeadm join 192.168.1.100:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>

Токен действителен 24 часа. Если он истек, сгенерируйте новый на control plane:

kubeadm token create --print-join-command

На control plane проверьте, что узел присоединился:

kubectl get nodes

Новый узел должен появиться в списке и перейти в статус Ready после установки CNI-компонентов на нём.

Проверка работоспособности кластера

Разверните тестовое приложение и проверьте связность. Создайте deployment с nginx:

kubectl create deployment nginx-test --image=nginx:alpine
kubectl scale deployment nginx-test --replicas=3

Проверьте, что поды распределились по узлам:

kubectl get pods -o wide

Создайте service для доступа к приложению:

kubectl expose deployment nginx-test --port=80 --type=NodePort

Получите порт и проверьте доступность:

kubectl get svc nginx-test
curl http://<worker-ip>:<node-port>

Ответ nginx подтверждает, что сеть работает, поды запущены, а service корректно маршрутизирует трафик. Обратите внимание: service проверяется по опубликованным endpoints, а не только по selector. Если selector настроен верно, но endpoints пусты, трафик не дойдет до подов. Проверьте endpoints командой:

kubectl get endpoints nginx-test

В столбце ENDPOINTS должны отображаться IP-адреса подов. Пустой список указывает на проблему с labels или readiness-пробами.

Базовая настройка безопасности кластера

После развертывания кластер уязвим для несанкционированного доступа. Два обязательных шага: шифрование данных etcd и настройка RBAC с принципом наименьших привилегий. Детальный план аудита безопасности описан в руководстве по аудиту безопасности Kubernetes.

Включение TLS-шифрования etcd

По умолчанию etcd хранит данные в открытом виде. Любой, кто получит доступ к файлам etcd, сможет прочитать секреты, конфигурации и токены. Включите шифрование на уровне API-сервера. Создайте файл EncryptionConfiguration:

cat <<EOF | sudo tee /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: $(head -c 32 /dev/urandom | base64)
      - identity: {}
EOF

Добавьте параметр в манифест kube-apiserver:

sudo sed -i '/- kube-apiserver/a\    - --encryption-provider-config=/etc/kubernetes/encryption-config.yaml' /etc/kubernetes/manifests/kube-apiserver.yaml

kube-apiserver автоматически перезапустится. Проверьте, что шифрование работает:

kubectl get secrets --all-namespaces -o json | grep -q 'aescbc' && echo "Encryption active"

Учтите: шифрование применяется только к новым данным. Существующие секреты нужно пересоздать, чтобы они были зашифрованы.

Настройка RBAC и ограничение доступа

RBAC управляет доступом к ресурсам кластера. Создайте ServiceAccount для приложения, Role с минимальными правами и RoleBinding для их связывания:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-sa
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: app-role
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["pods", "services"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: app-binding
  namespace: default
subjects:
  - kind: ServiceAccount
    name: app-sa
    namespace: default
roleRef:
  kind: Role
  name: app-role
  apiGroup: rbac.authorization.k8s.io
EOF

Отключите анонимный доступ к API-серверу. Добавьте флаг в манифест kube-apiserver:

sudo sed -i '/- kube-apiserver/a\    - --anonymous-auth=false' /etc/kubernetes/manifests/kube-apiserver.yaml

После перезапуска kube-apiserver анонимные запросы будут отклоняться. Проверьте, что kubectl продолжает работать - он использует сертификаты из kubeconfig, а не анонимный доступ.

Заключение и дальнейшие шаги

Вы развернули production-ready кластер Kubernetes: подготовили узлы, настроили containerd с systemd cgroup driver, инициализировали control plane через kubeadm, установили CNI-плагин, подключили worker-узлы и включили базовую безопасность. Кластер готов к развертыванию рабочих нагрузок.

Следующие шаги для укрепления кластера: настройте мониторинг с Prometheus и Grafana, настройте резервное копирование etcd, внедрите сетевые политики. Если вы планируете обновлять кластер в будущем, изучите пошаговое руководство по обновлению Kubernetes через kubeadm. Для проектирования отказоустойчивой архитектуры обратитесь к руководству по проектированию промышленных кластеров.

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