Перейти к содержанию

Этап 2: Инициализация первой control plane ноды

Выполнять ТОЛЬКО на k8scontrolplane01

Все шаги этого этапа выполняются только на первой ноде.

kube-vip на всех control plane нодах

Манифест kube-vip static pod нужно создать на всех control plane нодах:

  • k8scontrolplane01 — ПЕРЕД kubeadm init (этот этап)
  • k8scontrolplane02 и k8scontrolplane03 — ПЕРЕД kubeadm join (см. Этап 5)

Без kube-vip на всех нодах failover VIP не будет работать!

2.1. Введение

Последовательность действий на k8scontrolplane01

  1. Создать kubeadm-config.yaml (параметры кластера)
  2. Создать kube-vip static pod манифест (будет запущен при init)
  3. Запустить kubeadm init (инициализация кластера)
  4. Переключить kube-vip на admin.conf (для production безопасности)
  5. Настроить kubectl (для управления кластером)

2.2. Создание kubeadm конфигурационного файла

Зачем отдельный файл конфигурации

  • Декларативная конфигурация (можно сохранить и использовать повторно)
  • Явное указание всех параметров
  • Проще troubleshooting

Почему controlPlaneEndpoint = VIP

  • Все компоненты (kubelet, kube-proxy, пользователи) должны обращаться к VIP, а не к конкретной ноде
  • Обеспечивает HA - если одна control plane нода упадет, VIP переключится на другую

Объяснение параметров

  • localAPIEndpoint.advertiseAddress - IP этой конкретной ноды, на котором слушает API server
  • controlPlaneEndpoint - VIP адрес для HA (все клиенты подключаются сюда)
  • node-ip - явно указываем IP ноды для kubelet (иначе может выбрать неправильный интерфейс)
  • podSubnet - диапазон IP для pod'ов (используется CNI)
  • serviceSubnet - диапазон IP для Services
  • certSANs - Subject Alternative Names в TLS сертификате API server (все имена/IP по которым можем обращаться)

Почему важны certSANs

  • API server генерирует TLS сертификат при init
  • Если VIP или IP нод нет в certSANs, клиенты не смогут подключиться (ошибка проверки сертификата)
cat <<EOF | sudo tee /etc/kubernetes/kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.139.105
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///run/containerd/containerd.sock
  imagePullPolicy: IfNotPresent
  imagePullSerial: true
  kubeletExtraArgs:
    - name: node-ip
      value: "192.168.139.105"
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: v1.35.1
clusterName: kubernetes
controlPlaneEndpoint: "kube-api.orb.local:6443"
networking:
  podSubnet: "10.244.0.0/16"
  serviceSubnet: "10.96.0.0/12"
apiServer:
  timeoutForControlPlane: 4m0s
  certSANs:
    - "kube-api.orb.local"
    - "192.168.139.101"
    - "192.168.139.105"
    - "192.168.139.152"
    - "192.168.139.188"
EOF

2.3. Создание kube-vip static pod манифеста

Генерируем kube-vip манифест ПЕРЕД kubeadm init:

Параметры

  • --interface - сетевой интерфейс для VIP
  • --address - Virtual IP адрес
  • --controlplane - управление VIP для control plane
  • --services - управление VIP для Services (LoadBalancer type)
  • --arp - использовать ARP для анонсирования VIP
  • --leaderElection - leader election через Kubernetes Lease
  • --k8sConfigPath - путь к kubeconfig (используем super-admin.conf для bootstrap)

Почему super-admin.conf

  • В Kubernetes 1.29+ порядок создания файлов: сначала super-admin.conf, потом admin.conf
  • Static pod kube-vip запускается ДО того как admin.conf создан
  • super-admin.conf создается раньше и имеет права для bootstrap
  • После успешного init переключаемся на admin.conf для production безопасности
export VIP=192.168.139.101  # ПОМЕНЯЙ на свой VIP!
export INTERFACE=eth0

# Создаем директорию для static pod манифестов
sudo mkdir -p /etc/kubernetes/manifests

# Генерируем манифест kube-vip
sudo ctr image pull ghcr.io/kube-vip/kube-vip:v1.0.4

sudo ctr run --rm --net-host ghcr.io/kube-vip/kube-vip:v1.0.4 vip /kube-vip manifest pod \
  --interface $INTERFACE \
  --address $VIP \
  --controlplane \
  --services \
  --arp \
  --leaderElection \
  --k8sConfigPath /etc/kubernetes/super-admin.conf | sudo tee /etc/kubernetes/manifests/kube-vip.yaml

Проверка (опционально):

# Смотрим что получилось
cat /etc/kubernetes/manifests/kube-vip.yaml | grep -E "volumeMount|hostPath|address"

Ожидаемый вывод

  • mountPath: /etc/kubernetes/admin.conf - куда монтируется внутрь контейнера
  • path: /etc/kubernetes/super-admin.conf - откуда берется файл с хоста
  • value: "192.168.139.101" - ваш VIP

ВАЖНО: Pod еще НЕ запустится потому что /etc/kubernetes/super-admin.conf еще не существует. Он будет создан при kubeadm init.

2.4. Инициализация кластера

Что происходит при kubeadm init

  1. Preflight checks (проверка requirements)
  2. Генерация PKI сертификатов (/etc/kubernetes/pki)
  3. Создание kubeconfig файлов
  4. Генерация static pod манифестов для control plane (/etc/kubernetes/manifests)

  5. kube-apiserver

  6. kube-controller-manager
  7. kube-scheduler
  8. etcd

  9. Запуск control plane компонентов

  10. Создание ConfigMaps и RBAC

Флаг --upload-certs

  • Загружает PKI сертификаты в Secret в kube-system namespace
  • Шифрует их ключом (certificate-key)
  • Позволяет другим control plane нодам скачать сертификаты при join
  • Без этого пришлось бы вручную копировать /etc/kubernetes/pki на каждую ноду

Флаг --skip-phases=addon/kube-proxy

  • Пропускает создание kube-proxy DaemonSet
  • Нужен потому что Cilium полностью заменяет kube-proxy
  • Без этого флага kube-proxy создастся автоматически и его придется удалять вручную
sudo kubeadm init --config=/etc/kubernetes/kubeadm-config.yaml --upload-certs --skip-phases=addon/kube-proxy

ВАЖНО: Сохраните вывод команды! В нем будут:

  • join команда для control plane нод (с --certificate-key)
  • join команда для worker нод

2.5. Переключение kube-vip на admin.conf

Зачем

  • super-admin.conf имеет расширенные права и предназначен только для bootstrap
  • После успешного init нужно переключиться на admin.conf для production безопасности
  • Это best practice для Kubernetes 1.29+
# Меняем super-admin.conf на admin.conf в манифесте kube-vip
sudo sed -i 's#super-admin.conf#admin.conf#g' /etc/kubernetes/manifests/kube-vip.yaml

# Перезапускаем kubelet чтобы применить изменения
sudo systemctl restart kubelet

2.6. Настройка kubectl

Зачем: kubectl нужен kubeconfig файл чтобы знать как подключаться к API server и какие credentials использовать.

Что в admin.conf

  • API server URL (https://kube-api.orb.local:6443)
  • CA сертификат кластера
  • Client сертификат и ключ для аутентификации (cluster-admin права)
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

2.7. Проверка инициализации кластера

Проверяем что kubeadm init создал все необходимые компоненты

# Проверяем что нода появилась (будет NotReady до установки CNI)
kubectl get nodes

# Проверяем что control plane pod'ы запустились
kubectl get pods -n kube-system

# Проверяем что необходимые ConfigMaps созданы
kubectl get configmap -n kube-system kubeadm-config
kubectl get configmap -n kube-system kubelet-config
kubectl get configmap -n kube-public cluster-info

# Все три команды должны вернуть ConfigMap без ошибок