Table of Contents

Задача

Для экспериментов мне требуется периодически поднимать кластер 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 нормально стартовал с такими параметрами контейнера:

mp0: /boot,mp=/boot
mp1: /lib/modules,mp=/lib/modules
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

Выхода три:

Proxmox br_netfilter module absent

Недавно, после апгрейда ОС в контейнере - Ubuntu 20.04 → Ubuntu 21.04 перестали стартовать контейнеры kubelet и все выглядит так, словно отсутствует модуль br_filter. https://forum.proxmox.com/threads/missing-br_netfilter-module.53791/ Это прям шоустоппер!!
Оказалось, что не стоит обновлять систему раньше времени и обязательно перед такими манипуляциями делать бекапы!!! :).
В итоге - я просто создал новый контейнер, натянул на него чистый кластер k8s, а затем скопировал с ноды старого кластера директории:

/etc/kubernetes
/etc/var/lib/etcd
/etc/var/lib/kubelet

В общем-то всё… Кластер реанимировался.

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

Ошибки

Failed to start cAdvisor inotify_init: too many open files

Нужно увеличить 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).

Ссылки

https://medium.com/@kvaps/run-kubernetes-in-lxc-container-f04aa94b6c9c (вот тоже самое на русском языке )
https://forum.proxmox.com/threads/docker-in-lxc-container.45204/