Ahoj,
v poslední zprávě jsem psal o plánovaném přechodu na cgroups v2. Pomalu
na tom pracujeme už od počátku roku 2022. Vyžaduje to úpravy jednak v
našem kernelu, to je stále v řešení, a taky integraci v user space:
nutnost delegace controllerů, rozdílný způsob konfigurace a čtení
parametrů, až nakonec propojení s vpsAdminem. Pro mě asi největší oříšek
zatím byl devices controller. Pro zajímavost popíšu k čemu to je a jak
to funguje.
devices controller je pro nás stěžejní komponenta, bez které nemůžeme
fungovat. Řídí totiž přístup ke všem zařízením -- blokové jako disky
/dev/sda, atd. a znakové jako /dev/tty, /dev/null, /dev/zero, apod.
Protože ve VPS můžete udělat mknod libovolného zařízení, devices cgroup
je nezbytná pro řízení přístupu.
Ve výchozím stavu umožnujeme přístup k /dev/{console, full, kmsg, null,
ptmx, random, urandom, tty*}. Podle VPS features pak i /dev/{net/tun,
kvm, ppp}. Pro nás je nejdůležitější neumožnit přístup k diskovým
zařízením, nad kterými běží ZFS.
devices controller u cgroups v1 je krásně jednoduchý. Povolené zařízení
vidíme v devices.list:
cat /sys/fs/cgroup/devices/devices.list
c 1:3 rwm
c 1:5 rwm
c 1:7 rwm
c 1:8 rwm
c 1:9 rwm
c 1:11 rwm
c 5:0 rwm
c 5:1 rwm
c 5:2 rwm
c 136:* rwm
b *:* m
c *:* m
Tedy read-write-mknod (rwm) k vybraným zařízením a mknod (m) pro všechno
ostatní. Na Linuxu v user namespace normálně mknod není možný, ale na
vpsAdminOS ano. Hodí se to třeba když rozbalujete nějaký archiv, který
obsahuje soubory zařízení.
Tohoto nastavení devices.list docílíme tak, že nejprve zakážeme přístup
ke všemu:
echo a > devices.deny
A potom povolíme vybrané zařízení:
echo c 1:3 rwm > devices.allow
echo c 1:5 rwm > devices.allow
[...]
Je to krásně jednoduché jednak na přehled a taky na konfiguraci. Jediný
zádrhel je zde v tom, že echo a > devices.deny funguje jen pokud daná
cgroup nemá potomky. Protože se s cgroups pracuje z různých míst, řešil
jsem to tak, že se devices cgroup nastavovala jako první při spuštění
systému nebo vytvoření VPS.
cgroups v2 dlouho devices controller neměly vůbec... a když přišel, byl
implementován přes BPF. Funguje to tak, že napíšete BPF program,
zkompilujete, nahrajete do kernelu a potom ho připojíte k dané cgroup.
Při přístupu k zařízení se daný BPF program vykoná a buď přístup umožní,
nebo zakáže.
Ukázkový program je součástí kernelu:
https://github.com/torvalds/linux/blob/v5.10/tools/testing/selftests/bpf/pr…
Můj největší problém byl, že jsem to ani za nic nebyl schopen
zkompilovat. Detaily už samozřejmě nevím, ale byl jsem z toho absolutně
zoufalý. Kompilovat programy tímto způsobem by sice nebylo ideální,
protože k tomu potřebujete LLVM, což nafukuje velikost rootfs... ale
aspoň by se tím dalo začít.
Když se podíváme na projekty jako systemd nebo LXC, tam s devices cgroup
pracují taky. Nekompilují programy přes LLVM, ale vytvoří program rovnou
z BPF instrukcí. Pěkně je to vidět v LXC:
https://github.com/lxc/lxc/blob/lxc-5.0.2/src/lxc/cgroups/cgroup2_devices.c…
Tahle cesta se mi líbila mnohem víc, ale taky jsem nikam nepokročil.
Použít přímo tuto funkci LXC nemůžeme, protože LXC spouštíme pod
neprivilegovaným uživatelem a devices cgroup může nastavovat jen root.
Ani vykopírovat ten kód není jednoduché, potřebuje to spousty vaty okolo
a zřejmě jsem na to neměl nervy :-) Zkoušel jsem použít i libbpf, taky
bezúspěšně.
Vzdal jsem to a vrátil se k tomu cca o rok později... situace byla úplně
stejná x) Našel jsem ale knihovnu v Golangu, pomocí které si můžu
poskládat program z instrukcí, nahrát ho do kernelu a dokonce připojit k
cgroup! Nejlepší je, že k tomu není potřeba mít LLVM, zdrojové soubory
kernelu, libbpf, nic. Stačí Golang.
https://github.com/cilium/ebpf
Další nutný článek je virtuální souborový systém bpffs. BPF program
totiž zůstane v kernelu jen po dobu, kdy běží proces, který ho tam
nahrál. My takový proces prakticky nemáme, všechno se může při
aktualizaci restartovat... to by znamenalo, že se najednou ztratí
všechny programy hlídající přístup k zařízením.
Pokud na daný BPF program ale uděláme referenci v bpffs, program zůstane
v kernelu i po ukončení procesu, který ho vytvořil. Program pak uvolníme
smazáním souboru (jeho reference) v bpffs. Podobně můžeme dělat
reference na připojení programu (attach/link) k cgroup.
Celý náš stack je v Ruby, takže jsem na nastavovaní devices cgroup
udělal oddělený program v Golangu -- vznikl devcgprog. Ten z Ruby voláme
s cestou k cgroup a seznamem zařízení, které mají být povolené.
devcgprog vytvoří BPF program, nahraje ho do kernelu, uloží do bpffs a
připojí k cgroup. Kdyby se to někomu náhodou taky hodilo, devcgprog
najdete na githubu:
https://github.com/vpsfreecz/devcgprog
Použití je jednoduché:
devcgprog set /sys/fs/bpf/my-program \
/sys/fs/cgroup/my-cgroup \
/sys/fs/bpf/my-program-on-my-cgroup \
allow \
c:1:3:rwm c:1:5:rwm [...]
Parametry jsou: vytvořená reference v bpffs, cesta k cgroup, reference k
linku na cgroup, typ seznamu (allow pro allowlist a deny pro denylist) a
seznam zařízení.
Jeden BPF program můžete nahrát jednou a použít u vícero cgroup, k tomu
slouží devcgprog new/attach. U nás je kombinace možných programů omezená
podle VPS features. Jako název programu používáme hash všech zařízení,
existují tak programy pro různé kombinace TUN/TAP, KVM a PPP. Pokud už
program s daným hash existuje, uděláme jen attach na další VPS cgroup.
Oproti cgroups v1 je to stále méně přehledné, BPF program je v porovnání
s devices.list neprůhledný. Může taky dojít k tomu, že cgroup se smaže a
vytvoří znovu se stejným názvem, link soubor v bpffs zůstane, ale přitom
program tam už připojen není. Existence reference v bpffs tedy ještě
neznamená, že je vše v pořádku. Pravidelně tak voláme bpftool a
kontrolujeme, zda jsou programy správně nastaveny. To je jen pro
jistotu, nastavované cgroupy má pod kontrolou pouze root na nodu, tedy
by tato situace neměla nastat.
Neříkám, že BPF není super, naopak na trasování, flamegraphy, apod. je
to paráda. Akorát někdy není úplně snadné to použít :-)
Jakub
Ahoj,
(English below)
# Otisky SSH klíčů
V detailu VPS ve vpsAdminu nově najdete otisky SSH host klíčů
(fingerprints). Při prvním přihlášení přes SSH tak můžete zkontrolovat
identitu serveru. Otisky klíčů se vyčítají ze souborů
/etc/ssh/ssh_host_*.pub ve VPS. Klíče se čtou po každém startu VPS a pak
jednou za hodinu.
# Úpravy VPS adminy vpsFree
Šablony distribucí, ze kterých se vytváří nové VPS, mohou mít nastavení
specifické pro naše prostředí. Může se stát, že bug nebo nová vlastnost
aplikací či našeho prostředí bude vyžadovat změnu konfigurace systému.
Týká se to prakticky jen základního systému, tj. nastavení, které jsou
součástí šablon. Ve vpsAdminu máte možnost si nastavit, jestli o takové
úpravy máte zájem. Ve výchozím stavu je to povoleno. Pokud bychom ve VPS
něco měnili, budeme o tom informovat emailem.
Pro představu, nedávno jsme z kernelu odstranili cglimit cgroupu -- náš
vlastní controller, který se ukázal jako zbytečný. Distribuce se systemd
si s tím poradily samy, ale třeba Alpine/Devuan/Void mají seznam cgroups
zapsaný v init skriptu, takže jsme jej v existujících VPS museli upravit.
# cgroups v2
Tento rok bychom rádi započali přechod na cgroups v2. cgroups v Linuxu
se používají na účtování a limitaci skupin procesů. V našem prostředí je
to jeden ze základních prostředků pro izolaci VPS, používáme to primárně
na nastavení limitu paměti a času CPU. Na cgroups samozřejmě staví
všechny kontejnerové řešení jako docker, apod.
V současné době používáme cgroups v1 v hybridní hierarchii a právě
protože VPS jsou kontejnery, verze cgroups je daná hostitelem. systemd v
roce 2024 nejspíše přestane cgroups v1 podporovat, takže na to chceme
být připraveni. Aktuální distribuce už v2 podporují, ty starší jako
CentOS 7 budeme nadále provozovat na nodech s v1.
Ve vpsAdminu lze u VPS nastavit, jakou verzi cgroups VPS vyžaduje. Ve
výchozím stavu se to řídí šablonou distribuce. Pokud mají aplikace ve
VPS speciální požadavky, můžete si vynutit cgroups v1 a zabránit tak
budoucí migraci na v2. Naším cílem bude přesunout všechno co jde na
cgroups v2. Více info a seznam distribucí podporujících cgroups v2
najdete v KB:
https://kb.vpsfree.cz/navody/vps/cgroups
Žádnou akci z vaší strany to nevyžaduje, o případném přesunu VPS na
cgroups v2 budeme informovat individuálně v následujících měsících.
ENGLISH:
# SSH host key fingerprints
You can now see SSH host key fingerprints in VPS details in vpsAdmin.
You can check that the fingerprints match on your first SSH login,
making sure that you're connecting to your server. Key fingerprints are
read from /etc/ssh/ssh_host_*.pub files found inside the VPS. The files
are read on every VPS start and then once an hour.
# VPS modifications by vpsFree admins
New VPS are created from distribution templates and those can have
settings specific for our environment. It can happen that a bug or a new
feature in applications or our platform will require or benefit from
configuration change. You can configure whether you wish to have your
VPS updated by vpsFree admins should the need arise in VPS details in
vpsAdmin. It is enabled by default. We modify only the base system
configuration files and we will notify you by email when any changes are
made.
For example, we have recently removed the cglimit cgroup controller from
our kernel. It was our own creation and we've discovered it was only a
source of bugs. VPS using systemd handled this removal without any
problem, but distributions such as Alpine/Devuan/Void have the list of
cgroup controllers hardcoded in their init script. We've thus updated
the init script to not emit warning about cglimit mount failure on boot.
# cgroups v2
This year, we would like to begin transition to cgroups v2. cgroups in
Linux are used to account and limit groups of processes. On vpsAdminOS,
it is a fundamental component used to create a VPS. We use it primarily
to limit memory and CPU usage. cgroups are of course used by all other
container systems, such as docker, etc.
At this time, we're using cgroups v1 in a hybrid layout. Since VPS are
containers, the cgroup version is determined by the host. As systemd
will possibly remove support for cgroups v1 in 2024, we'd like to be
ready. Current distributions already support cgroups v2, the older ones
like CentOS 7 will be kept on nodes with cgroups v1.
Our goal will be to move as many VPS as possible to cgroups v2 nodes. By
default, we look at the distribution used inside the VPS to see if it
supports cgroups v2. If you wish, you can configure your cgroups version
preference in VPS details in vpsAdmin and pin it to cgroups v1 to
prevent future migration. More information about cgroups v2 and a list
of supported distributions can be found in KB:
https://kb.vpsfree.org/manuals/vps/cgroups
No action from you is needed at this time. We'll keep you updated about
the upcoming migration in the months to follow.
Jakub
Ahoj,
na VPS mám pomalý login. Trvá to cca 30 sekund, než proběhne ověření a
dojde k přihlášení. Když si dám u ssh podrobnější výpis, zjistím, že to
visí mezi těmito dvěma hláškami:
debug1: pledge: filesystem
debug1: client_input_global_request: rtype hostkeys-00(a)openssh.com
want_reply 0
Doteď mi to nevadilo, protože se k serveru nepřipojuju tak často, aby
mně těch 30 sekund vadilo, ale teď zkouším rozjet Cockpit a ten mi na
tom timeoutuje.
Našel jsem, že se to děje lidem s LXC, tak jsem se chtěl zeptat, jestli
jste taky na to u VPSfree nenarazili a jestli neexistuje nějaké
nastavení ssh nebo pam, které by to vyřešilo.
Jirka