ALT Container OS подветка K8S: различия между версиями

Материал из ALT Linux Wiki
Строка 254: Строка 254:
           label: docker
           label: docker
   filesystems:
   filesystems:
     - device: /dev/sdb1 # создадим в патиции /dev/sdb1 файловую систему BTRFS
     - device: /dev/sdb1 # создадим в партиции /dev/sdb1 файловую систему BTRFS
       format: btrfs
       format: btrfs
       wipe_filesystem: true
       wipe_filesystem: true

Версия от 10:45, 25 ноября 2021

Подветка 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-файл для форматирования, подключения тома 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-