ALT Container OS подветка K8S
Подветка K8S обеспечивает разворачивание серверов для организации kubernetes-кластера.
В настоящее время (16.11.2021) дистрибутив ALTLinux обеспечивает разворачивание kubernetes-кластера под двумя типами "движков" (см. Kubernetes):
- docker;
- CRI-O (podman)
В текущей реализации был выбран вариант движка CRI-O, обеспечивающий повышенный уровень защиты запускаемых контейнеров. Но, так как подветка K8S наследуется от основной ветки потока, включающей движок docker, в рамках данной подветки можно запускать docker-контейнеры, сервисы под docker-compose и организовывать параллельно (или вместо) с кластером kubernetes и docker swarm кластер.
QCOW2 образ подветки altcos/x86_64/Sisyphus/k8s
В настоящее время реализован образ QCOW2 подветки altcos/x86_64/sisyphus/k8s. Скачать его можно по следующим ссылкам: [Полный] [Сжатый]
Образ включает в себя архив docker-образов, необходимых для разворачивания kubernetes-кластера. Так что для разворачивания кластера доступ в Интернет не нужен.
Запуск образа в режиме master-узла через qemu-system-x86_64
Подготовка YML butane-файла для master-узла
Для запуска необходимо подготовить YML butane-файл, обеспечивающий следующий функционал при запуске образа:
- обеспечение доступа без пароля администратора по открытому ключу под пользователем altcos (passwd.users.ssh_authorized_keys)
- получение без пароля прав администратора (sudo) для пользователя altcos (файл /etc/sudoers.d/altcos);
- формирование переменных окружения для вызова команды kubectl (файл /etc/profile.d/kube.sh);
- создание systemd-сервиса для инициализации master-узла kubernetes-кластера.
Файл конфигурации k8s_master.yml выглядит следующим образом:
variant: fcos version: 1.3.0 passwd: users: - name: root groups: - wheel - docker password_hash: ... ssh_authorized_keys: - ssh-rsa ... - name: altcos groups: - wheel - docker password_hash: ... ssh_authorized_keys: - ssh-rsa ... storage: files: - path: /etc/sudoers.d/altcos contents: inline: | altcos ALL=NOPASSWD: ALL - path: /etc/profile.d/kube.sh mode: 0755 contents: inline: | # Set kube environment if [ `id -u ` = 0 ] then export KUBECONFIG=/etc/kubernetes/admin.conf else if [ -f /etc/kubernetes/admin.conf ] then if [ ! -d ~/.kube ] then mkdir -p ~/.kube sudo cp -i /etc/kubernetes/admin.conf ~/.kube/config sudo chown $(id -u):$(id -g) ~/.kube/config kubectl completion bash >> ~/.bashrc fi fi fi - path: /etc/hostname overwrite: true contents: inline: master01 systemd: units: - name: initk8smaster.service enabled: false contents: | [Unit] Description=Start up kubernetes in master mode After=crio.service kube-proxy.service kubelet.service systemd-networkd.service systemd-resolved.service [Service] Type=oneshot RemainAfterExit=yes Environment="KUBECONFIG=/etc/kubernetes/admin.conf" ExecStartPre=loadDockerArchiveImages.sh ExecStart=kubeadm init --cri-socket=/var/run/crio/crio.sock --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=SystemVerification --kubernetes-version=v1.20.12 ExecStartPost=kubectl taint nodes localhost node-role.kubernetes.io/master- [Install] WantedBy=multi-user.target
Запуск образа как master-узла
Запуск образа производится скриптом run_master.sh:
#!/bin/sh if ! butane -p k8s_master.yml > k8s_master.ign then exit 1; fi cp ~altcos/ALTCOS/streams/altcos/x86_64/sisyphus/k8s/images/qcow2/k8s.20211118.0.0.qcow2 k8s.qcow2 sudo qemu-system-x86_64 \ -m 2048 \ -machine accel=kvm \ -cpu host \ -smp 2 \ -hda k8s.qcow2 \ -fw_cfg name=opt/com.coreos/config,file=k8s_master.ign \ -net user,hostfwd=tcp::10222-:22 -net nic
Команда butane производит конвертацию butane-файла YML 'k8s_master.yml' в JSON-формате ignition в файл k8s_master.ign.
Команда cp копирует образ ядра в файл k8s.qcow2.
Обратите внимание, что для работы узла kubernetes требуется не менее 2-х ядер процессора и не менее 2GB оперативной памяти.
Доступ по протоколу ssh обеспечивается через порт 10222 HOST-компьютера localhost.
Запуск kubernetes на master-узле
Для того, чтобы запустить сервис:
- зайдите через консоль или через ssh под пользователем altcos;
- выполните запуск сервиса initk8smaster:
$ sudo systemctl start initk8smaster
Данные действия можно сделать и "удаленно" по протоколу ssh:
ssh -p 10222 altcos@localhost sudo systemctl start initk8smaster
Во время запуска длительностью менее минуты:
- производится загрузка из архива, входящего в состав qcow2-образа, необходимых docker-образов;
- запуск их как сервисов;
- инициализация master-узла кластера;
Логи запуска можно посмотреть командой:
$ journalctl -u initk8s Starting Start up kubernetes in master mode... ... Loaded image(s): k8s.gcr.io/coredns:1.7.0 ... Loaded image(s): k8s.gcr.io/etcd:3.4.13-0 ... Your Kubernetes control-plane has initialized successfully! ... Then you can join any number of worker nodes by running the following on each as root: kubeadm join 10.0.2.15:6443 --token yhhb22.0q7bovdkg89l6hr7 \ --discovery-token-ca-cert-hash sha256:16a864c569f23a5ecacafe5cb42931840fc7e4896b8c3946d0710133ea0b82bc ... node/localhost untainted Finished Start up kubernetes in master mode.
Рабочие (worker) узлы можно присоединять к кластеру указанной командой
kubeadm join ...
Работа с master-узлом кластера
Вы можете работать с мастер узлом как под обычным пользователем (например altcos), так и от имени суперпользователя.
Файл ~/.kube/config в домашнем каталоге пользователя altcos автоматически создается скриптом /etc/profile.d/kube.sh, описанным в YML-butane файле, при входе в пользователя altcos после инициализации узла кластера.
Для работы с master-узлом кластера из суперпользователя укажите при вызове sudo флаг -i. Например:
sudo -i kubectl get all -A
Проверка работы master-узла
Для проверки работы узла наберите команду
# kubectl get nodes NAME STATUS ROLES AGE VERSION localhost Ready control-plane,master 41m v1.20.8
Для проверки работы всего функционала наберите команду:
$ kubectl get all -A NAMESPACE NAME READY STATUS RESTARTS AGE kube-system pod/coredns-74ff55c5b-b4rxp 1/1 Running 0 9h kube-system pod/coredns-74ff55c5b-kfsxv 1/1 Running 0 9h kube-system pod/etcd-localhost 1/1 Running 0 9h kube-system pod/kube-apiserver-localhost 1/1 Running 0 9h kube-system pod/kube-controller-manager-localhost 1/1 Running 0 9h kube-system pod/kube-proxy-4t95d 1/1 Running 0 9h kube-system pod/kube-scheduler-localhost 1/1 Running 0 9h NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE default service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9h kube-system service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 9h NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE kube-system daemonset.apps/kube-proxy 1 1 1 1 1 kubernetes.io/os=linux 9h NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE kube-system deployment.apps/coredns 2/2 2 2 9h NAMESPACE NAME DESIRED CURRENT READY AGE kube-system replicaset.apps/coredns-74ff55c5b 2 2 2 9h
Должен быть:
- развернут deployment 'coredns' с двумя репликами (replicaset coredns-xxx, pods-xxx-yyy;
- запушен daemonset 'kube-proxy' с одной (по числу узлов) репликой;
Все перечисленные POD'ы должны иметь состояние READY 1/1.
В kubernetes по умолчанию на master-узле не могут запускаться поды в namespace default. В одноузловом варианте в данном примере для снятия этого ограничения (см. YML-файл выше) запускается команда
kubectl taint nodes localhost node-role.kubernetes.io/master-
Для проверки запуска POD'ов на master-узле в namespace default наберите команду:
kubectl apply -f https://k8s.io/examples/application/deployment.yaml
Поcле загрузки образа nginx проверьте запуск POD'а на master-узле:
# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-deployment-66b6c48dd5-5nfc6 1/1 Running 0 8m16s nginx-deployment-66b6c48dd5-j8mww 1/1 Running 0 8m16s
Действия после перезагрузке системы
После перезагрузки системы никаких дополнительных действий не требуется. master-узел kubernetes-кластера поднимается автоматически.
Подключение дополнительного BTRFS диска
Так как размер основного диска достаточно небольшой (около 4GB) для хранения образов и запуска pod'ов необходимо создать дополнительный диск. В приведенных ниже примерах для хранения каталогов образов, контейнеров, ... в docker и OCI-R создается и монтируется отдельный диск с файловой системой BTRFS.
Формирование YML butane-файла
Сформируем YML butane-файл k8s_master_btrfs.yml для форматирования, подключения тома BTRFS, изменения каталогов размещения данных docker-демона и CRI-O/podman:
variant: fcos version: 1.3.0 ignition: config: merge: - local: k8s_master.ign storage: disks: - device: /dev/sdb # создадим на диске /dev/sdb партицию /dev/sdb1 wipe_table: true partitions: - number: 1 label: docker filesystems: - device: /dev/sdb1 # создадим в партиции /dev/sdb1 файловую систему BTRFS format: btrfs wipe_filesystem: true label: docker with_mount_unit: false directories: - path: /var/mnt/docker # создадим каталог монтирования тома overwrite: true files: - path: /etc/fstab # добавим строку монтирования btrfs-тома на каталог /var/mnt/docker append: - inline: | LABEL=docker /var/mnt/docker btrfs defaults 0 2 # заменим в конфигурации dockerd-демона: # тип storage-driver с overlay2 на btrfs # изменим каталог размещения данных docker-демона с /var/lib/docker на /var/mnt/docker/docker/ - path: /etc/docker/daemon.json overwrite: true contents: inline: | { "init-path": "/usr/bin/tini", "userland-proxy-path": "/usr/bin/docker-proxy", "default-runtime": "docker-runc", "live-restore": true, "log-driver": "journald", "runtimes": { "docker-runc": { "path": "/usr/bin/runc" } }, "default-ulimits": { "nofile": { "Name": "nofile", "Hard": 64000, "Soft": 64000 } }, "data-root": "/var/mnt/docker/docker/", "storage-driver": "btrfs" } # заменим в конфигурации CRI-O, podman: # тип driver с overlay2 на btrfs # изменим каталог размещения данных docker-демона с /var/lib/containers/storage на /var/mnt/docker/containers/storage - path: /etc/containers/storage.conf overwrite: true contents: inline: | [storage] driver = "btrfs" runroot = "/var/run/containers/storage" graphroot = "/var/mnt/docker/containers/storage" [storage.options] additionalimagestores = [ ] [storage.options.overlay] mountopt = "nodev,metacopy=on"
Данный YML-файл:
- в элементе ignition.config.merge.local импортирует из файла k8s_master.ign описанную выше в файле k8s_master.yml конфигурацию сливая(merge) ее с нижеописанной конфигурацией;
- создает раздел /dev/sdb1;
- создает в разделе файловую систему типа BTRFS;
- создает каталог монтирования /var/mnt/docker;
- добавляет в /etc/fstab строку монтирования файловой системы раздела /dev/sdb1 в каталог /var/mnt/docker;
- заменяет файлы конфигурации docker-демона и OCI-R/podman, указывая тип драйвера с overlay2 на btrfs и перемещая каталоги хранения слоев образов и контейнеров из каталога /var/lib диска /dev/sda1 в каталог /var/mnt/docker диска /dev/sdb1.
Запуск образа как master-узла с хранилищем образов и контейнеров на BTRFS-диске
Запуск образа производится скриптом run_master_btrfs.sh
#!/bin/sh if ! butane -d . -p k8s_master_btrfs.yml > k8s_master_btrfs.ign then exit 1; fi cp ~altcos/ALTCOS/streams/altcos/x86_64/sisyphus/k8s/images/qcow2/k8s.20211118.0.0.qcow2 k8s.qcow2 qemu-img create -f qcow2 hdb.qcow2 10G sudo qemu-system-x86_64 \ -m 2048 \ -machine accel=kvm \ -cpu host \ -smp 2 \ -hda k8s.qcow2 \ -hdb hdb.qcow2 \ -fw_cfg name=opt/com.coreos/config,file=k8s_master_btrfs.ign \ -net user,hostfwd=tcp::10222-:22 -net nic
Данный скрипт аналогичен вышеописанному run_master.sh за исключением:
- используется файл конфигурации k8s_master_btrfs.yml объединяющий свои описания с описанием ignition-файла конфигурации k8s_master.ign, сформированного на предыдущем шаге и записывающий объединенную конфигурация в файл k8s_master.ign.
- формируется файл hdb.qcow2 размером 10GB для тома с файловой системой BTRFS;
- при вызове qemu-system-x86_64 данный файл указывается как второй том в параметре -hdb.
Все остальные действия по инициализации одноузлового кластера kubetnetes и работе с ним аналогичны описанным в предыдущем разделе.
Создание kubernet-кластера в среде libvirt
Установите пакеты virt-manager, virt-install. Запустите virt-manager и включите в Правка/Свойства подключения/Виртуальные сети сеть default, изменив значение Диапазон DHCP- c 192.168.122.2 - 192.168.122.254 на 192.168.122.129 - 192.168.122.254.
В описанном выше примере создается kubernetes кластер из 3-х узлов:
- master01 с IP-адресом 192.168.122.65;
- worker01 с IP-адресом 192.168.122.66;
- worker02 с IP-адресом 192.168.122.67.
Установка master-узла master01
Формирование YML butane-файла для узла master01
Cформируем YML butane-файл:
variant: fcos version: 1.3.0 ignition: config: merge: - local: k8s_master_btrfs.ign storage: files: - path: /etc/hostname overwrite: true contents: inline: master01 - path: /etc/hosts append: - inline: | 192.168.122.65 master01 192.168.122.66 worker01 192.168.122.67 worker02 - path: /etc/systemd/network/20-wired.network overwrite: true contents: inline: | [Match] Name=eth0 [Network] DHCP=no Address=192.168.122.65/24 Gateway=192.168.122.1 DNS=192.168.122.1 systemd: units: - name: initk8smaster01.service enabled: false contents: | [Unit] Description=Start up kubernetes in master mode After=crio.service kube-proxy.service kubelet.service systemd-networkd.service systemd-resolved.service [Service] Type=oneshot RemainAfterExit=yes Environment="KUBECONFIG=/etc/kubernetes/admin.conf" ExecStartPre=loadDockerArchiveImages.sh ExecStart=kubeadm init --cri-socket=/var/run/crio/crio.sock --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=SystemVerification --kubernetes-version=v1.20.12 ExecStartPost=kubectl apply -f /usr/share/k8s/flannel/kube-flannel.yml #ExecStartPost=kubectl taint nodes master01 node-role.kubernetes.io/master- [Install] WantedBy=multi-user.target
Данный YML-файл:
- в элементе ignition.config.merge.local импортирует из файла k8s_master_btrfs.ign описанную выше в файле k8s_master_btrfs.ign конфигурацию сливая(merge) ее с нижеописанной конфигурацией;
- заменяет в файле /etc/hosts имя узла на master01;
- добавляя в файл /etc/hosts привязку имен узлов master01, worker01, worker02 к их IP-адресам;
- перезаписывает файл конфигурации интерфейса eth0, указывая в ней IP-адреса master-узла, шлюза и DNS-сервера;
- создает unit-сервис initk8smaster01.service для инициализации узла master01.
В отличие от односервеного варианта unit-сервис initk8smaster01.service:
- загружает и конфигурирует overlay-сеть flannel для маршрутизации трафика между узлами;
- не снимает ограничение (taint) на запуск на master-узле POD'ов из namespace default.
Если Вы планируете запускать POD'ы из namespace default на master-узле раскомментируйте:
ExecStartPost=kubectl taint nodes master01 node-role.kubernetes.io/master-
Запуск образа как master01
Запуск образа производится скриптом createMaster1.sh:
#!/bin/sh if ! butane -d . -p k8s_master_1.yml > k8s_master_1.ign then exit 1 fi cp ~altcos/ALTCOS/streams/altcos/x86_64/sisyphus/k8s/images/qcow2/k8s.20211125.0.0.qcow2 k8s_master_1.qcow2 qemu-img create -f qcow2 master01_hdb.qcow2 10G virt-install --name k8s_master_1 \ --vcpus 2 \ --ram 2048 \ --os-variant altlinux1.0 \ --import \ --disk k8s_master_1.qcow2 \ --disk master01_hdb.qcow2 \ --vnc \ --qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=/home/kaf/K8S/k8s_master_1.ign"
После запуска образа перейдите в одно Менеджера виртуальных машин и проверьте запуск виртуальной машины --name k8s_master_1.
После запуска виртуальной машины:
- зайдите на нее по протоколу ssh:
ssh altcos@192.168.122.65
- запустите сервис инициализации master-узла:
sudo systemctl start initk8smaster01
- проверьте подъема всех необходимых сервисов:
sudo -i kubectl get all -A
В течении минуты вывод команды должен быть следующий:
NAMESPACE NAME READY STATUS RESTARTS AGE kube-system pod/coredns-74ff55c5b-c9z4j 1/1 Running 0 82s kube-system pod/coredns-74ff55c5b-s8ntc 1/1 Running 0 82s kube-system pod/etcd-master01 1/1 Running 0 16s kube-system pod/kube-apiserver-master01 1/1 Running 0 16s kube-system pod/kube-controller-manager-master01 1/1 Running 0 13s kube-system pod/kube-flannel-ds-xlkwf 1/1 Running 0 82s kube-system pod/kube-proxy-x4pwc 1/1 Running 0 82s kube-system pod/kube-scheduler-master01 1/1 Running 0 31s NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE default service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 98s kube-system service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 97s NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE kube-system daemonset.apps/kube-flannel-ds 1 1 1 1 1 <none> 97s kube-system daemonset.apps/kube-proxy 1 1 1 1 1 kubernetes.io/os=linux 97s NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE kube-system deployment.apps/coredns 2/2 2 2 97s NAMESPACE NAME DESIRED CURRENT READY AGE kube-system replicaset.apps/coredns-74ff55c5b 2 2 2 82s
Генерация ssh-ключей и запоминание открытого ключа
Находясь в пользователя altcos master-узла сгенерируйте ssh-ключи для беспарольного доступа на остальные узла кластера.
$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/var/home/altcos/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /var/home/altcos/.ssh/id_rsa Your public key has been saved in /var/home/altcos/.ssh/id_rsa.pub The key fingerprint is: SHA256:21N0WApmbf9bk61SK9NMMYRO00MCUhhxHmgc28zbYxk altcos@master01 The key's randomart image is: +---[RSA 3072]----+ | .=BOo.+o | | =@ o*=+ | | .. =+E+.. | | +.++ | | S . * +o| | o o .oo+| | . o = o+| | .+ =. | | + | +----[SHA256]-----+
Скопируйте открытый ключ из файла /var/home/altcos/.ssh/id_rsa.pub. Он будет использовать при формировании YML butane-файла для worker-узлов.
Формирование строки подключения worker-узла к кластеру
Находясь в пользователя altcos master-узла наберите команду просмотра логов сервиса initk8smaster0:
journalctl -u initk8smaster0
Найдите в логах строку подключения к кластеру:
kubeadm join 192.168.122.65:6443 --token ... --discovery-token-ca-cert-hash sha256:...
Скопируйте ее добавив к ней параметр --cri-socket=/var/run/crio/crio.sock . Данная строка будет использоваться при формировании YML butane-файла для worker-узлов.