Setup Kubernetes Cluster Using Kubeadm: Difference between revisions
Created page with "== Kubeadm Setup Prerequisites == Following are the prerequisites for '''Kubeadm Kubernetes cluster setup'''. # Minimum two '''Ubuntu nodes''' [One master and one worker node]. You can have more worker nodes as per your requirement. # The master node should have a minimum of '''2 vCPU and 2GB RAM'''. # For the worker nodes, a minimum of 1vCPU and 2 GB RAM is recommended. # '''10.X.X.X/X''' network range with static IPs for master and worker nodes. We will be using the '..." |
No edit summary |
||
| Line 11: | Line 11: | ||
</pre>'''На worker1:'''<pre> | </pre>'''На worker1:'''<pre> | ||
sudo hostnamectl set-hostname w1 | sudo hostnamectl set-hostname w1 | ||
</pre>'''На worker2:'''<pre> | </pre>'''На worker2:'''<pre>sudo hostnamectl set-hostname w2</pre>'''На всех нодах''' добавь записи в <code>/etc/hosts</code>:<pre> | ||
sudo hostnamectl set-hostname w2 | |||
</pre>'''На всех нодах''' добавь записи в <code>/etc/hosts</code>:<pre> | |||
sudo nano /etc/hosts | sudo nano /etc/hosts | ||
</pre>В конец файла допиши, подставив свои IP:<pre> | </pre>В конец файла допиши, подставив свои IP:<pre> | ||
| Line 99: | Line 97: | ||
</pre><blockquote>Репозиторий <code>v1.34</code> гарантирует, что ставится именно ветка 1.34.x. <code>apt-mark hold</code> не даст случайно обновиться до другой минорной версии при <code>apt upgrade</code></blockquote>(Не обязательно, но можно сразу включить kubelet, он будет крутиться и ждать <code>kubeadm init / join</code>):<pre> | </pre><blockquote>Репозиторий <code>v1.34</code> гарантирует, что ставится именно ветка 1.34.x. <code>apt-mark hold</code> не даст случайно обновиться до другой минорной версии при <code>apt upgrade</code></blockquote>(Не обязательно, но можно сразу включить kubelet, он будет крутиться и ждать <code>kubeadm init / join</code>):<pre> | ||
sudo systemctl enable --now kubelet | sudo systemctl enable --now kubelet | ||
</pre>''' | </pre>'''5. Инициализация control-plane (только cp1)''' | ||
''' | Теперь на <code>cp1</code> создаём кластер. | ||
'''5.1. kubeadm init с pod-CIDR для Calico''' | |||
Calico по умолчанию использует <code>192.168.0.0/16</code>. Для удобства берём его же: | |||
На <code>cp1</code>:<pre> | |||
sudo kubeadm init \ | |||
--apiserver-advertise-address=10.0.0.10 \ | |||
--pod-network-cidr=192.168.0.0/16 | |||
</pre> | |||
* <code>--apiserver-advertise-address</code> — IP cp1, по которому все будут ходить на API. | |||
* <code>--pod-network-cidr</code> — диапазон IP для pod’ов, который будет использовать Calico. | |||
В конце <code>kubeadm</code> выдаст: | |||
* сообщение об успешной инициализации; | |||
* '''команду <code>kubeadm join ...</code>''' — обязательно скопируй её куда-нибудь (будем использовать на worker’ах). | |||
'''5.2. Настраиваем kubectl для юзера <code>sadmin</code> (cp1)''' | |||
Сейчас kubeconfig лежит в <code>/etc/kubernetes/admin.conf</code> и принадлежит root’у. | |||
На <code>cp1</code> под <code>sadmin</code>:<pre> | |||
mkdir -p $HOME/.kube | |||
sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config | |||
sudo chown $(id -u):$(id -g) $HOME/.kube/config | |||
</pre>Проверка:<pre> | |||
kubectl get nodes | |||
</pre>Пока сеть не поднята, нода может быть <code>NotReady</code> — это нормально. | |||
'''6. Устанавливаем Calico 3.31 (только cp1)''' | |||
Берём свежий Calico 3.31.1 из официальной инструкции для on-prem. | |||
'''6.1. Tigera Operator + CRD''' | |||
На <code>cp1</code>:<pre> | |||
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.1/manifests/operator-crds.yaml | |||
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.1/manifests/tigera-operator.yaml | |||
</pre><blockquote>Это ставит оператор Calico, который потом сам раскатает нужные компоненты по нодам.</blockquote>'''6.2. Конфигурация Calico (custom-resources)''' | |||
По дефолту используем iptables-датаплейн (без eBPF, чтоб пока не усложнять). | |||
На <code>cp1</code>:<pre> | |||
curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.31.1/manifests/custom-resources.yaml | |||
kubectl create -f custom-resources.yaml | |||
</pre>(Если хочешь eBPF в будущем — там же есть <code>custom-resources-bpf.yaml</code>.) | |||
'''6.3. Проверяем, что Calico поднялся''' | |||
На <code>cp1</code>:<pre> | |||
watch kubectl get tigerastatus | |||
</pre>Ждём, пока всё будет <code>AVAILABLE=True</code>:<pre> | |||
NAME AVAILABLE PROGRESSING DEGRADED SINCE | |||
calico True False False ... | |||
ippools True False False ... | |||
... | |||
</pre>И смотрим pod’ы:<pre> | |||
kubectl get pods -n calico-system | |||
kubectl get pods -n kube-system | |||
kubectl get nodes | |||
</pre>cp1 должен перейти в статус <code>Ready</code>. | |||
'''7. Делаем control-plane “чистым” (без workload-подов)''' | |||
По умолчанию в 1.34 control-plane '''может''' принимать обычные поды (taint не ставится автоматически). | |||
Тебе этого '''не нужно''', поэтому сразу ставим taint: | |||
На <code>cp1</code>:<pre> | |||
kubectl taint nodes cp1 node-role.kubernetes.io/control-plane=:NoSchedule | |||
</pre>Проверка:<pre> | |||
kubectl describe node cp1 | grep -i Taint | |||
</pre>Должно быть что-то типа:<pre> | |||
Taints: node-role.kubernetes.io/control-plane:NoSchedule | |||
</pre><blockquote>Теперь scheduler НЕ будет ставить обычные pod’ы на cp1. Там останутся только системные компоненты (kube-apiserver, etcd, kube-controller-manager, scheduler, Calico DaemonSet и т.п.).</blockquote>'''8. Подключаем worker1 и worker2''' | |||
'''8.1. Получаем join-команду (если потерял)''' | |||
Если не сохранил вывод <code>kubeadm init</code>, на <code>cp1</code>:<pre> | |||
sudo kubeadm token create --print-join-command | |||
</pre>Пример:<pre> | |||
kubeadm join 10.0.0.10:6443 --token abcdef.0123456789abcdef \ | |||
--discovery-token-ca-cert-hash sha256:xxxxxxxx... | |||
</pre>'''8.2. Выполняем join на worker1 / worker2''' | |||
На <code>worker1</code>:<pre> | |||
sudo kubeadm join 10.0.0.10:6443 --token abcdef.0123456789abcdef \ | |||
--discovery-token-ca-cert-hash sha256:xxxxxxxx... | |||
</pre>На <code>worker2</code>:<pre> | |||
sudo kubeadm join 10.0.0.10:6443 --token abcdef.0123456789abcdef \ | |||
--discovery-token-ca-cert-hash sha256:xxxxxxxx... | |||
</pre><blockquote>Здесь используется токен и хеш CA, чтобы worker’ы безопасно присоединились к кластеру.</blockquote>После этого на <code>cp1</code>:<pre> | |||
kubectl get nodes | |||
</pre>Ожидаемый результат:<pre> | |||
NAME STATUS ROLES AGE VERSION | |||
cp1 Ready control-plane 20m v1.34.x | |||
worker1 Ready <none> 5m v1.34.x | |||
worker2 Ready <none> 3m v1.34.x | |||
</pre>Если worker’ы какое-то время <code>NotReady</code> — подожди, пока на них подтянутся и стартанут kube-proxy + Calico. | |||
'''9. Проверка: поды только на worker-нодах''' | |||
Создадим тестовый deployment: | |||
На <code>cp1</code>:<pre> | На <code>cp1</code>:<pre> | ||
kubectl create deployment nginx --image=nginx --replicas=3 | |||
</pre> | kubectl expose deployment nginx --port=80 --type=NodePort | ||
</pre>Смотрим:<pre> | |||
kubectl get pods -o wide | |||
</pre>Все pod’ы <code>nginx</code> должны сидеть на <code>worker1</code> и <code>worker2</code>, '''но не на cp1'''. | |||
Если вдруг увидишь под на cp1, значит taint не применился → ещё раз:<pre> | |||
kubectl taint nodes cp1 node-role.kubernetes.io/control-plane=:NoSchedule --overwrite | |||
kubectl rollout restart deploy nginx | |||
</pre>✅ '''1. Как удалить эти pod’ы (Deployment + Service)''' | |||
Ты создал: | |||
* Deployment: '''nginx''' | |||
* Service: '''nginx''' | |||
<pre | Чтобы удалить:<pre> | ||
kubectl delete service nginx | |||
</pre>Удалить Deployment:<pre> | |||
kubectl delete deployment nginx | |||
</pre>Проверяем:<pre> | |||
kubectl get pods | |||
kubectl get svc | |||
</pre>📌 '''Если хочешь удалить ВСЁ, что относится к nginx, одной командой:'''<pre> | |||
kubectl delete deploy,svc nginx | |||
</pre> | |||
Revision as of 07:35, 19 November 2025
Kubeadm Setup Prerequisites
Following are the prerequisites for Kubeadm Kubernetes cluster setup.
- Minimum two Ubuntu nodes [One master and one worker node]. You can have more worker nodes as per your requirement.
- The master node should have a minimum of 2 vCPU and 2GB RAM.
- For the worker nodes, a minimum of 1vCPU and 2 GB RAM is recommended.
- 10.X.X.X/X network range with static IPs for master and worker nodes. We will be using the 192.x.x.x series as the pod network range that will be used by the Calico network plugin. Make sure the Node IP range and pod IP range don't overlap.
На cp1:
sudo hostnamectl set-hostname cp1
На worker1:
sudo hostnamectl set-hostname w1
На worker2:
sudo hostnamectl set-hostname w2
На всех нодах добавь записи в /etc/hosts:
sudo nano /etc/hosts
В конец файла допиши, подставив свои IP:
10.0.0.10 cp1 10.0.0.11 w1 10.0.0.12 w2
Это позволяет нодам обращаться друг к другу по имени, а не по IP.
1. Общая подготовка системы (все ноды)
1.1. Обновляем пакеты
sudo apt update sudo apt upgrade -y
Просто приводим систему в свежий вид, чтобы избежать багов из-за старых пакетов.
1.2. Отключаем swap (обязательно для kubeadm)
На всех нодах:
sudo swapoff -a sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
Проверка:
free -h
1.3. Модули ядра и sysctl (для сетки) На каждой ноде:
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf overlay br_netfilter EOF sudo modprobe overlay sudo modprobe br_netfilter
Теперь sysctl:
cat <<EOF | sudo tee /etc/sysctl.d/kubernetes.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF
sudo sysctl --system
Это включает корректную обработку трафика через Linux bridge и форвардинг — обязательно для CNI (Calico).
1.4. (Для лаба) Отключить UFW
Если UFW включён и это чистый лаб:
sudo ufw disable
В проде, конечно, лучше открыть нужные порты, но для первой сборки проще без firewall.
2. Устанавливаем containerd (все ноды)
На каждой ноде:
sudo apt install -y containerd
Генерируем дефолтный конфиг:
sudo mkdir -p /etc/containerd sudo containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
Рестарт и включение:
sudo systemctl restart containerd sudo systemctl enable containerd sudo systemctl status containerd
SystemdCgroup = true → kubelet и containerd используют один и тот же cgroup-драйвер (systemd). Это теперь “best practice”.
3. Устанавливаем kubeadm/kubelet/kubectl 1.34 (все ноды)
По официальным докам для v1.34:
3.1. Пакеты для репо
На каждой ноде:
sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl gpg
3.2. GPG-ключ и репозиторий pkgs.k8s.io (v1.34)
Ubuntu 22.04 уже имеет /etc/apt/keyrings, но если вдруг нет:
sudo mkdir -p -m 755 /etc/apt/keyrings
Ключ репозитория:
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key \
| sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
Добавляем репо именно для Kubernetes 1.34:
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /" \
| sudo tee /etc/apt/sources.list.d/kubernetes.list
3.3. Установка kubeadm/kubelet/kubectl
sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl
Репозиторий
v1.34гарантирует, что ставится именно ветка 1.34.x.apt-mark holdне даст случайно обновиться до другой минорной версии приapt upgrade
(Не обязательно, но можно сразу включить kubelet, он будет крутиться и ждать kubeadm init / join):
sudo systemctl enable --now kubelet
5. Инициализация control-plane (только cp1)
Теперь на cp1 создаём кластер.
5.1. kubeadm init с pod-CIDR для Calico
Calico по умолчанию использует 192.168.0.0/16. Для удобства берём его же:
На cp1:
sudo kubeadm init \ --apiserver-advertise-address=10.0.0.10 \ --pod-network-cidr=192.168.0.0/16
--apiserver-advertise-address— IP cp1, по которому все будут ходить на API.--pod-network-cidr— диапазон IP для pod’ов, который будет использовать Calico.
В конце kubeadm выдаст:
- сообщение об успешной инициализации;
- команду
kubeadm join ...— обязательно скопируй её куда-нибудь (будем использовать на worker’ах).
5.2. Настраиваем kubectl для юзера sadmin (cp1)
Сейчас kubeconfig лежит в /etc/kubernetes/admin.conf и принадлежит root’у.
На cp1 под sadmin:
mkdir -p $HOME/.kube sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
Проверка:
kubectl get nodes
Пока сеть не поднята, нода может быть NotReady — это нормально.
6. Устанавливаем Calico 3.31 (только cp1)
Берём свежий Calico 3.31.1 из официальной инструкции для on-prem.
6.1. Tigera Operator + CRD
На cp1:
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.1/manifests/operator-crds.yaml kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.1/manifests/tigera-operator.yaml
Это ставит оператор Calico, который потом сам раскатает нужные компоненты по нодам.
6.2. Конфигурация Calico (custom-resources)
По дефолту используем iptables-датаплейн (без eBPF, чтоб пока не усложнять).
На cp1:
curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.31.1/manifests/custom-resources.yaml kubectl create -f custom-resources.yaml
(Если хочешь eBPF в будущем — там же есть custom-resources-bpf.yaml.)
6.3. Проверяем, что Calico поднялся
На cp1:
watch kubectl get tigerastatus
Ждём, пока всё будет AVAILABLE=True:
NAME AVAILABLE PROGRESSING DEGRADED SINCE calico True False False ... ippools True False False ... ...
И смотрим pod’ы:
kubectl get pods -n calico-system kubectl get pods -n kube-system kubectl get nodes
cp1 должен перейти в статус Ready.
7. Делаем control-plane “чистым” (без workload-подов)
По умолчанию в 1.34 control-plane может принимать обычные поды (taint не ставится автоматически).
Тебе этого не нужно, поэтому сразу ставим taint:
На cp1:
kubectl taint nodes cp1 node-role.kubernetes.io/control-plane=:NoSchedule
Проверка:
kubectl describe node cp1 | grep -i Taint
Должно быть что-то типа:
Taints: node-role.kubernetes.io/control-plane:NoSchedule
Теперь scheduler НЕ будет ставить обычные pod’ы на cp1. Там останутся только системные компоненты (kube-apiserver, etcd, kube-controller-manager, scheduler, Calico DaemonSet и т.п.).
8. Подключаем worker1 и worker2
8.1. Получаем join-команду (если потерял)
Если не сохранил вывод kubeadm init, на cp1:
sudo kubeadm token create --print-join-command
Пример:
kubeadm join 10.0.0.10:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:xxxxxxxx...
8.2. Выполняем join на worker1 / worker2
На worker1:
sudo kubeadm join 10.0.0.10:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:xxxxxxxx...
На worker2:
sudo kubeadm join 10.0.0.10:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:xxxxxxxx...
Здесь используется токен и хеш CA, чтобы worker’ы безопасно присоединились к кластеру.
После этого на cp1:
kubectl get nodes
Ожидаемый результат:
NAME STATUS ROLES AGE VERSION cp1 Ready control-plane 20m v1.34.x worker1 Ready <none> 5m v1.34.x worker2 Ready <none> 3m v1.34.x
Если worker’ы какое-то время NotReady — подожди, пока на них подтянутся и стартанут kube-proxy + Calico.
9. Проверка: поды только на worker-нодах
Создадим тестовый deployment:
На cp1:
kubectl create deployment nginx --image=nginx --replicas=3 kubectl expose deployment nginx --port=80 --type=NodePort
Смотрим:
kubectl get pods -o wide
Все pod’ы nginx должны сидеть на worker1 и worker2, но не на cp1.
Если вдруг увидишь под на cp1, значит taint не применился → ещё раз:
kubectl taint nodes cp1 node-role.kubernetes.io/control-plane=:NoSchedule --overwrite kubectl rollout restart deploy nginx
✅ 1. Как удалить эти pod’ы (Deployment + Service)
Ты создал:
- Deployment: nginx
- Service: nginx
Чтобы удалить:
kubectl delete service nginx
Удалить Deployment:
kubectl delete deployment nginx
Проверяем:
kubectl get pods kubectl get svc
📌 Если хочешь удалить ВСЁ, что относится к nginx, одной командой:
kubectl delete deploy,svc nginx