Развёртывание Kubernetes-кластера в Debian
Требуется: развернуть Kubernetes-кластер для получения опыта, связанного с настройкой и управлением Kubernetes-кластера, и дальнейшего его использования для разработки и хостинга персональных проектов.
Минимальная конфигурация кластера может состоять из одного-двух узлов: либо один master, которому разрешено хостить пользовательские нагрузки, либо один master и один worker. Однако, подобный кластер не будет, даже близко, похож на типичный промышленный high available (HA) кластер, а значит, полученный опыт будет сильно ограничен как в процессе развёртывания, так и в процессе эксплуатации. Конечно, ни о каком HA-кластере на одной физической машине речи быть не может, но, напомню, главная цель — получение опыта и площадки для экспериментов. К слову, если для разработки нужен кластер на рабочей станции, скажем для разработки cloud native приложений, или для изучения простейших команд kubectl, отличным выбором будет minikube.
Как выглядит минимально-достаточный промышленный HA Kubernetes-кластер?
- от двух master-узлов,
- от трёх etcd-узлов и load balancer для них,
- от двух worker-узлов.
Если мы будем хостить какие-либо web-приложения в кластере, доступ к которым необходимо обеспечить извне, может потребоваться либо внешний load balancer, либо ingress. Однако, это отдельная большая тема, достойная отдельной статьи.
Нам потребуется 5 виртуальных машин. На первых трёх будут развёрнуты master-узлы Kubernetes и etcd-серверы. На двух оставшихся worker-узлы Kubernetes и узлы haproxy-кластера.
Важный момент, почему мастеров 3? Дело в том, что etcd-узлов в кластере должно быть не менее трёх. Если их будет 2, в случае если один из них выйдет из строя или будет отключён, голосование по выбору лидера etcd-кластера не сможет завершиться, и единственный оставшийся etcd-узел будет недоступен, а вместе с ним и функциональность Kubernetes-кластера. Таким образом, узлов в etcd-кластере должно быть не менее 3. etcd-узлы я планирую размещать вместе с master-узлами Kubernetes, чтобы не плодить виртуалки. Поэтому master-узлов должно быть 3.
Worker-узлов может быть любое количество. Я выбрал 2, чтобы можно было симулировать выход одного из них из строя и наблюдать за миграцией подов на оставшийся. Добавить новые worker-узлы в кластер можно в любой момент.
Файл настроек
Создайте новую папку на машине, имеющей сетевой доступ к виртуалкам. В данной папке будут размещаться скрипты, которые будут запускаться на виртуалках. Далее по тексту я буду называть эту папку рабочей.
Все скрипты будут использовать общие настройки, которые я разместил в отдельном файле variables.sh. Создайте его в рабочей папке.
#!/bin/bash # IP-адреса и имена хостов мастер-узлов Kubernetes. Замените на свои. master1_IP=192.168.3.211 master2_IP=192.168.3.212 master3_IP=192.168.3.213 master1_Hostname=master1 master2_Hostname=master2 master3_Hostname=master3 # IP-адрес и имя хоста, на котором выполняется скрипт. thisHostname=$(hostname) thisIP=$(hostname -i) # etcd-token. Замените на свой. Может быть любой строкой. etcdToken=my-etcd-cluster-token # CRI-socket. containerdEndpoint=unix:///run/containerd/containerd.sock # Версии пакетов. Замените на текущие актуальные. etcdVersion=3.5.8 containerdVersion=1.6.20 runcVersion=1.1.1 cniPluginsVersion=1.1.1 kubernetesVersion=1.27.1 calicoVersion=3.22 # Пространство адресов подов. Зависит от CNI-плагина. В данном случае используется Calico. podSubnet=10.10.0.0/16 # Пространство адресов сервисов. Замените на своё. Может быть любое, но должно быть достаточно большим. serviceSubnet=10.46.0.0/16
Параметры, которые можно/нужно заменить помечены соответствующим комментарием. Назначение параметров должно быть понятно из их имён.
Развёртывание etcd
etcd используется в качестве основного хранилища информации о состоянии Kubernetes-кластера. Считайте, что это его база данных. Для устойчивости к отказам этого хранилища, как было сказано ранее, необходимо создать etcd-кластер. etcd можно развернуть различными способами, но я выбрал самый простой: развернуть на том же «виртуальном железе», что и master-узлы.
Создаём скрипт развёртывания etcd-узла install-etcd.sh в рабочей папке:
#!/bin/bash
source variables.sh
etcdEnvironmentFilePath=/etc/etcd.env
serviceFilePath=/etc/systemd/system/etcd.service
function installAndConfigurePrerequisites {
apt install curl -y
}
function downloadAndInstallEtcd {
curl -L https://github.com/etcd-io/etcd/releases/download/v${etcdVersion}/etcd-v${etcdVersion}-linux-amd64.tar.gz --output etcd-v${etcdVersion}-linux-amd64.tar.gz
tar -xvf etcd-v${etcdVersion}-linux-amd64.tar.gz -C /usr/local/bin/ --strip-components=1
}
function createEnvironmentFile {
cat > ${etcdEnvironmentFilePath} <<EOF
${thisHostname} > ${etcdEnvironmentFilePath}
${thisIP} >> ${etcdEnvironmentFilePath}
EOF
}
function createServiceFile {
cat > $serviceFilePath <<EOF
[Unit]
Description=etcd
Documentation=https://github.com/coreos/etcd
Conflicts=etcd.service
Conflicts=etcd2.service
[Service]
EnvironmentFile=/etc/etcd.env
Type=notify
Restart=always
RestartSec=5s
LimitNOFILE=40000
TimeoutStartSec=0
ExecStart=/usr/local/bin/etcd \\
--name ${thisHostname} \\
--data-dir /var/lib/etcd \\
--listen-peer-urls http://${thisIP}:2380 \\
--listen-client-urls http://0.0.0.0:2379 \\
--advertise-client-urls http://${thisIP}:2379 \\
--initial-cluster-token ${etcdToken} \\
--initial-advertise-peer-urls http://${thisIP}:2380 \\
--initial-cluster ${master1_Hostname}=http://${master1_IP}:2380,${master2_Hostname}=http://${master2_IP}:2380,${master3_Hostname}=http://${master3_IP}:2380 \\
--initial-cluster-state new
[Install]
WantedBy=multi-user.target
EOF
}
function removeDownloads {
rm -f etcd-v${etcdVersion}-linux-amd64.tar.gz
}
installAndConfigurePrerequisites
downloadAndInstallEtcd
createEnvironmentFile
createServiceFile
removeDownloads
systemctl enable --now etcd
И копируем все скрипты из рабочей папки в папку /root каждой виртуалки master-узлов Kubernetes (здесь и далее показано только для одной виртуалки):
scp *.sh root@192.168.3.211:/root
SSH-клиент запросит пароль (если вы его установили) доступа к приватному SSH-ключу и скопирует скрипты.
Последовательно подключаемся по SSH к каждому master-узлу и запускаем скрипт из папки /root:
./install-etcd.sh
Стоит отметить, что пока не отработает скрипт на втором узле, запущенный скрипт на первом узле не завершит своё выполнение. Это связано с тем, что etcd не может завершить голосование по выбору лидера пока не будет хотя бы двух узлов в кластере.
После того как скрипт на всех трёх master-узлах будет запущен, статус etcd-узлов должен стать active (running):
● etcd.service - etcd
Loaded: loaded (/etc/systemd/system/etcd.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2023-05-12 08:59:58 MSK; 4min 34s ago
Docs: https://github.com/coreos/etcd
Main PID: 412 (etcd)
Tasks: 12 (limit: 4657)
Memory: 209.9M
CPU: 14.905s
CGroup: /system.slice/etcd.service
└─412 /usr/local/bin/etcd --name master1 --data-dir /var/lib/etcd --listen-peer-urls http://192.168.3.211:2380 --listen-cli>
…а статус всего etcd-кластера должен выглядеть примерно так:
root@master1:~# etcdctl --write-out=table --endpoints=192.168.3.211:2379,192.168.3.212:2379,192.168.3.213:2379 endpoint status +--------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | +--------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | 192.168.3.211:2379 | f9f7e4f118c2fa2a | 3.5.8 | 3.8 MB | false | false | 28 | 17163 | 17163 | | | 192.168.3.212:2379 | 3e04d49b592fc75d | 3.5.8 | 3.7 MB | true | false | 28 | 17163 | 17163 | | | 192.168.3.213:2379 | 61c0872d036471cc | 3.5.8 | 3.8 MB | false | false | 28 | 17163 | 17163 | | +--------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
Установка containerd и runc
После того, как Kubernetes перестал поддерживать Dockershim (да и не нужен Docker, по большому счёту, в Kubernetes-кластере), осталось два довольно равнозначных варианта среды исполнения: containerd и CRI-O. Я выбрал первый. Поставить его можно двумя способами (компиляция из исходников не в счёт): воспользоваться репозиторием пакетов ОС или скачать релиз с GitHub. На момент написания статьи версия в репозитории Debian — 1.4.13, версия релиза в GitHub — 1.6.20. Разница существенная, поэтому я выбрал вариант с GitHub.
containerd нужно установить на всех узлах кластера
Для установки containerd в рабочей папке создаём скрипт install-containerd.sh следующего содержания:
#!/bin/bash
source variables.sh
function installAndConfigurePrerequisites {
apt install curl -y
cat <<EOF | tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
# Настройка обязательных параметров sysctl.
cat <<EOF | tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables=1
net.ipv4.ip_forward=1
net.bridge.bridge-nf-call-ip6tables=1
EOF
# Применяем изменения без перезагрузки.
sysctl --system
}
function downloadAndInstallContainerd {
# Загружаем релиз containerd.
curl -L https://github.com/containerd/containerd/releases/download/v${containerdVersion}/containerd-${containerdVersion}-linux-amd64.tar.gz --output containerd-${containerdVersion}-linux-amd64.tar.gz
tar -xvf containerd-${containerdVersion}-linux-amd64.tar.gz -C /usr/local
# Создаём файл конфигурации containerd.
mkdir /etc/containerd/
containerd config default > /etc/containerd/config.toml
# Разрешаем использование systemd cgroup.
sed -i "s/SystemdCgroup = false/SystemdCgroup = true/g" /etc/containerd/config.toml
# Создаём файл сервиса containerd.
cat > /etc/systemd/system/containerd.service <<EOF
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target
[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/containerd
Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=infinity
TasksMax=infinity
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
EOF
# Разрешаем и запускаем сервис containerd.
systemctl daemon-reload
systemctl enable --now containerd
}
function downloadAndInstallRunc {
# Загружаем и устанавливаем низкоуровневую службу запуска контейнеров.
curl -L https://github.com/opencontainers/runc/releases/download/v${runcVersion}/runc.amd64 --output runc.amd64
install -m 755 runc.amd64 /usr/local/sbin/runc
}
function downloadAndInstallCniPlugins {
curl -L https://github.com/containernetworking/plugins/releases/download/v${cniPluginsVersion}/cni-plugins-linux-amd64-v${cniPluginsVersion}.tgz --output cni-plugins-linux-amd64-v${cniPluginsVersion}.tgz
mkdir -p /opt/cni/bin
tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v${cniPluginsVersion}.tgz
}
function removeDownloads {
rm -f containerd-${containerdVersion}-linux-amd64.tar.gz
rm -f runc.amd64
rm -f cni-plugins-linux-amd64-v${cniPluginsVersion}.tgz
}
installAndConfigurePrerequisites
downloadAndInstallContainerd
downloadAndInstallRunc
downloadAndInstallCniPlugins
removeDownloads
systemctl restart containerd
Снова копируем скрипты на все master- и worker-узлы:
scp *.sh root@192.168.3.211:/root
…и запускаем их на каждом узле:
./install-containerd.sh
После его установки проверяем, что сервис работает (должно быть Active: active (running)):
● containerd.service - containerd container runtime
Loaded: loaded (/etc/systemd/system/containerd.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2023-05-07 16:41:01 MSK; 4 days ago
Docs: https://containerd.io
Main PID: 666 (containerd)
Tasks: 119
Memory: 1.3G
CPU: 7min 4.139s
CGroup: /system.slice/containerd.service
├─ 666 /usr/local/bin/containerd
├─2591 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 6cedd48fff62593eacbbea68bdf6a01e64f401a420efa3a6e4c70177b74462c0 -address /run/cont>
├─2615 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 7240ab10082c27e67f872847e991d1b1c4421bce7319969e93fa803ab792bc8b -address /run/cont>
├─2638 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 9a4847bcdb18b25189ff5550bbc0e5fa1538d4333c3bcc83e97a9edb6c89f681 -address /run/cont>
├─2961 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id fb9cd36bc95d773b8648862dba6b984791ce87fa7e297232ccbbfd1933f4b09f -address /run/cont>
├─3002 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id ef340c8986faf39512526bacfcb8cf598848cee2876502af37e80b5d11b58891 -address /run/cont>
├─4277 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id a0590d157367ba34a12e1ad8045efefb8e4cdc94480dec1e09bab38d44b10e97 -address /run/cont>
├─4443 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 60936f49daca0fdb61f8e3cc536d1376abb960652c1030d1b075fdf94ebbf584 -address /run/cont>
└─4513 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 7b107aa8d0f19a2b772f3ae084a0b9539cc61c3e2aa4e675f8f09190cf998997 -address /run/cont>
Развёртывание первого master-узла Kubernetes
В рабочей папке создаём скрипт install-master-node.sh:
#!/bin/bash
source variables.sh
function installAndConfigurePrerequisites {
apt install -y apt-transport-https curl gnupg2 apparmor apparmor-utils
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
# Установить необходимые пакеты и зафиксировать их версию.
apt update
apt install -y kubelet=$kubernetesVersion-00
apt install -y kubeadm=$kubernetesVersion-00
apt install -y kubectl=$kubernetesVersion-00
apt-mark hold kubelet kubeadm kubectl
}
function createKubeadmConfig {
cat > kubeadm-init.yaml <<EOF
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: "${thisIP}"
nodeRegistration:
criSocket: "${containerdEndpoint}"
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v${kubernetesVersion}
apiServer:
certSANs:
- ${master1_IP}
- ${master2_IP}
- ${master3_IP}
- 127.0.0.1
controlPlaneEndpoint: ${thisIP}
etcd:
external:
endpoints:
- http://${master1_IP}:2379
- http://${master2_IP}:2379
- http://${master3_IP}:2379
networking:
podSubnet: "${podSubnet}"
serviceSubnet: "${serviceSubnet}"
dnsDomain: "cluster.local"
EOF
}
function initializeMasterNode {
kubeadm init --config=kubeadm-init.yaml
}
function installCalicoCNI {
export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl apply -f https://docs.projectcalico.org/v${calicoVersion}/manifests/calico.yaml
}
function archiveCertificates {
tar -zcvf certificates.tar.gz -C /etc/kubernetes/pki .
}
function extractCertificates {
mkdir -p /etc/kubernetes/pki
tar -xvf certificates.tar.gz -C /etc/kubernetes/pki
}
installAndConfigurePrerequisites
createKubeadmConfig
if [[ $thisIP == $master1_IP ]]; then
# На первом мастер-узле устанавливаем CNI-плагин и архивируем сертификаты
# для последующего использования на других мастер-узлах.
initializeMasterNode
installCalicoCNI
archiveCertificates
fi
if [[ $thisIP != $master1_IP ]]; then
# На не первом мастер-узле используем сертификаты, полученные с первого мастер-узла.
extractCertificates
initializeMasterNode
fi
Этот скрипт будет использоваться также и для остальных master-узлов, поэтому копируем его также и на них.
Запускаем скрипт на первом master-узле master01:
./install-master-node.sh
После успешного запуска в папке /root появится архив с сертификатами кластера certificates.tar.gz, который необходимо скопировать в папки /root остальных master-узлов.
В результате успешного выполнения вы должны получить примерно такой вывод:
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join 192.168.3.211:6443 --token 405s55.bpe3cdieqfshw2p3 \
--discovery-token-ca-cert-hash sha256:3bdea11b4cfa3e290b687599884b0bb392caea6d07839ec648cf3e29addaca08 \
--control-plane
Необходимо сохранить данный текст, так как далее нам понадобятся два параметра из него.
Обеспечение доступа kubectl к кластеру
kubectl используется в качестве основного инструмента администрирования Kubernetes-кластера. Мы его установим на всех узлах кластера, однако, если попробовать его использовать, мы получим ошибку с достаточно непонятным текстом сообщения.
The connection to the server localhost:8080 was refused - did you specify the right host or port?
Для того, чтобы kubectl работал необходимо сказать ему, где искать конфигурацию для доступа к кластеру. Проще всего это сделать с помощью переменной окружения KUBECONFIG, указывающей на файл конфигурации. В зависимости от разных условий, файл этот может располагаться в разных местах.
- На master-узлах при работе из-под учётки root: /etc/kubernetes/admin.conf.
- На worker-узлах при работе из-под учётки root: /etc/kubernetes/kubelet.conf.
- На любых узлах при работе из-под другой учётки: $HOME/.kube/config.
В последнем случае этот файл необходимо создать или скопировать с master-узлов.
После того, как файл найден/скопирован/создан в файле .bashrc (или аналогичном, вашей командной оболочки) добавляем следующую строку (показано для случая master-узел из-под root):
export KUBECONFIG=/etc/kubernetes/admin.conf
И перезагружаем оболочку (показано для bash):
exec bash
Рекомендую установить kubectl на вашей рабочей машине.
Развёртывание остальных master-узлов Kubernetes
Для развёртывания оставшихся master-узлов используется тот же скрипт install-master-node.sh. Помимо скриптов, как было сказано ранее, необходимо скопировать в папку скриптов на целевые машины архив с сертификатами. Без этого архива скрипт не отработает. Проще всего распространить данный архив на все master-узлы можно, скопировав его вначале в рабочую папку с master01, а затем из рабочей папки на master02 и master03.
После установки посредством скрипта install-master-node.sh проверяем, что все master-узлы работают:
kubectl get nodes NAME STATUS ROLES AGE VERSION master1 Ready control-plane 25m v1.27.1 master2 Ready control-plane 11m v1.27.1 master3 Ready control-plane 7m34s v1.27.1
Развёртывание worker-узлов Kubernetes-кластера
Worker-узлы развёртываем с помощью следующего скрипта install-worker-node.sh, который необходимо создать в рабочей папке:
#!/bin/bash
source variables.sh
function installAndConfigurePrerequisites {
apt install -y apt-transport-https curl gnupg2 apparmor apparmor-utils
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt update
apt install -y kubelet=$kubernetesVersion-00
apt install -y kubeadm=$kubernetesVersion-00
apt install -y kubectl=$kubernetesVersion-00
apt-mark hold kubelet kubeadm kubectl
}
function joinMasterToCluster {
read -p "Enter token: " token
read -p "Enter SHA256 without 'sha256:' prefix: " sha
kubeadm join 192.168.3.211:6443 --token $token --discovery-token-ca-cert-hash sha256:$sha
}
installAndConfigurePrerequisites
joinMasterToCluster
Как и в предыдущих шагах копируем все скрипты на worker-узлы:
scp *.sh root@192.168.3.214:/root
Подключаемся по SSH к узлу и запускаем скрипт:
./install-worker-node.sh
В ходе его выполнения будут заданы два вопроса про токен и SHA его сертификата. Их значения нужно взять из вывода, полученного при развёртывании первого master-узла. В моём случае это были: 405s55.bpe3cdieqfshw2p3 и 3bdea11b4cfa3e290b687599884b0bb392caea6d07839ec648cf3e29addaca08 соответственно.
Время жизни токена ограничено 24 часами. Поэтому если между развёртыванием первого master-узла и worker-узла пройдёт более 24 часов, вам необходимо повторно сгенерировать этот токен. Для этого, подключившись к кластеру, необходимо выполнить следующую команду и использовать полученный токен и его хэш-сумму для скрипта install-worker-node.sh.
kubeadm token create --print-join-command
Развёртывание узлов haproxy-кластера
Последним штрихом будет создание haproxy-кластера для доступа worker-узлов к master-узлам. Зачем это нужно? Дело в том, что в конфигурации worker-узла жёстко прописывается адрес одного из master-узлов. В этом можно убедиться, найдя в файле /etc/kubernetes/kubelet.conf на worker-узле параметр server:. Если этот master-узел «приляжет», worker-узел «отвалится» от кластера. Чтобы этого не происходило, и кластер не терял свои worker-узлы, необходимо обеспечить защиту от подобных проблем. Одно из возможных решений реализовать доступ к control-plane через HA-proxy.
Создаём в рабочей папке скрипт install-haproxy.sh со следующим содержимым:
#!/bin/bash
source variables.sh
function installAndConfigurePrerequisites {
apt install -y apt-transport-https curl gnupg2 apparmor apparmor-utils
}
function downloadAndInstallHaproxy {
curl https://haproxy.debian.net/bernat.debian.org.gpg \
| gpg --dearmor > /usr/share/keyrings/haproxy.debian.net.gpg
echo deb "[signed-by=/usr/share/keyrings/haproxy.debian.net.gpg]" \
http://haproxy.debian.net bullseye-backports-2.5 main \
> /etc/apt/sources.list.d/haproxy.list
apt update
apt install -y haproxy=2.5.\*
}
function configureHaproxy {
cat > /etc/haproxy/haproxy.cfg <<EOF
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
# An alternative list with additional directives can be obtained from
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend k8s-api
bind ${thisIP}:6443
bind 127.0.0.1:6443
mode tcp
option tcplog
default_backend k8s-api
backend k8s-api
mode tcp
option tcplog
option tcp-check
balance roundrobin
default-server port 6443 inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
server apiserver1 ${master01_IP}:6443 check
server apiserver2 ${master02_IP}:6443 check
server apiserver3 ${master03_IP}:6443 check
EOF
systemctl restart haproxy
}
function connectNodeToLocalHaproxy {
# Заменить адрес мастер узла на локальный адрес узла Haproxy.
sed -i --regexp-extended "s/(server: https:\/\/)[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}/\1127.0.0.1/g" /etc/kubernetes/kubelet.conf
systemctl restart kubelet
}
installAndConfigurePrerequisites
downloadAndInstallHaproxy
configureHaproxy
connectNodeToLocalHaproxy
И, как обычно, копируем все скрипты из рабочей папки на worker-узлы:
scp *.sh root@192.168.3.214:/root
Запускаем скрипт на worker-узлах:
./install-haproxy.sh
После этого проверяем, что кластер работает и доступен:
kubectl get nodes NAME STATUS ROLES AGE VERSION master1 Ready control-plane 59m v1.27.1 master2 Ready control-plane 45m v1.27.1 master3 Ready control-plane 41m v1.27.1 worker1 Ready <none> 9m13s v1.27.1 worker2 Ready <none> 5m36s v1.27.1
