Rootless kubernetes: различия между версиями

Материал из ALT Linux Wiki
Строка 300: Строка 300:
зайти в него через <code>ssh</code>.
зайти в него через <code>ssh</code>.


Для входа в namespace пользователя наберите команду :
<pre>
$ nsenter_u7s
#
</pre>


В рамках своего <code>namespace</code> пользователь <code>u7s-admin</code> имеет права <code>root</code>, оставаясь в рамках системы
с правам пользователя <code>u7s-admin</code>.


Наличие прав <code>root</code> позволает использовать системные команды,требующих <code>root-привелегий</code> для работы с сетевым, файловым окружением (эти окружения отличаются от системных): <code>ip</code>, <code>iptables</code>, <code>crictl</code>, ...
С помощью команды <code>crict</code>l можно
* посмотреть  наличие образов в системном кэше,
* удалить, загрузить образы
* посмотреть состояние контейнеров, pod'ов
* и т.п.
Кроме этого <code>namespace</code> пользователя <code>u7s-admin</code> присутствуют файлы и каталоге созданные в рамках данного
<code>namespace</code> и отсутствующие в основной системе.
Например Вы можете посмотреть логи контейнеров в каталоге <code>/var/log/pods</code> и т.п.


= Разворачивание rootless kubernetes кластера с балансировщиком REST-запросов haproxy =
= Разворачивание rootless kubernetes кластера с балансировщиком REST-запросов haproxy =

Версия от 11:11, 29 июня 2023


Общее описание

Запуск Kubernetes в режиме rootless обеспечивает запуск Podов без системных root-привелегий в рамках user namespace системного пользователя u7s-admin. Работа в этом режиме практически не требует никаких модификаций, но обеспечивает повышенные уровень защищенности kubernetes, так как клиентские приложения даже при использовании уязвимостей не могут получить права пользователя root и нарушить работу узла.

Запуск kubernetes версии 1.26.3 и старше в режиме rootless обеспечивает пакет podsec-k8s версии 1.0.5 или выше.

podsec-k8s - Быстрый старт

Установка master-узла

Инициализация master-узла

Для запуска kubernetes в режиме rootless установите пакет podsec-k8s версии 1.0.5 или выше.

apt-get install podsec-k8s

Измените переменную PATH:

export PATH=/usr/libexec/podsec/u7s/bin/:$PATH

В каталоге /usr/libexec/podsec/u7s/bin/ находятся программы, обеспечивающие работы kubernetes в rootless-режиме.

Для разворачивания master-узла запустите команду:

kubeadm init

По умолчанию уровень отладки устанавливается в 0. Если необходимо увеличить уровень отладки укажите перед подкомандой init флаг -v n. Где n принимает значения от 0 до 9-ти.

После:

  • генерации сертификатов в каталоге /etc/kuarnetes/pki,
  • загрузки образов,
  • генерации conf-файлов в каталоге /etc/kubernetes/manifests/, /etc/kubernetes/manifests/etcd/
  • запуска сервиса kubelet и Pod’ов системных kubernetes-образов

инициализируется kubernet-кластер из одного узла.

По окончании скрипт выводит строки подключения master(Control Plane) и worker-узлов:

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 xxx.xxx.xxx.xxx:6443 --token ... --discovery-token-ca-cert-hash sha256:.. --control-plane

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

kubeadm join xxx.xxx.xxx.xxx:6443 --token ... --discovery-token-ca-cert-hash sha256:...

Запуск сетевого маршрутизатора для контейенеров kube-flannel

Для перевода узла в состояние Ready, запуска coredns Pod’ов запустите flannel.

На master-узле под пользоваталем root выполните команду:

# kubectl apply -f /etc/kubernetes/manifests/kube-flannel.yml
Connected to the local host. Press ^] three times within 1s to exit session.
[INFO] Entering RootlessKit namespaces: OK
namespace/kube-flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
Connection to the local host terminated.

После завершения скрипта в течении минуты настраиваются сервисы мастер-узла кластера. По ее истечении проверьте работу usernetes (rootless kuber)


Проверка работы master-узла

На master-узле выполните команду:

# kubectl get daemonsets.apps -A
NAMESPACE      NAME              DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-flannel   kube-flannel-ds   1         1         1       1            1           <none>                   102s
kube-system    kube-proxy        1         1         1       1            1           kubernetes.io/os=linux   8h

Число READY каждого daemonset должно быть равно числу DESIRED и должно быть равно числу узлов кластера.

# kubectl get nodes -o wide
NAME       STATUS   ROLES           AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE           KERNEL-VERSION         CONTAINER-RUNTIME
<host>     Ready    control-plane   16m   v1.26.3   10.96.0.1     <none>        ALT SP Server 11100-01   5.15.105-un-def-alt1   cri-o://1.26.2

Проверьте работу usernetes (rootless kuber)

# kubectl get all -A
NAMESPACE     NAME                                   READY   STATUS    RESTARTS   AGE
kube-system   pod/coredns-c7df5cd6c-5pkkm            1/1     Running   0          19m
kube-system   pod/coredns-c7df5cd6c-cm6vf            1/1     Running   0          19m
kube-system   pod/etcd-host-212                      1/1     Running   0          19m
kube-system   pod/kube-apiserver-host-212            1/1     Running   0          19m
kube-system   pod/kube-controller-manager-host-212   1/1     Running   0          19m
kube-system   pod/kube-proxy-lqf9c                   1/1     Running   0          19m
kube-system   pod/kube-scheduler-host-212            1/1     Running   0          19m

NAMESPACE     NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
default       service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP                  19m
kube-system   service/kube-dns     ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   19m

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   19m

NAMESPACE     NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   deployment.apps/coredns   2/2     2            2           19m

NAMESPACE     NAME                                DESIRED   CURRENT   READY   AGE
kube-system   replicaset.apps/coredns-c7df5cd6c   2         2         2       19m

Состояние всех Pod’ов должны быть в 1/1.

Проверьте состояние дерева процессов:

# pstree
...
├─systemd─┬─(sd-pam)
│         ├─dbus-daemon
│         ├─nsenter.sh───nsenter───_kubelet.sh───kubelet───11*[{kubelet}]
│         └─rootlesskit.sh───rootlesskit─┬─exe─┬─conmon───kube-controller───7*[{kube-controller}]
│                                        │     ├─conmon───kube-apiserver───8*[{kube-apiserver}]
│                                        │     ├─conmon───kube-scheduler───7*[{kube-scheduler}]
│                                        │     ├─conmon───etcd───8*[{etcd}]
│                                        │     ├─conmon───kube-proxy───4*[{kube-proxy}]
│                                        │     ├─2*[conmon───coredns───8*[{coredns}]]
│                                        │     ├─rootlesskit.sh───crio───10*[{crio}]
│                                        │     └─7*[{exe}]
│                                        ├─slirp4netns
│                                        └─8*[{rootlesskit}]
...

Процесс kubelet запускается как сервис в user namespace процесса rootlesskit.

Все остальные процессы kube-controller, kube-apiserver, kube-scheduler, kube-proxy, etcd, coredns запускаются как контейнеры от соответствующих образов в user namespace процесса rootlesskit.

Обеспечение запуска обычных POD’ов на мастер-узле

По умолчанию на master-узле пользовательские Podы не запускаются. Чтобы снять это ограничение наберите команду:

# kubectl taint nodes <host> node-role.kubernetes.io/control-plane:NoSchedule-
node/<host> untainted

Инициализация и подключение worker-узла

Установите пакет podsec-k8s:

apt-get install podsec-k8s

Подключение worker-узлов

Скопируйте команду подключения worker-узла, полученную на этапе установки начального master-узла. Запустите ее:

kubeadm join xxx.xxx.xxx.xxx:6443 --token ... --discovery-token-ca-cert-hash sha256:...

По умолчанию уровень отладки устанавливается в 0. Если необходимо увеличить уровень отладки укажите перед подкомандой join флаг -v n. Где n принимает значения от 0 до 9-ти.

По окончании скрипт выводит текст:

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

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

Проверка состояния процессов

Проверьте состояние дерева процессов:

# pstree
...
├─systemd─┬─(sd-pam)
│         ├─dbus-daemon
│         ├─nsenter.sh───nsenter───_kubelet.sh───kubelet───10*[{kubelet}]
│         └─rootlesskit.sh───rootlesskit─┬─exe─┬─conmon───kube-proxy───4*[{kube-proxy}]
│                                        │     ├─rootlesskit.sh───crio───9*[{crio}]
│                                        │     └─6*[{exe}]
│                                        ├─slirp4netns
│                                        └─8*[{rootlesskit}]
...

Процесс kubelet запускается как сервис в user namespace процесса rootlesskit.

Все остальные процессы kube-proxy, kube-flannel запускаются как контейнеры от соответствующих образов в user namespace процесса rootlesskit.

Проверка готовности master и worker узлов kubernets

Зайдите на master-узел и проверьте подключение worker-узла:

# kubectl get nodes -o wide
NAME       STATUS   ROLES           AGE     VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                 KERNEL-VERSION         CONTAINER-RUNTIME
<host1>   Ready    control-plane   7h54m   v1.26.3   10.96.0.1     <none>  ALT   cri-o://1.26.2
<host2>   Ready    <none>          8m30s   v1.26.3   10.96.0.1     <none>  ALT   cri-o://1.26.2
...

Инициализация и подключение дополнительных master-узлов

Установите пакет podsec-k8s:

apt-get install podsec-k8s

Подключение master-узлов

Скопируйте команду подключения master-узла, полученную на этапе установки начального master-узла. Она отличается от команды подключения worker-узлов наличием дополнительных параметров --control-plane, --certificate-key.

Запустите ее:

kubeadm join xxx.xxx.xxx.xxx:6443 --token ... --discovery-token-ca-cert-hash sha256:...
  --control-plane --certificate-key ...  

По умолчанию уровень отладки устанавливается в 0. Если необходимо увеличить уровень отладки укажите перед подкомандой join флаг -v n. Где n принимает значения от 0 до 9-ти.

По окончании скрипт выводит текст:

This node has joined the cluster and a new control plane instance was created:

* Certificate signing request was sent to apiserver and approval was received.
* The Kubelet was informed of the new secure connection details.
* Control plane label and taint were applied to the new node.
* The Kubernetes control plane instances scaled up.
* A new etcd member was added to the local/stacked etcd cluster.

Проверка состояния процессов

Проверьте состояние дерева процессов:

# pstree
...
        ├─systemd─┬─(sd-pam)
        │         ├─dbus-daemon
        │         ├─kubelet.sh───nsenter_u7s───nsenter───_kubelet.sh───kubelet───11*[{kubelet}]
        │         └─rootlesskit.sh───rootlesskit─┬─exe─┬─conmon───kube-controller───4*[{kube-controller}]
        │                                        │     ├─conmon───kube-scheduler───8*[{kube-scheduler}]
        │                                        │     ├─conmon───etcd───9*[{etcd}]
        │                                        │     ├─conmon───kube-proxy───4*[{kube-proxy}]
        │                                        │     ├─conmon───kube-apiserver───8*[{kube-apiserver}]
        │                                        │     ├─rootlesskit.sh───crio───8*[{crio}]
        │                                        │     └─7*[{exe}]
        │                                        ├─slirp4netns
        │                                        └─8*[{rootlesskit}]

Дерево процессов должно совпадать с деревом процессов основного master-узла.

Проверка готовности master и worker узлов kubernets

На одном из master-узлов наберите команду:

# kubectl get nodes -o wide
NAME       STATUS   ROLES           AGE     VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                 KERNEL-VERSION         CONTAINER-RUNTIME
<host1>   Ready    control-plane   7h54m   v1.26.3   10.96.0.1     <none>        ALT    cri-o://1.26.2
<host2>   Ready    <none>          8m30s   v1.26.3   10.96.0.1     <none>  ALT   cri-o://1.26.2
...
<hostN>   Ready    control-plane   55m     v1.26.3   10.96.122.<N> <none>        ALT      cri-o://1.26.2
...

Использование REST-интерефейсов подключенных master-узлов

По умолчанию на подключенных master-узлах в файле /etc/kubernetes/admin.conf указан адрес API-интерфейса основного master-узла:

apiVersion: v1
clusters:
- cluster:
    ...
    server: https://<master1>:6443
...

Для балансировки нагрузки в файлах конфигурации ~user/.kube/config есть смысл указать адреса API-интерфейсов дополнительгных master-узла:

apiVersion: v1
clusters:
- cluster:
    ...
    server: https://<masterN>:6443
...

Системный пользователь u7s-admin

Все контейнеры в rootless kubernetes. включая системные работают от имени системного пользователя u7s-admin. Вы можете для мониторинга работы системы или запуска дополнительного функционала работать в системе от имени этого пользователя.

Для входа в терминальный режим этого пользователя достаточно в пользователе с правами root набрать команду:

# machinectl shell u7s-admin@ /bin/bash

или задав пароль пользователя:

# passwd u7s-admin

зайти в него через ssh.

Для входа в namespace пользователя наберите команду :

$ nsenter_u7s
#

В рамках своего namespace пользователь u7s-admin имеет права root, оставаясь в рамках системы с правам пользователя u7s-admin.

Наличие прав root позволает использовать системные команды,требующих root-привелегий для работы с сетевым, файловым окружением (эти окружения отличаются от системных): ip, iptables, crictl, ...

С помощью команды crictl можно

  • посмотреть наличие образов в системном кэше,
  • удалить, загрузить образы
  • посмотреть состояние контейнеров, pod'ов
  • и т.п.

Кроме этого namespace пользователя u7s-admin присутствуют файлы и каталоге созданные в рамках данного namespace и отсутствующие в основной системе. Например Вы можете посмотреть логи контейнеров в каталоге /var/log/pods и т.п.

Разворачивание rootless kubernetes кластера с балансировщиком REST-запросов haproxy

Ручная балансировка запросов к API-интерфейсам master-узлов путем указания у клиентов адресов различных master-узлов довольно неудобна, так как не обеспечивает равномерного распределения запросов по узлам кластера и не обеспечивает автоматической отказоустойчивости при выходе из строя master-узлов.

Решает данную проблему установка балансировщика нагрузки haproxy.

Перевод кластера в режим балансировки запросов через haproxy возможен. Подробности описаны в статье How to convert a Kubernetes non-HA control plane into an HA control plane?, но данная процедура не гарантирует корректный перевод на всех версиях kubernetes и ее не рекомендуют применять на production кластерах.

Так что наиболее надежным способом создания кластера с балансировкой запросов является создание нового кластера.

Настройка балансировщика REST-запросов haproxy

Балансировщик REST-запросов haproxy можно устанавливать как на отдельный сервер, так на один из серверов кластера.

Если балансировщик устанавливается на rootless сервер кластера, но для балансировщика необходимо выделить отдельный IP-адрес. Если на этом же сервере функционируют локальный регистратор (registry.local) и сервер подписей (sigstore.local), то IP-адрес балансировщика может совпадать c IP-адресами этих сервисов.

Если планируется создание отказоустойчивого решения на основе нескольких серверов haproxy, то для них кроме собственного IP-адреса необходимо будет для всех серверов haproxy выделить один общий IP-адрес, который будет иметь master-балансировщик.


Полная настройка отказоустойчивого кластера haproxy из 3-х узлов описана в документе ALT Container OS подветка K8S. Создание HA кластера.

Здесь же мы рассмотрим создание и настройка с одним сервером haproxy с балансировкой запросов на master-узлы.

Установите пакет haproxy:

# apt-get install haproxy

Отредактируйте конфигурационный файл /etc/haproxy/haproxy.cfg:

  • добавьте в него описание frontend’a main, принимающего запросы по порту 8443:
     frontend main
      bind *:8443
      mode tcp
      option tcplog
      default_backend apiserver
    
  • добавьте описание backend’а apiserver:
    backend apiserver
      option httpchk GET /healthz
      http-check expect status 200
      mode tcp
      option ssl-hello-chk
      balance     roundrobin
          server master01 <IP_или_DNS_начального_мастер_узла>:6443 check
    
  • запустите haproxy:
# systemctl enable haproxy
# systemctl start haproxy

Настройка отказоустойчивого кластера серверов haproxy, keepalived

Особенности разворачивания приложений kubernetes

При использовании сервисов типа NodePort поднятые в рамках кластера порты в диапазоне 30000-32767 остаются в namespace пользователя u7s-admin. Для их проброса наружу необходимо в пользователе u7s-admin запустить команду:

$ nsenter_u7s rootlessctl add-ports 0.0.0.0:<port>:<port>/tcp

Сервисы типа NodePort из за их небольшого диапазона и "нестабильности" портов при переносе решения в другой кластер довольно редко используются. Рекомендуется вместо них использовать сервисы типа ClusterIP c доступом к ним через Ingress-контроллеры.

Установка и настройка ingress-контролера

Выбор регистратора образов

Пакет обеспечивает загрузку kubernet-образов с регистраторов различного уровня. Уровень регистратора определяется переменной среды U7S_REGISTRY. Переменная может принимать нижеописанные основные значения.

Native kubernetes регистратор

export U7S_REGISTRY=

Если переменная U7S_REGISTRY установлена в пустое значение образы загружаются со стандартного регистратора образов kubernetes.

Регистратор altlinux

С регистратора altlinux устанавливаются образы для которых не требуются ограничения политики доступа для различных категория пользователей:

  • export U7S_REGISTRY=registry.altlinux.org/k8s-c10f1 - образы для сертфицированного дистрибутива c10;
  • export U7S_REGISTRY=registry.altlinux.org/k8s-p10 - образы для несертфицированного дистрибутива p10.

podsec - Локальный регистратор

C локального регистраторе, как правило, устанавливается подписанные образы с ограничением политики доступа для различных категория пользователей, устанавливаемые скриптами пакета podsec. Это образы загружаются с регистратора registry.local пользователем группы podsec_dev, подписываются и загружаются в локальный регистратор registry.local. Подробности по установке rootless kubernetes в этом режиме описаны в документе Установка и настройка U7S (rootless kuber).

  • export U7S_REGISTRY=registry.local/k8s-c10f1 - образы для сертфицированного дистрибутива c10;
  • export U7S_REGISTRY=registry.local/k8s-p10 - образы для несертфицированного дистрибутива p10.

Настройка политики доступа к образам различным категориям пользователей

Поддержка электронной подписи образов

Автоматический выбор регистратора образов

Если переменная U7S_REGISTRY не установлена, ее значения вычисляется автоматически по следующему алгоритму:

  • Если файл /etc/hosts содержит описание хоста registry.local префикс переменной U7S_REGISTRY принимает значение registry.local/, иначе registry.altlinux.org/.
  • Если переменная CPE_NAME файла /etc/os-release содержит значение spserver суффикс переменной U7S_REGISTRY принимает значение k8s-c10f1, иначе k8s-p10.

podsec-k8s-rbac - Поддержка управление доступом на основе ролей (RBAC)

podsec-inotify - Мониторинг безопасности системы