Задача

Для экспериментов мне требуется периодически поднимать кластер kubernetes (на момент написания - версия 1.16.0).
Я не хочу использовать виртуальные машины, а хочу использовать контейнеры. В первую очередь из-за некоторых аппаратных ограничений (мой хост довольно слабый - Pentium J5005 и 24Gb памяти DDR4).
В качестве инструмента развертывания я использую ansible.

Настройки хоста Proxmox 5.x/6

Вот тут есть описание профиля контейнера, с которыми все должно работать. Но я пока это не применял. https://discuss.linuxcontainers.org/t/not-able-to-run-kubernetes-inside-docker-inside-lxd/4643/3

В /etc/modules добавляем:

overlay
aufs

и чтобы не переазгружаться выполняем:

/sbin/lsmod | /bin/grep overlay || /sbin/modprobe overlay
/sbin/lsmod | /bin/grep aufs || /sbin/modprobe aufs

Параметры контейнеров

Запустить master-node в unprivileged контейнере пока не удалось, потому что нужен доступ к настройкам (в частности ядра memory overcommit). То есть при создании контейнера мнимаем галку unprivileged.
Объем swap - 0.

Параметры контейнера в Proxmox 5.x

К стандартным настройкам добавляем:

lxc.apparmor.profile: unconfined
lxc.cap.drop:
lxc.cgroup.devices.allow: a
lxc.mount.auto: proc:rw sys:rw

Параметры контейнера в Proxmox 6

К стандартным настройкам контейнера добавляем:

mp0: /boot,mp=/boot
mp1: /lib/modules,mp=/lib/modules
lxc.hook.autodev: sh -c "mknod -m 0644 ${LXC_ROOTFS_MOUNT}/dev/kmsg c 1 11"
lxc.apparmor.profile: unconfined
lxc.cap.drop:
lxc.cgroup.devices.allow: a
lxc.mount.auto: proc:rw sys:rw

Параметры контейнера в Proxmox 7

После апгрейда до Proxmox 7 в системе cgroups обновился до версии cgroups2. В итоге kubelet нормально стартовал с такими параметрами контейнера:

lxc.apparmor.profile: unconfined
lxc.cap.drop:
lxc.cgroup2.devices.allow: a
lxc.mount.auto: proc:rw sys:rw
lxc.mount.entry: /dev/kmsg dev/kmsg none defaults,bind,create=file

Также в версии Proxmox 7 используется ядро 5.11 и более новое. В нем запрещено изменения параметров net_filter (https://github.com/kubernetes-sigs/kind/issues/2240#issuecomment-838938881). В результате не стартует kube-proxy:

server.go:650] Version: v1.20.1
conntrack.go:100] Set sysctl 'net/netfilter/nf_conntrack_max' to 131072
server.go:495] open /proc/sys/net/netfilter/nf_conntrack_max: permission denied

Выхода три:

  • либо откатиться на pve-kernel-5.10.6-1-pve
  • обновить kube-proxy (в мае 2021 в него смерджили патч, который позволяет не изменять значения, которые уже достаточно хороши для работы kube-proxy - https://github.com/kubernetes-sigs/kind/pull/2241)
  • в конфиге kube-proxy дать параметру conntrack-max-per-core значение 0 - тогда kube-proxy будет использовать то значение, которое установлено сейчас. Для этого нужно найти и отредактировать значение в ConfigMap:
    kubectl edit cm -n kube-system kube-proxy

Также - серьезная проблема - отсутствует модуль br_filter. https://forum.proxmox.com/threads/missing-br_netfilter-module.53791/ Это прям шоустоппер!!
В качестве воркараунда можно поработать с дефолтным ядром Debian.
Устанавливаем его:

sudo apt-get install linux-image-amd64 linux-headers-amd64

Затем надо сделать это ядро дефолтным в конфиге Grub.
Это ядро в меню Grub попало в подменю Advanced…
Чтобы сделать его дефолтным надо получить menuentry_id_option для подменю, потом получить menuentry_id_option для данного пункта, потом объединить эти две строки с помощью > и прописать полученную строку в качестве значения GRUB_DEFAULT в файлике /etc/defaults/grub и обновить конфиг grub.
Для подменю строку menuentry_id_option смотрим тут:

cat /boot/grub/grub.cfg | grep submenu

Для только что установленного не-PVE-ядра строку menuentry_id_option смотрим тут:

VER=`dpkg -l | grep linux-image | grep -v meta | awk {'print $2'} | cut -d'-' -f3,4`
cat /boot/grub/grub.cfg | grep $VER

Дальше редактируем файлик /etc/default/grub, комментируем там текущий GRUB_DEFAULT и прописываем нужный (две стройки menuentry_id_option, соединенные >):

#GRUB_DEFAULT=0
GRUB_DEFAULT="gnulinux-advanced-f8b1e0cb-f813-4cce-a713-049ae5bcc098>gnulinux-5.10.0-8-amd64-advanced-f8b1e0cb-f813-4cce-a713-049ae5bcc098"

И дальше выполняем:

sudo update-grub

Также прописываем автозагрузку br_netfilter:

echo br_netfilter | sudo tee -a /etc/modules

Если на хосте используется ZFS, то надо установить пакет zfs-dkms:

sudo apt-get install zfs-dkms

Также, со стандартным ядром не работает AppArmor, поэтому чтобы контейнеры запускались в конфиге контейнера должно быть:

lxc.apparmor.profile: unconfined

Kubernetes CNI

В качетсве CNI можно использовать либо flannel:

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

либо kube-router:

kubectl apply -f https://raw.githubusercontent.com/cloudnativelabs/kube-router/master/daemonset/kubeadm-kuberouter.yaml

Kubernetes Dashboard Web UI

https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#welcome-view
Установка Kubernetes Dashboard Web UI:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/aio/deploy/recommended/kubernetes-dashboard.yaml

Если мы админим кластер с машины, где есть kubectl и браузер, то для того, чтобы локально пользоваться Kubernetes Dashboard Web UI достаточно запустить:

kubectl proxy &

и консоль будет доступна по адресу: http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/.
Если необходимо иметь доступ консоли не только с локального хоста, на котором исполняется kubectl proxy, то запускаем его так:

kubectl proxy --address='0.0.0.0' --accept-hosts='^*$'

В результате, консоль будет доступна и с других хостов.
Кроме того, для доступа к консоли Kubernetes Dashboard Web UI без kubectl proxy нужно сменить тип service'а который предоставляет доступ к pod'у kubernetes-dashboard. Вместо установленного по-умолчанию ClusterIP нужно сделать NodePort:

kubectl -n kube-system patch service kubernetes-dashboard  -p '{"spec":{"type":"NodePort"}}'

В результате, dashboard будет доступен на IP-адресе master-ноды.
Это можно сделать и вручную, отредактировав service, который предоставляет доступ к pod'у kubernetes-dashboard, где в качестве .spec.type указать NodePort:

kubectl -n kube-system edit service kubernetes-dashboard

Ошибки

Нужно увеличить inotify/max_user_instances
Текущее значение можно посмотреть так:

cat /proc/sys/fs/inotify/max_user_instances

Для увеличения лимита добавляем строку

fs.inotify.max_user_instances=999999

В файл /etc/sysctl.conf и применяем:

sysctl --system

Или вот одной строкой:

echo fs.inotify.max_user_instances=99999 | sudo tee -a /etc/sysctl.conf && sudo sysctl --system

При попытке запустить kubelet в контейнере, файловая система которого лежит просто в директории хоста, вываливается ошибка:

Failed to start ContainerManager failed to get rootfs info: failed to get device for dir "/var/lib/kubelet": could not find device with major: 0, minor: 49 in cached partitions map

Так делать нельзя. Файловая система контейнера должна лежать в каком-то контейнере, который будет смонтирован как loop-устройство(например по-умолчанию - в qcow2).

Ссылки

Enter your comment. Wiki syntax is allowed:
X I Q​ D E
 
  • proxmox/how_to_start_kubernetes_inside_proxmox_lxc_container.txt
  • Last modified: 2021/09/14 10:38
  • by admin