cgroups V2, przyszłość już tu jest

Ten post został napisany ponad 2 lata temu, do wszystkich porad technologicznych w nim zawartych lepiej będzie podejść z dużą rezerwą, bo bardzo możliwe że tego rodzaju informacje są już nieaktualne.

Opublikowano: 08.12.2020

Ostatnia modyfikacja: 07.02.2024

kontenery

linux

podman

Jeżeli używasz Fedory 31 lub nowszej, to bardzo możliwe, że cgroups V2 są twoją codziennością. F31 to była pierwsza dystrybucja Linuksa, w której cgroups domyślnie są w wersji 2, a nie 1. O ile nic nie zmuszało cię do używania Dockera, to raczej nadal masz cgroups V2, ale jak ktoś jest ciekawy co to takiego, to nie zaszkodzi przeczytać.

Ribeye

Control groups, w skrócie cgroups, są ficzerem jądra Linuksa, który umożliwia kontrolę przydzielonych zasobów dla poszczególnych procesów - cykli procesora, ilości pamięci, przepustowości podsystemu we/wy. Wersja 1 w głównej linii jądra pojawiła się pod koniec roku 2007, a wydana została wraz jądrem 2.6.24 w styczniu 2008. Prace nad wersją 2 rozpoczęły się w roku 2013 (ładnie opisane powody przepisania tego systemu), a wydana została w roku 2014 wraz z wersją 3.16. Po 5 latach prac developerzy Fedory w wydaniu 31 ustawili cgroups V2 jako domyślne i od tamtej pory nic nie jest takie samo. Pierwszym symptomem, że coś jest inaczej było to, że nie uruchamiał się demon Dockera:

dockerd[10141]: Error starting daemon: Devices cgroup isn’t mounted

Od wydania F31 minął rok, Docker jeszcze nie obsługuje cgroups V2 (planowane jest to w wersji 20.10). Możliwe że zapowiadane wycofanie wsparcia dla Dockera w Kubernetes coś przyspieszy, ale koniec Dockera tak czy inaczej nadchodzi wielkimi krokami. Żartuję oczywiście.

V1 i V2, widzialne różnice

Różnic między V1 a V2 jest dużo, ale wiekszość z nich nie będzie widoczna dla programisty używającego kontenerów (tym mniej dla zwykłego power usera), ale dla porządku wspomnę co się zmienia:

Widać że system został znacząco uproszczony, ale to co będzie widoczne, to tylko mozliwość przydzielenia określonych zasobów procesowi uruchamianemu z konta zwykłego użytkownika (np w kontenerze rootless). Teoretycznie można to było zrobić i w V1, ale dla bezpieczeństwa najczęściej było to wyłączane na poziomie kompilacji jądra systemu, ponieważ mogło mieć katastrofalne skutki uboczne - łącznie z zawieszeniem systemu, dlatego w przypadku V1 było to ograniczone do procesów uruchamianych przez administratora. Jakkolwiek Podman miał tę możliwość (tak samo jak Docker), to jednak była ona ograniczona do uruchamiania kontenerów z uprawnieniami administracyjnymi - tak samo jak w Dockerze. Od strony zwykłego power usera będzie dawało to możliwość np uruchomienia aplikacji i określenia jej przydziału mocy obliczeniowej przy użyciu --cpus=2 --memory=2g, a przy tym kontener będzie uruchomiony z uprawnieniami zwykłego użytkownika. I będzie to dostępne nie tylko dla procesów uruchomionych w kontenerach, ale dla wszystkich procesów - da się powiedzieć np Chrome, że nie dostanie więcej niż 2 procesory i 2 GB RAM.

Będzie również możliwe użycie programu crun do uruchamiania kontenerów zamiast popularnego runc. Jako że jest napisany w C, można się spodziewać mniejszego obciążenia systemu hosta.

No i oczywiście nie będzie działał Docker. Ale czy naprawdę jest po czym płakać?

Aktualizacja dzień później: Docker 20.10 został wydany i znowu działa.

Jak włączyć cgroups V2

Użytkownicy Fedory 31 (lub nowszej) nie muszą robić nic. A reszta?

Najpierw warto sprawdzić zalecane wersje pakietów systemowych:

Wymagania te spełnia już Ubuntu 18.04.4 z jądrem HWE (5.3 z wydania 19.10, wymaga to sprawdzenia i ewentualnej aktualizacji). Od wydania 19.10 wszystkie pakiety systemowe w Ubuntu są w wymaganych wersjach.

Przełączenie na cgroups V2 dokonuje się przez podanie parametru uruchamiania jądra, który jest przekazywany do systemd. W Ubuntu robi się to przez dopisanie go w pliku /etc/default/grub i zaktualizowanie bootloadera poleceniem update-grub.

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=1"

Jeżeli mamy uruchomiony demon Dockera, to można go wyłączyć, żeby nie brudził w logach (bo i tak się nie uruchomi dopóki nie wyjdzie 20.10): sudo systemctl stop docker && sudo systemctl disable docker. W tym momencie pozostaje tylko sudo update-grub && sudo reboot. Po ponownym uruchomieniu będziemy już mieli cgroups V2.

$ podman info --debug
host:
  arch: amd64
  buildahVersion: 1.18.0
  cgroupManager: systemd
  cgroupVersion: v2
  conmon:
    package: 'conmon: /usr/libexec/podman/conmon'
    path: /usr/libexec/podman/conmon
    version: 'conmon version 2.0.20, commit: '
  cpus: 8
  distribution:
    distribution: ubuntu
    version: "20.04"
  eventLogger: journald

Żeby jako domyślny program uruchamiający kontenery użyć crun, to najlepiej jest skonfigurować to sobie na koncie użytkownika.

$ cp -v /etc/containers/containers.conf .config/containers/
'/etc/containers/containers.conf' -> '.config/containers/containers.conf'

W tymże pliku trzeba w sekcji “Default OCI runtime” odkomentować linijkę runtime i zmienić jej wartość na "crun", a następnie w tabeli engine.runtimes poniżej odkomentować listę ścieżek dla crun. I gotowe.

I to jest dopiero XXI wiek.