====== Обновление кластера Kubernetes ======
* [[https://admantium.medium.com/kubernetes-with-kubespray-9d7aaf04d35e|Kubernetes with Kubespray]]
===== Реклама =====
* Kubernetes - актуальное и востребованное решение для масштабирования и отказоустойчивости приложений, можно сказать - операционная система над операционными системами. Но что с обновлениями этого "монстра"? Ведь, даже обновление одной Linux системы потенциально может закончится проблемами. На нашем вебинаре мы убедимся что и здесь отказоустойчивая архитектура Kubernetes поможет нам провести эту "неприятную" операцию без "стресса"
===== Техническое задание =====
* Спланировать процедуру обновления кластера Kubernetes
* Обновить версию ОС Linux на каждом узле до актуальной
* Обновить версию Kubernetes на каждом узле до актуальной
* Убедиться, что все приложения в кластере продолжали функционировать во все это время
===== Запись вебинара =====
* [[https://rutube.ru/video/1b0cde4db02403e1e2a8a79cafda4131/]]
* Тэги: linux, кubernetes, cluster, kubespray, upgrade
===== Методическая подготовка =====
* Продолжение вебинаров [[Практические примеры Keycloak]], [[Доступ к приложениям в Bare-Metal Kubernetes]] и [[Работа с хранилищами в Kubernetes]]
===== Шаг 1. Убеждаемся, что приложение в кластере работает =====
* "Возвращаем"доступ к кeycloak в kube кластере в настройках haproxy на gate (в последней лабораторной рассматривали восстановление приложения в другом кластере из бекапа)
gate1.corp13.un:~# cat /etc/haproxy/haproxy.cfg
...
# use_backend bk-node-ingress if { ssl_fc_sni keycloak.corp13.un }
...
* [[Пакет OpenSSL#Импорт сертификата центра сертификации]]
gate1:~# curl https://keycloak.corp13.un/ #-f
* Добавим [[Сервис Keycloak#Аутентификация пользователей WEB приложения]] для удобства тестирования работоспособности приложения из командной строки
gate1:~# while : ; do \
curl -f -d "client_id=any-client" -d "client_secret=anystring" -d "grant_type=password" \
-d "username=user1" -d 'password=kcpassword1' \
https://keycloak.corp13.un/realms/corp13/protocol/openid-connect/token &>/dev/null && \
echo "YES work `date`" || \
echo "NO work `date`"; \
sleep 60; done | tee -a work.log
* Подключаемся к [[Система Kubernetes#longhorn]]
$ cp .kube/config_kube .kube/config
===== Шаг 2. Возвращаем 3-й узел в кластер etcd ====
* [[Система Kubernetes#Отладка etcd]]
* Инструкция по восстановлению control-plane
server.corp13.un:~/kubespray# pandoc -t plain docs/recover-control-plane.md | less
...
- If your new control plane nodes have new ip addresses you may have
to change settings in various places.
...
* Создаем новый kube3 (HW аналогично kubeN) и назначаем ему старый ip адрес (через установку mac и dhclient)
* Возвращаем kube3 в инвентарный файл выполняем предварительную настройку
server.corp13.un:~# ssh-copy-id kube3
server.corp13.un:~# cat /root/kubespray/inventory/mycluster/hosts.yaml
...
kube3:
ansible_host: 192.168.13.223
ip: 192.168.13.223
access_ip: 192.168.13.223
...
(venv1) server.corp13.un:~# ansible all -a 'sed -i"" -e "/swap/s/^/#/" /etc/fstab' -i /root/kubespray/inventory/mycluster/hosts.yaml --limit=kube3
(venv1) server.corp13.un:~# ansible-playbook conf/ansible/roles/nodes.yml -i /root/kubespray/inventory/mycluster/hosts.yaml --limit=kube3
* Добавляем, согласно инструкции, атрибуты etcd_member_name, секции broken_etcd (с kube3) и broken_kube_control_plane (пустую)
(venv1) server.corp13.un:~/kubespray# cat inventory/mycluster/hosts.yaml
all:
hosts:
kube1:
ansible_host: 192.168.13.221
ip: 192.168.13.221
access_ip: 192.168.13.221
etcd_member_name: etcd1
kube2:
ansible_host: 192.168.13.222
ip: 192.168.13.222
access_ip: 192.168.13.222
etcd_member_name: etcd2
kube3:
ansible_host: 192.168.13.223
ip: 192.168.13.223
access_ip: 192.168.13.223
etcd_member_name: etcd3
kube4:
ansible_host: 192.168.13.224
ip: 192.168.13.224
access_ip: 192.168.13.224
children:
kube_control_plane:
hosts:
kube1:
kube2:
kube_node:
hosts:
kube1:
kube2:
kube4:
etcd:
hosts:
kube1:
kube2:
kube3:
broken_etcd:
hosts:
kube3:
broken_kube_control_plane:
hosts:
k8s_cluster:
children:
kube_control_plane:
kube_node:
calico_rr:
hosts: {}
(venv1) server.corp13.un:~/kubespray# time ansible-playbook -i inventory/mycluster/hosts.yaml --limit etcd,kube_control_plane -e etcd_retries=10 recover-control-plane.yml
...
real 34m6.621s
...
Методические замечания
- Выключить только что созданный kube3
- Выключить с откатом на "begin upgrade k8s webinar" kube1,2,4
- Удалить только что созданный kube3
- Восстановить из снимка "Corrected etcd" kube1,2,3,4
- Дождаться запуска kubernetes и убедиться что с [[Система Kubernetes#Отладка etcd|etcd]] все в порядке
- Дождаться работы приложения (10-12 минут)
- Пока ждем, обсудить добавление kube3 как woker в kubernetes (делать не будем, все как в предыдущем вебинаре)
- Пока ждем, почистить место на узлах
- Пока ждем, подготовить все к запуску процесса обновления kubernetes
===== Шаг 3. Добавляем 3-й узел как worker в кластер kubernetes и longhorn ====
(venv1) server.corp13.un:~/kubespray# cat inventory/mycluster/hosts.yaml
...
kube_node:
hosts:
kube1:
kube2:
kube3:
kube4:
...
# broken_etcd:
# hosts:
# kube3:
# broken_kube_control_plane:
# hosts:
...
(venv1) server.corp13.un:~/kubespray# time ansible-playbook -i inventory/mycluster/hosts.yaml --limit=kube3 scale.yml
...
real 13m57.709s
...
kube3:~# apt install open-iscsi
* [[#Освобождение места для работы longhorn]] на kube1,2
===== Шаг 4. Обновляем кластер kubernetes =====
* [[https://github.com/kubernetes-sigs/kubespray/blob/master/docs/operations/upgrades.md]]
~/kubespray# pandoc -t plain docs/upgrades.md | less
...
Multiple upgrades
...
~/kubespray# git describe --tags
~/kubespray# git tag
* [[https://stackoverflow.com/questions/10312521/how-do-i-fetch-all-git-branches|How do I fetch all Git branches?]]
~/kubespray# git fetch --all
~/kubespray# git checkout v2.23.3
* [[https://github.com/kubernetes-sigs/kubespray?tab=readme-ov-file#quick-start|Kubespray - Deploy a Production Ready Kubernetes Cluster]]
~/kubespray# cp -rvfpT inventory/sample inventory/mycluster
* [[Язык программирования Python#Виртуальная среда Python]]
(venv1) ~/kubespray# pip3 install -r requirements.txt
kube1:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
kube1 Ready control-plane 183d v1.26.11
kube2 Ready control-plane 183d v1.26.11
kube3 Ready 4h44m v1.26.11
kube4 Ready 165d v1.26.11
(venv1) ~/kubespray# time ansible-playbook -i inventory/mycluster/hosts.yaml upgrade-cluster.yml
...
real 94m58.471s
...
kube1:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
kube1 Ready control-plane 183d v1.27.7
kube2 Ready control-plane 183d v1.27.7
kube3 Ready 13h v1.27.7
kube4 Ready 165d v1.27.7
* Через несколько итераций получаем обновленный кластер (в процессе потребоваться обновить систему с kubespray для создание новой виртуальной среды Python, поддерживающей новые версии требуемых компонентов)
* Так же были обновлены kube1,3 и оставлены не обновленными kube2,4 для демонстрации, что версия k8s не привязана жестко к версии OS
(venv2) server.corp13.un:~/kubespray# git describe --tags
v2.26.0
kube1:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
kube1 Ready control-plane 188d v1.30.4
kube2 Ready control-plane 188d v1.30.4
kube3 Ready 44h v1.30.4
kube4 Ready 170d v1.30.4
Методические замечания
- Наблюдать работоспособность приложения в процессе обновления
- Параллельно, обновить систему на kube1
- Завершить очную запись вебинара и остановить запись
- Дождаться завершения обновления, включить запись продемонстрировать результат обновления kubernetes и kube1
- Опционально, остановить server,kube1,2,3,4 и восстановить их из снимка "final upgrade k8s" (можно остановить запись на время запуска приложения)
- Продемонстрировать полностью обновленный kubernetes и систему на узлах
===== Дополнительные материалы =====
==== Обновление 11-го debian до 12-го ====
* [[https://www.debian.org/releases/stable/amd64/release-notes/ch-upgrading.en.html|Chapter 4. Upgrades from Debian 11 (bullseye)]]
kubeN# cat /etc/debian_version
kubeN# uname -a
kubeN# time (apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y upgrade)
...
real 4m39.581s
...
kubeN# dpkg --configure -a
kubeN# sed -i -e 's/bullseye/bookworm/g' /etc/apt/sources.list
kubeN# time (apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y upgrade)
...
real 5m55.980s
...
kubeN# cat /etc/debian_version
kubeN# time DEBIAN_FRONTEND=noninteractive apt -y full-upgrade
...
real 5m53.970s
...
kubeN# init 6
kubeN# uname -a
kubeN# apt autoremove
==== Освобождение места для работы longhorn ====
kubeN# journalctl --vacuum-time=1h
kubeN# systemctl disable rsyslog.service; apt purge rsyslog -y; rm -v /var/log/syslog* /var/log/messages*
kubeN# apt purge perl -y && apt autoremove -y
kubeN# find /tmp -type f -size +10M | xargs rm
==== Выключение кластера kubernetes ====
(venv1) server.corp13.un:~/kubespray# ansible all -m community.general.shutdown -i /root/kubespray/inventory/mycluster/hosts.yaml