Всем привет сегодня разберемся в установке kubeadm в данном примере будет 3 master ноды и 3 worker ноды. Данный разбор будет производиться на ubuntu 24.04, все 6 серверов будут в одной сети. Ну чтож начнем P.s все этапы выполняем на всех серверах если не сказанно обратного.
1. Подготовка системы на сервера.
1.1 обновление системы здесь долго не задерживаемся
sudo apt update sudo apt upgrade -y
1.2 Устанавливаем пакеты
sudo apt-get install -y \ curl \ wget \ vim \ net-tools \ htop \ git
1.3 Отключаем swap(хоть это уже не обезательно кубер уже вроде как работает с ним но делаем по инерции :) )
sudo swapoff -a #это Удали swap из fstab чтобы он не включался при перезагрузке sudo sed -i '/ swap / s/^/#/' /etc/fstab
1.3.1 при ошибках или проверки используйте это, а именно вручную отредактируйте файл:
sudo nano /etc/fstab
Найти строки типа:
UUID=xxxx-xxxx none swap sw 0 0
И добавить # в начало.
1.4 Настройка сети
Включи модули ядра для Kubernetes:
# Эти модули нужны для контейнеризации и сетевых возможностей sudo modprobe overlay sudo modprobe br_netfilter # Сделай это постоянным sudo tee /etc/modules-load.d/kubernetes.conf > /dev/null <<EOF overlay br_netfilter EOF
Настрой параметры ядра:
sudo tee /etc/sysctl.d/99-kubernetes.conf > /dev/null <<EOF net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 net.ipv4.ip_nonlocal_bind = 1 EOF sudo sysctl --system
Проверь эти значения (все должны быть 1):
sysctl net.bridge.bridge-nf-call-iptables sysctl net.bridge.bridge-nf-call-ip6tables sysctl net.ipv4.ip_forward
1.5 Установить Docker
Добавь репозиторий Docker:
Curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update
Установи Docker:
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
Добавь своего пользователя в группу docker (опционально, но удобно):
sudo usermod -aG docker $USER newgrp docker
Включи Docker:
sudo systemctl enable docker sudo systemctl start docker
Проверь что Docker работает:
docker run hello-world
1.5 Установи kubeadm, kubelet, kubectl
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.35/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.35/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list sudo apt-get update
Включи kubelet (но НЕ запускай его пока!):
sudo systemctl enable kubelet
2.Настройка Keepalived(этот процесс отвечает за отказоустойчевость мастер нод на сетевом уровне если в вашем примере 1 master нода и вы не планируете ставить ещё тогда этот момент смело пропускайте.) всё будет дальше прописанно использовать на всех 3 master нодах если не сказанно обратного.
2.1 установка
sudo apt-get install -y keepalived psmisc
2.2 Включение forwarding для Keepalived
# Это нужно чтобы Keepalived мог управлять VIP sudo sysctl -w net.ipv4.ip_nonlocal_bind=1
Сделай это постоянным:
sudo tee -a /etc/sysctl.conf > /dev/null <<EOF net.ipv4.ip_nonlocal_bind=1 EOF sudo sysctl -p
2.3 Делаем конфигурацию.
Создаём
sudo vim /etc/keepalived/keepalived.conf
и вставляем/заменяем на
global_defs { router_id KUBE_MASTER1 # меняется на каждой ноде script_user root enable_script_security } vrrp_script check_apiserver { script "/etc/keepalived/check_apiserver.sh" interval 2 weight -30 fall 3 rise 2 } vrrp_instance VI_1 { state BACKUP interface ens160 virtual_router_id 51 priority 100 advert_int 1 nopreempt authentication { auth_type PASS auth_pass keepalived123 } virtual_ipaddress { x.x.x.x/24 dev ens160 } track_script { check_apiserver } }
2.4 создаём скрипт создаем в /etc/keepalived/check_apiserver.sh
#!/bin/bash curl -k --silent --max-time 2 https://127.0.0.1:6443/healthz | grep -q ok if [ $? -eq 0 ]; then exit 0 else exit 1 fi
Делаем его исполняемым
chmod +x /etc/keepalived/check_apiserver.sh
2.5 теперь внимательно делаем конфигурацию на 2 и 3 worker ноде. Месторасположение тот же шаблон тот же единственное изменение это "router_id KUBE_MASTER1" меняем по нумерации ваших мастер нод.
upd. Все control-plane ноды настроены с одинаковым priority и отключённым preempt для предотвращения повторного захвата VIP и исключения двойного failover.
2.6 запускаем keeplived
sudo systemctl enable keepalived sudo systemctl start keepalived
Проверь статус:
sudo systemctl status keepalived # Должно быть: active (running)
2.7 Проверяем как работает на 1 master ноде
ip addr show ens160 # если вы указывали другой интерфейс то поменяйте на свой
ну и пустите пинг с другой ноды до вашего vIP
3.Инициализация первой Master ноды (на этом этапе делаем все на master нрде 1 если не сказоно другого)
создай файл:
sudo vim /tmp/kubeadm-config.yaml
Содержимое (замени IP адреса):
apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration kubernetesVersion: v1.35.0 controlPlaneEndpoint: "x.x.x.x:6443" # ↑ Это VIP - точка входа для всего кластера certificatesDir: /etc/kubernetes/pki clusterName: kubernetes networking: dnsDomain: cluster.local podSubnet: "192.168.0.0/16" # ↑ Pod CIDR - диапазон IP для контейнеров в подах # Calico будет использовать этот диапазон serviceSubnet: "10.96.0.0/12" # ↑ Service CIDR - для Kubernetes сервисов controllerManager: extraArgs: bind-address: "0.0.0.0" scheduler: extraArgs: bind-address: "0.0.0.0" etcd: local: dataDir: /var/lib/etcd --- apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd
Объяснение важных параметров:
Параметр | Значение | Зачем |
|---|---|---|
| x.x.x.x:6443 | VIP для доступа к Kubernetes API |
| 192.168.0.0/16 | IP адреса для подов (контейнеров) |
| 10.96.0.0/12 | IP адреса для Kubernetes сервисов |
| systemd | Как контролировать ресурсы контейнеров |
3.1 Инициализируй кластер (если у вас ошибка то смотри 3.1.2)
sudo kubeadm init --config=/tmp/kubeadm-config.yaml --upload-certs
Что происходит:
📝 Создаются сертификаты для безопасности
🔑 Генерируются ключи для authentication
📦 Распаковываются Docker образы Kubernetes
⚙️ Запускаются компоненты: API Server, etcd, Controller Manager, Scheduler
🔓
--upload-certs- загружает сертификаты для других master нод
ВАЖНО: Дождись конца! Это может занять 2-5 минут.
Вывод будет примерно такой:
Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run (as a regular user): mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-setup/addons-available/ You can now join any number of control-plane nodes by running the following command on each as root: kubeadm join 10.202.4.111:6443--token xxxxx.xxxxxxxxxxxxx \ --discovery-token-ca-cert-hash sha256:xxxxx.... \ --control-plane --certificate-key yyyyy.... Please save these tokens! You'll need them for other nodes.
3.1.2 этот раздел если у вас как и у меня возникла ошибка вида
W0207 15:44:07.467481 30644 common.go:100] your configuration file uses a deprecated API spec: "kubeadm.k8s.io/v1beta3" (kind: "ClusterConfiguration"). Please use 'kubeadm config migrate --old-config old-config-file --new-config new-config-file', which will write the new, similar spec using a newer API version. [init] Using Kubernetes version: v1.35.0 [preflight] Running pre-flight checks [preflight] Some fatal errors occurred: [ERROR CRI]: could not connect to the container runtime: failed to create new CRI runtime service: validate service connection: validate CRI v1 runtime API for endpoint "unix:///var/run/containerd/containerd.sock": rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService [ERROR ContainerRuntimeVersion]: could not connect to the container runtime: failed to create new CRI runtime service: validate service connection: validate CRI v1 runtime API for endpoint "unix:///var/run/containerd/containerd.sock": rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService [preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...` error: error execution phase preflight: preflight checks failed To see the stack trace of this error execute with --v=5 or higher
я предположил что это из-за проблемы в том, что containerd версии 2.2.1 имеет проблемы с Kubernetes 1.35. Решаем это путем Использование Docker вместо containerd (сделать всё это надо на всех Master нодах)
# Скачай последнюю версию VER=$(curl -s https://api.github.com/repos/Mirantis/cri-dockerd/releases/latest | grep tag_name | cut -d '"' -f 4 | sed 's/v//g') # Скачай архив wget https://github.com/Mirantis/cri-dockerd/releases/download/v${VER}/cri-dockerd-${VER}.amd64.tgz # Распакуй tar xzf cri-dockerd-${VER}.amd64.tgz sudo mv cri-dockerd/cri-dockerd /usr/local/bin/ rm -rf cri-dockerd cri-dockerd-${VER}.amd64.tgz # Проверь установку cri-dockerd --version
Создай systemd сервис для cri-dockerd
sudo vim /etc/systemd/system/cri-docker.service
Содержимое:
[Unit] Description=CRI Interface for Docker Application Container Engine Documentation=https://docs.mirantis.com After=network-online.target firewalld.service docker.service Wants=network-online.target Requires=cri-docker.socket [Service] Type=notify ExecStart=/usr/local/bin/cri-dockerd --container-runtime-endpoint fd:// ExecReload=/bin/kill -s HUP $MAINPID TimeoutStopSec=120 RestartSec=5 Restart=always [Install] WantedBy=multi-user.target
Создай socket файл
sudo vim /etc/systemd/system/cri-docker.socket
Содержимое:
[Unit] Description=CRI Docker Socket PartOf=cri-docker.service [Socket] ListenStream=%t/cri-dockerd.sock SocketMode=0660 SocketUser=root SocketGroup=docker [Install] WantedBy=sockets.target
Запусти cri-dockerd
sudo systemctl daemon-reload sudo systemctl enable cri-docker.service cri-docker.socket sudo systemctl startcri-docker.service cri-docker.socket
Проверь:
sudo systemctl status cri-docker.service
Должно быть active (running)
после этого меняем конфигурацию кубера,
sudo vim /tmp/kubeadm-config.yaml
--- apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration kubernetesVersion: v1.35.0 controlPlaneEndpoint: "x.x.x.x:6443" # ↑ Это VIP - точка входа для всего кластера certificatesDir: /etc/kubernetes/pki clusterName: kubernetes networking: dnsDomain: cluster.local podSubnet: "192.168.0.0/16" # ↑ Pod CIDR - диапазон IP для контейнеров в подах # Calico будет использовать этот диапазон serviceSubnet: "10.96.0.0/12" # ↑ Service CIDR - для Kubernetes сервисов controllerManager: extraArgs: bind-address: "0.0.0.0" scheduler: extraArgs: bind-address: "0.0.0.0" etcd: local: dataDir: /var/lib/etcd --- apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd # ↓ ДОБАВЬ ЭТО: --- apiVersion: kubeadm.k8s.io/v1beta3 kind: InitConfiguration nodeRegistration: criSocket: unix:///var/run/cri-dockerd.sock # ↑ Указываем что использовать cri-dockerd вместо containerd
и делаемин ициализацию снова
sudo kubeadm init --config=/tmp/kubeadm-config.yaml --upload-certs
3.2 Настрой 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 работает:
kubectl get nodes
Должно быть:
NAME STATUS ROLES AGE VERSION kubem1 NotReady control-plane 1m v1.35.0
❌ NotReady - это НОРМАЛЬНО! Потому что сетевой плагин не установлен ещё.
3.3 Проверь компоненты
kubectl get pods -n kube-system
Должно быть примерно так:
NAME READY STATUS coredns-768b8dd64f-xxxxx 0/1 Pending ← Ждёт сетевого плагина coredns-768b8dd64f-xxxxx 0/1 Pending etcd-kubem1 1/1 Running ✅ kube-apiserver-kubem1 1/1 Running ✅ kube-controller-manager-kubem1 1/1 Running ✅ kube-scheduler-kubem1 1/1 Running ✅
Что это:
etcd - база данных (хранит конфиг всего кластера)
kube-apiserver - API сервер (управляет кластером)
kube-controller-manager- контролер (следит за состоянием)
kube-scheduler - планировщик (выбирает где запустить поды)
coredns - DNS (будет работать когда установим Calico)
3.4 Установи Calico (сетевой плагин)
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/tigera-operator.yaml
ждём 5 минут и приступаем
kubectl wait --for=condition=available --timeout=300s deployment/tigera-operator -n tigera-operator
Создай конфиг Installation для Calico
cat <<EOF | kubectl apply -f - apiVersion: operator.tigera.io/v1 kind: Installation metadata: name: default spec: calicoNetwork: ipPools: - blockSize: 26 cidr: 192.168.0.0/16 encapsulation: VXLANCrossSubnet natOutgoing: Enabled nodeSelector: all() EOF
Подожди пока Calico запустится
# Проверяй статус kubectl get pods -n calico-system -w
Когда все поды будут в статусе Running - нажми Ctrl+C
# Должны быть примерно такие поды: # calico-kube-controllers-xxxx - Running # calico-node-xxxx - Running # calico-typha-xxxx - Running (опционально)
Проверь что всё работает
# Проверь статус ноды kubectl get nodes
Должно быть:
NAME STATUS ROLES AGE VERSION kubem1 Ready control-plane 20m v1.35.0
✅ Ready - отлично!
Поздравляю вас мы смогли сделать если вы дошли до данного этапа значит сегодня точно доделаете )
4.добовляем остальные мастер ноды в кластер
Перед началом проверяем что бы всё было так как тут:
kubectl get nodesпоказывает kubem1 как Readykubectl get pods -n kube-system- все поды Runningkubectl get pods -n calico-system- все поды Running
4.1 Получи команды для присоединения. Всё делаем на master ноде 1(Важно все это делаем для каждой уникальной ноде для добовление токены должны быть уникальными)
# Получи token для worker нод (НЕ нужны сертификаты) kubeadm token create --print-join-command --ttl=30m
Вывод будет примерно:
kubeadm join 10.202.4.111:6443 --token abc123.def456 \ --discovery-token-ca-cert-hash sha256:xxxxx....
СОХРАНИ эту команду - она нужна для worker нод позже!
Теперь получи команду для MASTER нод:
На kubem1:
bash# Загрузи сертификаты для других master нод sudo kubeadm init phase upload-certs --upload-certs
Вывод будет:
I0207 16:30:15.xxx etcdserver: Serving insecure client requests on 127.0.0.1:2379, this is STRONGLY discouraged! W0207 16:30:15.xxx Loads of warnings... Certificates uploaded successfully. [upload-certs] Storing the apiserver certificate in Secret in the cluster [upload-certs] Uploading the apiserver CA certificate in the cluster ... Upload certificate key: abc123def456ghi789jkl000mnopqr
СКОПИРУЙ и СОХРАНИ Upload certificate key!
Создай полную команду для master нод Это команда для kubem2 и kubem3 (важно помнить что мы используем --cri-socket unix:///var/run/cri-dockerd.sock для запуска):
bash# Используй данные из предыдущих команд # ЗАМЕНИ на свои значения! sudo kubeadm join <API_SERVER_ENDPOINT> \ --token <BOOTSTRAP_TOKEN> \ --discovery-token-ca-cert-hash <CA_CERT_HASH> \ --control-plane \ --certificate-key <CERTIFICATE_KEY> \ --cri-socket <CRI_SOCKET_PATH> --cri-socket unix:///var/run/cri-dockerd.sock
Ожидай вывод:
[preflight] Running pre-flight checks [preflight] Found systemd as the boot cri driver [download-certs] Downloading the certificates in Secret in the cluster [certs]Using certificateDir at /etc/kubernetes/pki [certs] Generating "front-proxy-ca" certificate and key [certs] Valid certificates and keys now exist in /etc/kubernetes/pki [certs] Using the existing "sa" key [kubeconfig] Generating kubeconfig files [kubeconfig] kubeconfig file for kubelet kubem2 [kubeconfig] kubeconfig file for admin kubem2 [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubelets.conf" [kubelet-start] Starting the kubelet [control-plane] Using manifest files from "/etc/kubernetes/manifests" [upload-certs] Skipping phase. [certs] Not requested a certificate rotation [mark-control-plane] Marking the node kubem2 as a control-plane by adding labels and taints. [kubeadm-join] 1.35.0 [bootstrap-token] Using token: abc123... [bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long lived certificate credentials [bootstrap-token] Configured RBAC rules to allow the csrs approver controller automatically approve CSRs from a 'system:bootstrappers' group [bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster [bootstrap-token] Thedefault bootstrap token generated by 'kubeadm init' has been deleted [bootstrap-token] Bootstrap tokens have been deleted after cluster bootstrap. It's safe to reuse the bootstrap token for new nodes. This node has joined the cluster and a new control plane instance was created successfully. Before completing cluster setup, you need to ensure that your cluster deploys a pod network. It is now safe to move forward without the drain/uncordon steps.
✅ Успешно присоединился!
Копируй конфиг kubectl правильно на 2 и 3 master ноду
# На kubem1 scp /home/kube_m1/.kube/config kube_m2@ip/tmp/config # На kubem2 и на 3 мастер ноде всё тоже самое mkdir -p $HOME/.kube cp /tmp/config $HOME/.kube/config chmod 600 $HOME/.kube/config
Проверь на kubem2 и kubem3
# На kubem2 kubectl get nodes # Должно быть: # NAME STATUS ROLES AGE VERSION # kubem1 Ready control-plane 40m v1.35.0 # kubem2 Ready control-plane 15m v1.35.0 # kubem3 Ready control-plane 10m v1.35.0
5.Добавление Worker нод (kubew1, kubew2, kubew3)
на них(воркер нодах) должно быть установленно всё тоже самое что и на мастер нодах 2 и 3 (отключенный swap, Включи модули ядра и настроенны, cri-dockerd и kubeadm, kubelet, kubectl, Docker установлены )
конфиги тоже должны быть они одинаковые
5.1
Получи токен для Worker нод(Получим токен присоединения (без флага --control-plane))
**На мастер 1
# Создай новый токен для worker нод kubeadm token create --print-join-command --ttl=30m
и точно так же присоединяем
p.s как выглядит ещё раз команда присоединение
Пояснение параметров:
sudo kubeadm join <API_SERVER_ENDPOINT> \ --token <BOOTSTRAP_TOKEN> \ --discovery-token-ca-cert-hash <CA_CERT_HASH> \ --control-plane \ --certificate-key <CERTIFICATE_KEY> \ --cri-socket <CRI_SOCKET_PATH>
<API_SERVER_ENDPOINT>- адрес и порт control-plane нодыКак получить:
kubectl cluster-infoна control-plane<BOOTSTRAP_TOKEN>- временный токен для аутентификацииКак получить на control-plane:
kubeadm token create --print-join-command<CA_CERT_HASH>- хэш CA сертификата кластераКак получить на control-plane:
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex<CERTIFICATE_KEY>- ключ для расшифровки сертификатовКак получить на control-plane:
kubeadm init phase upload-certs --upload-certs<CRI_SOCKET_PATH>- путь к сокету container runtimeВарианты:
Для containerd:
unix:///var/run/containerd/containerd.sockДля Docker с cri-dockerd:
unix:///var/run/cri-dockerd.sock
Как определить:
sudo systemctl status containerd docker cri-docker
ну вот и всё по итогу должно получиться вот так
