Read in English below.
LXCFS je souborový systém založený na FUSE (Filesystem in Userspace), který jsme od počátku vpsAdminOS používali k virtualizaci vybraných souborů v /proc
a /sys
ve VPS jakožto kontejnerech. Linux sice podporuje izolaci pomocí jmenných prostorů a limity přes cgroups, nicméně i tak by bez LXCFS ve VPS šlo vidět v top
-u všechny CPU nodu, free
by ukazoval využití paměti celého nodu, load average by byl vyšší než čekáte, atp. Postupem času jsme roli LXCFS zmenšovali a od kernelu 6.6.10
pro vpsAdminOS jsme ho kompletně odstranili, už není potřeba!
Náš kernel nyní obsahuje patche, které vybrané soubory v /proc
virtualizují na základě jmenných prostorů a limitů z cgroups. LXCFS muselo tyto hodnoty zjišťovat z userspace čtením parametrů ze /sys/fs/cgroup
a k počítání load average dokonce muselo procházet všechny procesy patřící VPS přes /proc
. Čtení těchto souborů zabírá sdílené zámky, což pak zdržuje ostatní přístupy.
LXCFS taktéž fungovalo jen tam, kde je připojeno. Pokud sami uvnitř VPS pouštíte kontejnery, museli jste LXCFS dovnitř buď ručně bind-mountovat, a nebo uvnitř těchto kontejnerů hodnoty v /proc
virtualizovány nebyly. Některé utility zjišťují stav systému pomocí systémového volání sysinfo a to pak LXCFS kompletně obešlo. sysinfo
používá např. Busybox, nebo i samotná glibc. Na Alpine Linuxu, kde je ve výchozím stavu Busybox, tak příkaz uptime
ukazoval load average celého nodu.
Na nodech se starším kernelem se můžeme podívat, jaké soubory LXCFS v poslední fázi provozu virtualizuje:
$ grep lxcfs /proc/mounts
lxcfs /proc/cpuinfo fuse.lxcfs rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other 0 0
lxcfs /proc/diskstats fuse.lxcfs rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other 0 0
lxcfs /proc/loadavg fuse.lxcfs rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other 0 0
lxcfs /proc/uptime fuse.lxcfs rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other 0 0
V minulosti zde bylo také /proc/stat
, /proc/meminfo
, /proc/swaps
a /sys/devices/system/cpu/online
. Virtualizaci využití CPU z pohledu VPS na základě CFS kvót jsme tehdy do LXCFS sami dodělávali.
Historicky jsme začínali s jednou instancí LXCFS pro všechny VPS v rámci jednoho nodu, to fungovalo v pohodě na nodech do 100 VPS. Když jsme přecházeli na nody se 300/600 VPS, jeden LXCFS proces už přestával stíhat. Krátce jsme spouštěli každému VPS vlastní instanci LXCFS, ale to se ukázalo jako velmi špatný nápad, neboť se pak 300/600 LXCFS procesů pralo o čtení z /proc
a cgroups parametrů. Nakonec jsme přešli na model LXCFS worker procesů, kdy jedna instance obsluhovala max 50 VPS a poté se dle potřeby spouštěly další instance:
[root@node24.prg.vpsfree.cz]
~ # osctl lxcfs worker ls
NAME ENABLED SIZE MAX_SIZE CPU_PACKAGE LOADAVG CFS
worker.0.cpu1 true 49 50 1 true true
worker.1.cpu1 true 50 50 1 true true
worker.2.cpu1 true 50 50 1 true true
worker.3.cpu1 true 50 50 1 true true
worker.4.cpu1 true 50 50 1 true true
worker.5.cpu1 true 48 50 1 true true
worker.6.cpu1 true 18 50 1 true true
worker.7.cpu0 true 50 50 0 true true
worker.8.cpu0 true 50 50 0 true true
worker.9.cpu0 true 50 50 0 true true
worker.10.cpu0 true 49 50 0 true true
worker.11.cpu0 true 50 50 0 true true
worker.12.cpu0 true 36 50 0 true true
node23/24.prg mají dva CPU sokety a tam ještě řešíme i to, aby VPS používalo LXCFS instanci na stejném soketu. Kanál na přenos dat mezi sokety má totiž omezenou propustnost, takže se snažíme VPS držet v rámci jednoho soketu.
Nyní tohle všechno odpadá a LXCFS jsme z vpsAdminOS kompletně odstranili. Z VPS tak vždy uvidíte virtualizované hodnoty. Pokud uvnitř VPS sami LXCFS používáte, nic se pro vás nemění a můžete jej nadále provozovat. Naše změny vás pouze abstrahují od toho, že VPS je taky jen kontejner.
English
I’d like to inform you about a significant change we’ve implemented in vpsAdminOS concerning LXCFS, a filesystem based on FUSE (Filesystem in Userspace) used for virtualizing selected files in /proc
and /sys
for VPS as containers. Linux supports isolation through namespaces and cgroups limits, but without LXCFS in a VPS, you’d see all physical CPUs in top
, free
would show the memory usage of the entire node, and the load average would be higher than expected. Over time, we’ve been reducing our reliance on LXCFS and, as of kernel version 6.6.10 for vpsAdminOS, we’ve completely removed it - it’s no longer needed!
Our kernel now includes patches that virtualize selected files in /proc
based on namespaces and cgroups limits. LXCFS had to calculate these values from userspace by reading parameters from /sys/fs/cgroup
, and to calculate load average, it even had to go through all processes belonging to a VPS via /proc
. Reading these files takes up shared locks, which then slow down other accesses.
LXCFS also only worked where it was actually mounted. If you run containers within a VPS, you had to either manually bind-mount LXCFS or the values in /proc
inside these containers were not virtualized. Some utilities determine the system status using the sysinfo system call, which completely bypassed LXCFS. sysinfo
is used, for example, by Busybox or even glibc. For instance, on Alpine Linux, which defaults to Busybox, the uptime
command showed the load average of the entire node.
On nodes with older kernels, we can see which files LXCFS are virtualized in its final form:
$ grep lxcfs /proc/mounts
lxcfs /proc/cpuinfo fuse.lxcfs rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other 0 0
lxcfs /proc/diskstats fuse.lxcfs rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other 0 0
lxcfs /proc/loadavg fuse.lxcfs rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other 0 0
lxcfs /proc/uptime fuse.lxcfs rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other 0 0
In the past, there were also /proc/stat
, /proc/meminfo
, /proc/swaps
, and /sys/devices/system/cpu/online
. We’ve contributed the initial implementation of CPU usage view based on CFS quotas to LXCFS.
We initially started with one LXCFS instance per node for all VPS, which worked fine for nodes with up to 100 VPS. As we moved to nodes with 300/600 VPS, a single LXCFS process began to struggle. We briefly ran an individual LXCFS instance for each VPS, but this proved to be a very bad idea, as then 300/600 LXCFS processes were competing for reading /proc
and cgroups parameters. Eventually, we switched to a model of LXCFS worker processes, where one worker served a maximum of 50 VPS, and additional workers were launched as needed:
[root@node24.prg.vpsfree.cz]
~ # osctl lxcfs worker ls
NAME ENABLED SIZE MAX_SIZE CPU_PACKAGE LOADAVG CFS
worker.0.cpu1 true 49 50 1 true true
worker.1.cpu1 true 50 50 1 true true
worker.2.cpu1 true 50 50 1 true true
worker.3.cpu1 true 50 50 1 true true
worker.4.cpu1 true 50 50 1 true true
worker.5.cpu1 true 48 50 1 true true
worker.6.cpu1 true 18 50 1 true true
worker.7.cpu0 true 50 50 0 true true
worker.8.cpu0 true 50 50 0 true true
worker.9.cpu0 true 50 50 0 true true
worker.10.cpu0 true 49 50 0 true true
worker.11.cpu0 true 50 50 0 true true
worker.12.cpu0 true 36 50 0 true true
Nodes like node23/24.prg have two CPU sockets and there we also ensured that VPS use LXCFS worker running on the same socket. The data transfer channel between sockets has limited bandwidth, so we try to keep VPS pinned to individual sockets.
Now, all of this is no longer necessary, and we’ve completely removed LXCFS from vpsAdminOS. From within a VPS, you will always see virtualized values. If you are using LXCFS inside the VPS yourself, nothing changes for you, and you can continue to operate it. Our changes only abstract away the fact that a VPS is also a container.