k8s - хорошая шутка, но технологию очень сильно привязывают к облакам, например AWS и т.д. Но что делать, если у тебя есть свои мощности, и хочется поработать с k8s на своих машинах, или же просто поднять кластер на виртуалках, чтобы поучиться им пользоваться.

Я задумался, о том, что хочу поднять свой кластер, чтобы просто поучиться работать с “кубером”, на своей работе мы его не используем (да такие организации есть), но потрогать технологию хочется, особенно когда о ней много пишут, говорят, показывают)

Для начала нам нужно поднять 2 или 3 виртуальные машины. Я решил выбрать именно три. Устанавливаем на них Ubuntu 22.04 LTS

Назову я их так

k8s-master-01 IP: 192.168.88.54

k8s-node-01 IP: 192.168.88.55

k8s-node-02 IP: 192.168.99.56

Теперь начнем предварительную настройку

Настройка всех машин

Настройка системы

Сейчас я буду описывать команды, которые необходимо выполнить на все виртуалках, неважно какая у них будет роль, то есть мы настраиваем и мастер и ноды

Настоим файл hosts, чтобы было проще ориентироваться и приведем файл к подобному виду

/etc/hosts

127.0.0.1 localhost
127.0.1.1 k8s-master-01
192.168.88.54 k8s-master-01
192.168.88.55 k8s-node-01
192.168.88.56 k8s-node-02

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

В файл были добавлены эти строки

192.168.88.54 k8s-master-01
192.168.88.55 k8s-node-01
192.168.88.56 k8s-node-02

Обновим пакеты системы

apt update && apt upgrade -y && apt dist-upgrade -y

Установим необходимые пакеты

apt install curl apt-transport-https git -y

Отключаем файл подкачки

swapoff -a

И отключим монтирование этого файла при загрузке системы

В файле /etc/fstab находим строку, начинающуюся с /swap.img и комментируем ее

...
#/swap.img      none    swap    sw      0       0

Загружаем дополнительные модули ядра

Создадим файл /etc/modules-load.d/k8s.conf и запишем в него

br_netfilter
overlay

br_netfilter расширяет возможности netfilter, overlay необходим для Docker

Сразу же загрузим эти модули, чтоб не перезагружать систему

modprobe br_netfilter && modprobe overlay

И проверяем, загружены ли они

lsmod | egrep "br_netfilter|overlay"

Вывод будет примерно вот таким

overlay               151552  16
br_netfilter           32768  0
bridge                307200  1 br_netfilter

Создадим еще один файл /etc/sysctl.d/k8s.conf с содержимым

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

Данная настройка контролирует возможность обработки трафика через bridge в netfilter. В нашем примере мы разрешаем данную обработку для IPv4 и IPv6

Применяем параметры командой sysctl --system

Установка Docker

На всех узлах кластера установим Docker

apt install docker docker.io -y

Разрешаем автозапуск докера

systemctl enable docker

Создадим файл /etc/docker/daemon.json, если он уже есть, то приводим его к подобному виду

{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}

Важным параметром является настройка native.cgroupdriver, значение должно быть именно systemd. Если этого не сделать, при создании кластера k8s выдаст множество предупреждений, что по началу может сбивать с толку, но не повлияет на работоспособность кластера

И перезапускаем Docker

service docker restart

Установка Kubernetes

Установка выполняется из сторонних репозиториев, по этому для начала добавим публичный ключ проверки подписи пакетов

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

Добавим сам репозиторий создав файл /etc/apt/sources.list.d/kubernetes.list с содержимым

deb https://apt.kubernetes.io/ kubernetes-xenial main

И выполним установку

apt update && apt install kubelet kubeadm kubectl -y

Для полноценной работы кластера данные пакеты необходимо установить на всех узлах

Полноценная работа кластера сильно зависит от версий установленных пакетов, чтобы случайно не обновить пакет, требуется запретить его обновление

apt-mark hold kubelet kubeadm kubectl

Настройка Master Node k8s

Настройка системы

Теперь мы работаем только на мастер ноде. Нужно заранее решить одну проблему, которой я столкнулся на Ubuntu 22.04 LTS. Когда вы будете инициализировать мастер, он может падать.

Решение я нашел вот тут: https://github.com/kubernetes/kubernetes/issues/106464

apparently, the new Linux system which by default use cgroup v2 such as Arch linux, bullseye, ubuntu 21 , etc causing problems when deploying Kubernetes cluster using kubeadm init

по-видимому, новая система Linux, которая по умолчанию использует cgroup v2, такую как Arch linux, bullseye, ubuntu 21 и т. д., вызывает проблемы при развертывании кластера Kubernetes с использованием kubeadm init.

Решением было включить cgroup v1 при старте системы. Для этого нам нужно отредактировать файл /etc/default/grub

Находим строку GRUB_CMDLINE_LINUX_DEFAULT="" и добавим значение systemd.unified_cgroup_hierarchy=0

Пример готового файла /etc/default/grub

GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=0
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="systemd.unified_cgroup_hierarchy=0"
GRUB_CMDLINE_LINUX=""

Затем обновляем настройки grub2 update-grub и перезагружаем master node

Инициализация master node

Установим дополнительные пакеты для master node

apt update && apt install kubeadm kubectl -y

kubelet мы уже устанавливали и отключили автообновление, по этому его уже не трогаем

Так же отключим автообновление

apt-mark hold kubeadm kubectl

Установка завершена, проверяем версию k8s

kubectl version --client --output=yaml

clientVersion:
  buildDate: "2022-07-13T14:30:46Z"
  compiler: gc
  gitCommit: aef86a93758dc3cb2c658dd9657ab4ad4afc21cb
  gitTreeState: clean
  gitVersion: v1.24.3
  goVersion: go1.18.3
  major: "1"
  minor: "24"
  platform: linux/amd64
kustomizeVersion: v4.5.4

Создание кластера

Инициализация мастер ноды

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

–pod-network-cidr - задает внутреннюю подсеть для нашего кластера

Данный процесс не быстрый и занимает несколько минут, после выполнения мы увидим подобный вывод

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following 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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

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-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

  kubeadm join 192.168.88.54:6443 --token 9x5u03.gvpohd0ihswqf38x \
    --discovery-token-ca-cert-hash sha256:bb7a86234c57d4a77fab5accbe159385f25e7091b5569abcd155ff4b7d41b0da

Разберем, что нам вывели

Выполняем данные команды, чтоб конфиг k8s лежал у пользователя в домашней папке

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

Так же рекомендуется в окружение пользователя добавить переменную KUBECONFIG, можно просто выполнить эту команду

export KUBECONFIG=/etc/kubernetes/admin.conf

или лучше вот так

export KUBECONFIG=$HOME/.kube/config

Чтобы каждый раз команду не вводить, добавим ее в ENV. В файле /etc/environment добавим строку

export KUBECONFIG=$HOME/.kube/config

Можно так же в домашней папке пользователя добавить в файл ~/.bashrc, в самый низ строку export KUBECONFIG=$HOME/.kube/config

Посмотреть список узлов кластера можно данной командой

kubectl get nodes

На данном этапе мы должны увидеть только мастер ноду:

NAME            STATUS     ROLES           AGE   VERSION
k8s-master-01   NotReady   control-plane   5m   v1.27.2

Как можно увидеть, статус мастера не готов, и он так и будет висеть, пока не завершим настройку. Для этого нужно добавить CNI (Container Networking Interface) - это файл описывающий принцип работы сетевой инфраструктуры контейнеров. Их есть несколько вариантов, но пока возьмем тот, что я первый нашел в сети

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yaml

Через несколько минут мастер нода будет в статусе готовности и можно добавлять ноды в кластер

Инициализация ноды

Если так случилось, что вы потеряли команду на присоединение ноды к кластеру, то просто выполнить на мастере

kubeadm token create --print-join-command

На выводе, вы получаете команду, для присоединения ноды к кластеру

kubeadm join 192.168.99.54:6443 --token 2lobny.ji1kxd65rhr5ypl3 \
  --discovery-token-ca-cert-hash \
  sha256:bb7a86234c57d4a77fab5accbe159385f25e7091b5569abcd155ff4b7d41b0da

Выполняем данную команду на сервере k8s-node-01 (192.168.88.55) и на втором k8s-node-02 (192.168.88.56), ждем завершения процесса

После завершения работы команды, мы должны увидеть подобное

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

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

kubectl get nodes

NAME            STATUS     ROLES           AGE   VERSION
k8s-master-01   Ready      control-plane   18m   v1.27.2
k8s-node-01     Ready      <none>          80s   v1.27.2
k8s-node-02     NotReady   <none>          90s   v1.27.2

Обратите внимание, что нода k8s-node-02 имеет статус NotReady. Это значит, что настройка еще выполняется и необходимо подождать. Как правило, в течение 2 минут статус меняется на Ready

Фаервол

Разрешим через UFW порты на мастер ноде

ufw allow 6443/tcp
ufw allow 6000:6007/tcp
ufw allow 10250:10252/tcp

6443 - подключение для управления (Kubernetes API)

2379:2380 - порты для взаимодействия мастера с воркерами (etcd server client API)

10250:10252 - работа с kubelet (соответственно API, scheduler, controller-manager)

На рабочей ноде

ufw allow 10250/tcp
ufw allow 30000:32767/tcp

10250 - подключение к kubelet API

30000:32767 - рабочие порты по умолчанию для подключения к подам (NodePort Services)

И наш кластер готов. В следующий раз опишу, как можно работать с данным кластером и как пользоваться k8s

Анонсы и еще больше информации в Telegram-канале