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.

Jak hostować modele Ollama AI na serwerach dedykowanych
Dowiedz się, jak hostować modele Ollama AI na serwerach dedykowanych, aby zapewnić bezpieczeństwo danych, skalowalność i zwiększyć wydajność.
5 min czytania - 8 września 2025
Jak zainstalować i korzystać z Redis na serwerze VPS
9 min czytania - 7 stycznia 2026

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