Zarządzanie pamięcią w systemie Linux: Swap, OOM Killer i Cgroups
12 min czytania - 31 maja 2026

Jak Linux swap, OOM killer i cgroups współpracują ze sobą - z przykładami konfiguracji dla baz danych, serwerów WWW i hostów VPS z wieloma dzierżawcami.
Wyjaśnienie zarządzania pamięcią w systemie Linux: swap, OOM killer i cgroups
System Linux obsługuje pamięć inaczej niż większość systemów operacyjnych. Wysokie zużycie pamięci RAM nie zawsze stanowi problem — jądro aktywnie wykorzystuje wolną pamięć do buforowania w celu przyspieszenia odczytu z dysku. Jednak gdy pojawia się rzeczywisty nacisk na pamięć, zadziałają trzy mechanizmy: swap, OOM killer i cgroups. Zrozumienie działania każdego z nich oraz sposobu ich konfiguracji stanowi różnicę między serwerem, który płynnie radzi sobie z obciążeniem, a serwerem, który ulega awarii bez ostrzeżenia.
Jak system Linux zarządza stronami pamięci
Każdy proces działa we własnej wirtualnej przestrzeni adresowej, która w systemach 64-bitowych może mieć rozmiar do 128 TB. Jądro mapuje te adresy wirtualne na fizyczną pamięć RAM za pomocą tabel stron, a bufor TLB (Translation Lookaside Buffer) buforuje ostatnie wyszukiwania. Trafienie w TLB zajmuje około 1 nanosekundy; brak trafienia kosztuje 20–100 nanosekund, co sumuje się w przypadku obciążeń intensywnie wykorzystujących pamięć, takich jak bazy danych.
Pamięć fizyczna jest podzielona na strony o wielkości 4 KB, a jądro dzieli je na dwie kategorie:
- Strony oparte na plikach — powiązane z plikami na dysku. Jądro może odrzucać czyste strony lub opróżniać brudne bez konieczności korzystania z pamięci wymiany.
- Strony anonimowe — pamięć sterty i stosu bez pliku podkładowego. Muszą one zostać zapisane w pamięci wymiany, zanim jądro będzie mogło je zwolnić.
Na serwerach o dużym zapotrzebowaniu na pamięć duża część stron anonimowych oznacza, że pamięć wymiany jest angażowana wcześnie. Obserwuj si (swap in) i so (swap out) w vmstat 1 — stałe wartości niezerowe to pierwszy sygnał ostrzegawczy, że system jest obciążony.
Do monitorowania użyj odpowiedniego narzędzia:
| Narzędzie | Najlepsze do | Kluczowy wskaźnik |
|---|---|---|
free -h | Szybki przegląd całego systemu | available kolumna |
vmstat 1 | Monitorowanie wymiany pamięci i operacji wejścia/wyjścia w czasie rzeczywistym | si, so |
htop | Interaktywny widok poszczególnych procesów | Paski pamięci, lista procesów |
smem | Dokładne wykorzystanie pamięci na proces | USS (rozmiar unikalnego zestawu) |
/proc/meminfo | Szczegóły na poziomie jądra | MemAvailable, Dirty, Slab |
Jeden z częstych błędów: obserwowanie free kolumny free -h i panikowanie. Liczy się kolumna available kolumna ma znaczenie. Obejmuje ona pamięć, którą jądro może odzyskać z pamięci podręcznej na żądanie. Serwer pokazujący tylko 512 MB wolnej pamięci, ale 5 GB dostępnej, nie ma problemów.
Gdy ilość pamięci spadnie poniżej progu, kswapd w tle. Jeśli to nie wystarczy, jądro przechodzi do trybu bezpośredniego odzyskiwania, blokując procesy do momentu zwolnienia stron. Stąd biorą się skoki opóźnień. Ustaw alert, gdy MemAvailable spadnie poniżej 10–15% całkowitej pamięci RAM, abyś miał czas na reakcję
Konfiguracja pamięci wymiany
Pamięć wymiany to obszar dysku — partycja lub plik — do którego jądro przenosi nieaktywne strony anonimowe, gdy pamięć RAM się zapełni. Różnica w szybkości jest znaczna: pamięć RAM DDR4 ma opóźnienie około 100 ns, podczas gdy dyski SSD NVMe mają opóźnienie około 100 000 ns, a dyski SSD SATA – blisko 500 000 ns. Pamięć wymiany jest buforem bezpieczeństwa, a nie dodatkową pamięcią RAM. Serwer, który stale polega na pamięci wymiany, ma problem z pamięcią, którego nie rozwiąże zwiększenie jej rozmiaru.
Używaj pliku swap zamiast partycji. Łatwiej jest zmienić jego rozmiar i nie wymaga to ponownego partycjonowania.
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfileDodaj plik do /etc/fstab , aby zachować go po ponownym uruchomieniu. chmod 600 krok jest wymagany — wszelkie dane wyładowane z pamięci RAM są czytelne z pliku swap, więc plik nie może być ogólnodostępny do odczytu.
Po utworzeniu pliku swap dostosuj vm.swappiness. Domyślna wartość 60 jest agresywna. W przypadku większości obciążeń hostingowych chcesz, aby jądro preferowało pamięć RAM i używało pliku wymiany tylko w ostateczności:
| Rola serwera | vm.swappiness | vm.vfs_cache_pressure |
|---|---|---|
| Ogólny serwer WWW | 10–20 | 50 |
| Baza danych (MySQL/PostgreSQL) | 1–5 | 50 |
| Domyślnie (większość dystrybucji) | 60 | 100 |
Jeśli chodzi o rozmiar partycji swap: 1–2 GB wystarczy dla VPS o pojemności 2 GB, obsługującego sporadyczne skoki ruchu. W systemach z 8 GB lub więcej pamięci RAM zazwyczaj wystarcza stała partycja swap o rozmiarze 2–4 GB. Celem jest zapewnienie jądru zaworu bezpieczeństwa dla stron zimnych, a nie rozszerzenie całkowitej pamięci adresowalnej.
Na serwerach z ograniczoną pamięcią RAM, ale z wystarczającą mocą procesora, zram tworzy skompresowany obszar wymiany w pamięci, całkowicie unikając operacji wejścia/wyjścia na dysku. Warto to rozważyć w przypadku hostów VPS z wieloma najemcami, gdzie NVMe jest współdzielone między najemcami. Należy uważać na konflikty wejścia/wyjścia, jeśli obszar wymiany znajduje się na tym samym urządzeniu co pliki bazy danych — intensywna wymiana i zapis na dysku o dużej przepustowości nie współistnieją dobrze.
OOM killer
Gdy jądro wyczerpie pamięć RAM i pamięć wymiany i nie może odzyskać wystarczającej ilości pamięci innymi sposobami, wkracza OOM killer. Ocenia on procesy za pomocą funkcji oom_badness() funkcji:
points = (rss_anon + rss_file + rss_shmem + swapents + pgtables_pages) + (oom_score_adj × totalpages / 1000)Proces z najwyższą oceną zostaje zabity. Formuła faworyzuje procesy zużywające dużo pamięci, a jądro unika zabijania wielu procesów w krótkich odstępach czasu, sprawdzając, czy dany proces nie został już zakończony w ciągu ostatnich 5 sekund.
W logach pojawiają się dwa rodzaje zdarzeń OOM:
- Globalny OOM — w całym systemie zabrakło pamięci RAM i przestrzeni wymiany. Logi mają prefiks
Out of memory: - Cgroup OOM — kontener lub usługa osiągnęły swój
memory.maxlimit. Logi mają prefiksMemory cgroup out of memory:
Aby przejrzeć poprzednie zdarzenia OOM:
dmesg -T | grep -i "out of memory"
journalctl -k --grep="oom"Zwróć uwagę na order w logach OOM. Wartość powyżej 0 sugeruje raczej fragmentację pamięci niż jej całkowite wyczerpanie — jądro nie mogło znaleźć wystarczającej liczby ciągłych stron, nawet przy dostępnej wolnej pamięci.
Możesz wpłynąć na to, które procesy są celem OOM killera, dostosowując /proc/<pid>/oom_score_adj. Zakres wynosi od -1000 (nigdy nie zabijaj) do +1000 (zabijaj jako pierwszy). W przypadku usług zarządzanych przez systemd ustaw to na stałe w pliku jednostki:
[Service]
OOMScoreAdjust=-1000Dodatkowe parametry sysctl do dostosowywania zachowania OOM:
| Parametr | Wartość | Efekt |
|---|---|---|
vm.overcommit_memory | 0 | Domyślny tryb heurystycznego nadmiernego przydzielania |
vm.overcommit_memory | 2 | Tryb ścisły; zapobiega alokacjom przekraczającym RAM × overcommit_ratio + swap |
vm.panic_on_oom | 1 | Restartuje zamiast zabijać proces |
vm.oom_kill_allocating_task | 1 | Zabija proces, który wywołał OOM, zamiast największego konsumenta |
W celu proaktywnego monitorowania sprawdź /proc/pressure/memory (Pressure Stall Information, dostępne od jądra 4.20). Obserwuj some avg10 wartość: poniżej 5% oznacza prawidłowy stan, utrzymywanie się powyżej 20% oznacza, że prawdopodobnie zbliża się zdarzenie OOM. Rosnący allocstall licznika w /proc/vmstat jest kolejnym wczesnym sygnałem — zlicza on bezpośrednie zatrzymania związane z odzyskiwaniem pamięci, które często poprzedzają zabijanie procesów z powodu OOM. Narzędzia takie jak systemd-oomd lub earlyoom mogą reagować na progi PSI, zanim uruchomi się mechanizm OOM killer jądra
Grupy C i limity pamięci
Grupy kontrolne (cgroups) pozwalają organizować procesy w grupy i egzekwować sztywne limity zasobów. Wprowadzone w systemie Linux 2.6.24, stanowią podstawę środowisk uruchomieniowych kontenerów, w tym Docker, Podman, Kubernetes i LXC. Jądro śledzi wykorzystanie pamięci dla każdej grupy cgroup, obejmując pamięć anonimową, strony oparte na plikach oraz obiekty jądra. Jeśli grupa cgroup osiągnie swój limit, jądro odzyskuje pamięć w ramach tej grupy lub uruchamia zabicie procesu w zakresie grupy cgroup z powodu braku pamięci (OOM).
Cgroup v1 i v2 różnią się przede wszystkim strukturą. W wersji v1 każdy kontroler (pamięć, procesor, wejście/wyjście) jest montowany oddzielnie pod /sys/fs/cgroup/<controller>/, co prowadzi do niespójnego śledzenia zasobów. Wersja v2 wykorzystuje ujednoliconą hierarchię w /sys/fs/cgroup/. Kubernetes przeszedł na wersję v2 jako domyślną w wersji 1.25 i zrezygnował ze wsparcia dla v1 w wersji 1.31.
Aby sprawdzić, której wersji używa Twój system:
stat -fc %T /sys/fs/cgroup/cgroup2fs oznacza v2; tmpfs zazwyczaj oznacza wersję v1.
| Funkcja | Cgroup v1 | Cgroup v2 |
|---|---|---|
| Hierarchia | Wiele, na kontroler | Pojedyncza, ujednolicona |
| Sztywny limit pamięci | memory.limit_in_bytes | memory.max |
| Miękki limit pamięci | memory.soft_limit_in_bytes | memory.high (ograniczenia przepustowości) |
| Śledzenie wykorzystania | memory.usage_in_bytes | memory.current |
| Wskaźniki ciśnienia | Ograniczone | PSI zintegrowane |
Kluczowe elementy sterujące pamięcią w cgroup v2:
| Parametr | Typ | Opis |
|---|---|---|
memory.max | Twardy limit | Przekroczenie tej wartości uruchamia mechanizm OOM killer |
memory.high | Ograniczenie miękkie | Ogranicza alokację i uruchamia odzyskiwanie pamięci przed osiągnięciem limitu twardego |
memory.low | Ochrona miękka | Pamięć poniżej tego progu jest odzyskiwana jako ostatnia |
memory.min | Ochrona twarda | Pamięć poniżej tego poziomu nigdy nie jest odzyskiwana |
memory.swap.max | Limit wymiany | Ustaw na 0, aby wyłączyć wymianę dla tej grupy cgroup |
memory.oom.group | Boolean | Jeśli opcja jest włączona, OOM zabija wszystkie procesy w cgroup jednocześnie |
Praktyczna zasada: ustaw memory.high około 10–20% poniżej memory.max , aby dać jądru miejsce na odzyskanie pamięci przed osiągnięciem twardego limitu. Przy określaniu rozmiaru memory.max, dodaj 20–30% powyżej szczytowego zużycia aplikacji, aby uwzględnić pamięć podręczną stron, która wlicza się do sumy pamięci cgroup.
Zarządzaj grupami cgroup za pośrednictwem systemd zamiast zapisywać bezpośrednio w systemie plików cgroup. Używaj dyrektyw plików jednostek, takich jak MemoryMax=, MemoryHigh=i MemoryMin= dla limitów trwałych. W przypadku szybkich testów:
systemd-run --scope -p MemoryMax=512M <command>W przypadku pul procesów roboczych serwera WWW ustawienie memory.oom.group=1 zapewnia czyste zakończenie działania, jeśli jeden proces roboczy przekroczy swój limit — nie pozostawiając żadnych osieroconych procesów. W przypadku silników baz danych memory.min chroni pulę buforów przed odzyskaniem w sytuacji obciążenia całego systemu.
Konfiguracja pamięci w zależności od roli serwera
Właściwe ustawienia pamięci zależą od tego, do czego służy serwer. Zastosowanie tej samej konfiguracji do bazy danych i serwera WWW PHP spowoduje uszkodzenie jednego z nich.
| Rola serwera | vm.swappiness | Strategia OOM | Polityka Cgroup |
|---|---|---|---|
| Baza danych | 1–5 | Ochrona (OOMScoreAdjust=-900) | Użyj memory.min w celu ochrony puli buforów |
| Serwer WWW/aplikacji | 10–20 | Domyślnie | Limit na pulę pracowników poprzez memory.max |
| Pracownik w tle | 60 | Możliwość zabicia (OOMScoreAdjust=+200) | Ograniczanie przepustowości za pomocą memory.high |
| Wielodostępny serwer VPS | 60 (z zram) | Domyślnie | Twarda izolacja na dzierżawcę poprzez memory.max |
W przypadku MySQL i PostgreSQL przydziel 50–70% dostępnej pamięci RAM innodb_buffer_pool_size, wyłącz Transparent Huge Pages, aby zmniejszyć skoki opóźnień, i zabezpiecz proces za pomocą OOMScoreAdjust=-900 w pliku jednostki systemd.
W przypadku PHP-FPM należy dostosować wielkość pul pracowników do rzeczywistego zużycia pamięci. Każdy pracownik zużywa zazwyczaj 30–100 MB. Należy podzielić przydzieloną pamięć RAM przez średnią wielkość pracownika, aby uzyskać bezpieczną pm.max_children wartość. Użyj memory.max w cgroups, aby ograniczyć pulę.
W przypadku obciążeń wymagających intensywnego zapisu ustaw vm.dirty_ratio na około 10%, a vm.dirty_background_ratio na 3%. Spowoduje to częstsze opróżnianie brudnych stron, co pozwoli uniknąć długich przestojów operacji wejścia/wyjścia
Zapewnij trwałość dostrojenia jądra, zapisując parametry w /etc/sysctl.d/90-memory.conf. Ustawienia zastosowane w czasie działania systemu zostaną utracone po ponownym uruchomieniu.
Podsumowanie zalecanych wartości według roli:
| Parametr | Serwer WWW/aplikacji | Serwer bazy danych |
|---|---|---|
vm.swappiness | 10–20 | 1–5 |
vm.vfs_cache_pressure | 50 | 50 |
vm.dirty_ratio | 15 | 10% |
vm.min_free_kbytes | 65536 | 65536 |
| Ochrona przed wyczerpaniem pamięci | Domyślnie | OOMScoreAdjust=-1000 |
Jeśli obsługujesz obciążenia o dużej gęstości i potrzebujesz serwera z wystarczającą rezerwą mocy, aby prawidłowo stosować te zasady, warto przyjrzeć się serwerom dedykowanym FDC.

Zarządzanie pamięcią w systemie Linux: Swap, OOM Killer i Cgroups
Jak Linux swap, OOM killer i cgroups współpracują ze sobą - z przykładami konfiguracji dla baz danych, serwerów WWW i hostów VPS z wieloma dzierżawcami.
12 min czytania - 31 maja 2026
Przewodnik konfiguracji Prometheus i node_exporter
15 min czytania - 29 maja 2026

Masz pytania lub potrzebujesz niestandardowego rozwiązania?
Elastyczne opcje
Globalny zasięg
Natychmiastowe wdrożenie
Elastyczne opcje
Globalny zasięg
Natychmiastowe wdrożenie