Содержание

Уcтанавливаем Kubernetes - kubeadm.

Долго, нудно. Но позволяет понять весь процесс…

Подготовка

Дано:
Есть как минимум 5 физических или виртуальных машин с установленной OS Debian.

Требуется:
Развернуть кластер минимально работоспособный кластер Kubernetes в составе:

Данную инструкцию писал для себя. Если Вы будете ее использовать - используйте на свой страх и риск. И не забывайте менять ip адреса и параметры в настройках.

Предварительная подготовка control-plane серверов
Установим на все три сервера, которые планируем использовать для control-plane OS Debian 12 в минимальной конфигурации, без графического интерфейса.

Сервера должны удовлетворять минимальным требованиям:

1
Product_uuid можно поглядеть #cat /sys/class/dmi/id/product_uuid
2
Control-plane node(s):

Protocol Direction Port Range Purpose Used By
TCP Inbound 6443 Kubernetes API server All
TCP Inbound 2379-2380 etcd server client API kube-apiserver, etcd
TCP Inbound 10250 kubelet API Self, Control plane
TCP Inbound 10259 kube-scheduler Self
TCP Inbound 10257 kube-controller-manager Self

Worker node(s):

Protocol Direction Port Range Purpose Used By
TCP Inbound 10250 kubelet API Self, Control plane
TCP Inbound 30000-32767 NodePort Services* All

Любые номера портов, отмеченные знаком *, могут быть в переопределены в Вами в дальнейшем.

Вообще, по моему мнению, выставлять кластер во внешние сети - это простой и быстрый способ создать себе проблемы. Между внешними сетями (например internet) и кластером обязательно должен быть межсетевой экран.

Замечаение про Swap:
По умолчанию, поддержка swap в kubernetes отключена. Можно включить поддержку swap в настройках, но так как это просто пример развертывания kubernetes кластера - просто отключим swap на всех серверах.

Планируем

Спланируем, как будут называться наши ноды в кластере, и какие у них будут IP:

Имя ноды IP
k8s-master-71 192.168.254.71
k8s-master-72 192.168.254.72
k8s-master-73 192.168.254.73
k8s-worker-74 192.168.254.74
k8s-worker-75 192.168.254.75

Так же, зарезервируем на будущее ip - 192.168.254.70. Это у нас будет ip адрес для доступа к кластеру, не привязанный к конкретной ноде (для высокой доступности кластера).

Настраиваем ноды

Для примера, приведу настройку одной ноды. То же самое нужно сделать на всех нодах, изменив их имена и адреса соответственно.

Ставим sudo, всегда работать от имени root-а - это нехорошо и небезопасно.

apt install sudo
usermod -aG sudo <username>

Отключаем Swap:

swapoff -a

и комментируем строчку в файле /etc/fastb которая отвечает за загрузку swap

При необходимости немного настроим сеть:
Правим /etc/network/interfaces
в нем конфигурируем сетевой интерфейс:

# The primary network interface
allow-hotplug <interface_name>
iface <interface_name> inet static
address 192.168.254.71/24
gateway 192.168.254.1

Правим /etc/resolv.conf
в нем прописываем dns сервер:

nameserver 8.8.4.4

Правим /etc/hosts в нем прописываем все наши ноды - их адреса и имена:

192.168.254.70  k8s-master
192.168.254.71  k8s-master-71
192.168.254.72  k8s-master-72
192.168.254.73  k8s-master-73
192.168.254.74  k8s-worker-74
192.168.254.75  k8s-worker-75

Ставим дополнительные необходимые пакеты

sudo apt update
sudo apt upgrade -y
sudo apt install curl apt-transport-https ca-certificates gnupg2 wget socat chrony -y

Загружаем модули и меняем sysctl

sudo modprobe overlay
sudo modprobe br_netfilter

Правим(создаем) файл: sudo nano /etc/sysctl.d/kubernetes.conf
и в него добавляем:

net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1

Правим(создаем) файл: sudo nano /etc/modules-load.d/containerd.conf и в него добавляем:

overlay
br_netfilter

Применяем изменения:

sudo sysctl --system

Устанавливаем containerd

Получаем ключик:

sudo mkdir -m 0755 -p /etc/apt/keyrings
sudo wget https://download.docker.com/linux/debian/gpg -O /etc/apt/keyrings/docker.asc
sudo chmod 644 /etc/apt/keyrings/docker.asc  

Получаем репы:

sudo echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

Устанавливаем последнею версию containerd

sudo apt-get install containerd.io

Немного ее настраиваем:

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

Запускаем:

sudo systemctl restart containerd
sudo systemctl enable containerd

Устанавливаем kubeadm, kubelet и kubectl

Для начала - надо знать какую версию мы будем устанавливать.
Посмотреть какие версии есть - можно например тут.
В моем случае - актуальная версия: v1.31

Получаем ключики:

sudo wget https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key -O /etc/apt/keyrings/kubernetes-apt-keyring.asc
sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.asc  

Получаем репы:

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

Ставим kubeadm, kubelet и kubectl и замораживаем.

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

Запускаем kubelet:

sudo systemctl enable --now kubelet

Еще немного настраиваем containerd:

SAND=`kubeadm config images list | grep pause | cut -d: -f 2` && sed -i "s/:.*/\:${SAND}\"/" /etc/containerd/config.toml
systemctl restart containerd

Отказоустойчивый control-plane

Нам надо control-plane которая устойчива к сбоям и отказам. Например, к выходу из строя одной control-plane ноды.
Поэтому, на всех control-plane (и только control-plane) нодах устанавливаем keepalived.

sudo apt install keepalived -y

Приводим файл конфига keepalived (/etc/keepalived/keepalived.conf) к следующему виду:

global_defs {
  router_id MyKube_123  <= Это надо поменять
  enable_script_security
}

vrrp_script apiserver {
  script "/usr/bin/curl -s -k https://localhost:6443/healthz -o /dev/null"
  interval 20
  timeout  5
  rise     1
  fall     1
  user     root
}

vrrp_instance Kube_71 {
  state MASTER
  interface ens192  <= Это надо поменять
  virtual_router_id 51  <= Это надо поменять
  priority 100
  advert_int 1
  authentication {
      auth_type PASS
      auth_pass skdjfgkwjrhflehkurf  <= Это надо поменять
  }

  virtual_ipaddress {
      192.168.254.70 label ens192:keep  <= Это надо поменять
  }

  track_script {
      apiserver
  }
}

Запускаем keepalived на всех control-plane нодах.

systemctl restart keepalived 
systemctl enable keepalived

Устанавливать дополнительно, как указано в других местах haproxy - нет смысла. При поднятие адреса keepalived на этом же адресе поднимается порты доступа к kubeAPI.

Инициализируем кластер

Создадим файл конфигурации для kubeadm - /etc/kubernetes/kubeadm-config.yaml
В него добавим следующею конфигурацию:

---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
controlPlaneEndpoint: "192.168.254.70:6443"
clusterName: "cluster.local"
etcd:
  local:
    extraArgs:
      - name: listen-metrics-urls
        value: http://0.0.0.0:2381
networking:
  podSubnet: "10.244.0.0/16"
scheduler:
  extraArgs:
    - name: bind-address
      value: "0.0.0.0"
controllerManager:
  extraArgs:
    - name: bind-address
      value: "0.0.0.0"

---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
metricsBindAddress: 0.0.0.0
mode: ipvs
ipvs:
  strictARP: True

Актуальную версию kubeadm.k8s.io/v1beta4 можно поглядеть так:

kubeadm config print init-defaults | grep apiVersion

Подробности про параметры конфига можно прочитать тут: https://kubernetes.io/docs/reference/config-api/. Обращаем внимание на версии!

Соб-но подготовка закончена. Приступим к сбору кластера в одно целое.

На одной из нод, которая у нас будет исполнять роль control-plane запускаем:

sudo kubeadm init --config  /etc/kubernetes/kubeadm-config.yaml --upload-certs

Нода задумается и если все хорошо, выведет инструкцию по дальнейшему добавлению остальных нод в кластер.

Для добавления других control-plane нод:
kubeadm join 192.168.254.70:6443 –token egcvbl.g97lu30g8lejfiz3 \
–discovery-token-ca-cert-hash sha256:0af49752295e168f14debc45484d4fb0a2479e492b026d07916b75beb513b086 \
–control-plane –certificate-key 7070f2f345910332376947bdaf46cdcf991c208a00c8601bf6e99fa930fe3efa

И для добавления к кластер workers нод:
kubeadm join 192.168.254.70:6443 –token egcvbl.g97lu30g8lejfiz3 \
–discovery-token-ca-cert-hash sha256:0af49752295e168f14debc45484d4fb0a2479e492b026d07916b75beb513b086

На соответствующих нодах выполняем соотвествующие команды для добавления этих нод в кластер.

Примечание:
Выданные кластером токены на присоединение будут действительны:

  1. 2 часа для присоединения control-plane нод
  2. 24 часа для присоединения worker нод

по соображениям безопасности.
Однако, в любой момент можно создать новый токен для присоединения worker ноды:

sudo kubeadm token create --print-join-command

и certificate-key для присоединения control-plane нод:

kubeadm init phase upload-certs --upload-certs


Теперь проверим, все ли собралось.

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 ComponentStatus
kubectl get nodes

Мы должны увидеть состояние кластера. Он собрался, компоненты кластера работают, но ноды пока все еще не готовы так как нет сетевого плагина:

NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy ok
NAME STATUS ROLES AGE VERSION
k8s-master-71 NotReady control-plane 2m34s v1.31.1
k8s-master-72 NotReady control-plane 2m15s v1.31.1
k8s-master-73 NotReady control-plane 2m10s v1.31.1
k8s-worker-74 NotReady <none> 1m20s v1.31.1
k8s-worker-75 NotReady <none> 37s v1.31.1

Теперь самое время установить сетевой плагин flannel + MetalLB или сетевой плагин Calico CNI+PureLB.