Aleksander Roszig
8 sierpnia 2026 | 6 min czytaniaKubernetes HPA: Horizontal Pod Autoscaler dla CPU i pamięci
Spis treści
Autoskalowanie to jeden z głównych powodów, dla których firmy przechodzą na Kubernetesa lub w ogóle chcą korzystać z chmury. Mimo to w wielu klastrach, które audytujemy, Horizontal Pod Autoscaler albo w ogóle nie jest używany, albo jest skonfigurowany w sposób, który aktywnie szkodzi aplikacji. Liczba replik jest ustalana raz, na sztywno wpisana w manifest, a klaster płaci za szczytową pojemność 24/7. To dokładne przeciwieństwo tego, jak powinno wyglądać środowisko cloud native.
W tym artykule chciałbym wyjaśnić, jak działa Kubernetes Horizontal Pod Autoscaler oraz pokazać działające przykłady skalowania na CPU, na pamięci i na obu metrykach jednocześnie. HPA działa bezpośrednio na resource requests, więc jeśli nie wiesz, jak działają requesty w Kubernetesie, polecam przeczytać wcześniejsze części o CPU request i limit oraz memory request i limit.
Czym jest HPA w Kubernetesie?
HPA (Horizontal Pod Autoscaler) to wbudowany kontroler Kubernetesa, który dostosowuje liczbę replik podów do obserwowanego obciążenia CPU lub pamięci.
- Horyzontalnie oznacza więcej lub mniej podów z tą samą ilością zasobów. HPA nigdy nie zmienia CPU ani pamięci przypisanej do pojedynczego poda. Zmiana zasóbów bez zmiany liczby replik to skalowanie wertykalne, obsługiwane przez VPA (Vertical Pod Autoscaler).
- HPA to obiekt API (
autoscaling/v2) plus pętla kontrolna działająca wewnątrz kube-controller-manager, która śledzi ten obiekt. Deklarujesz stan docelowy, a kontroler reguluje stan systemu.
Jak działa Horizontal Pod Autoscaler
Kontroler domyślnie sprawdza co 15 sekund (--horizontal-pod-autoscaler-sync-period) dla każdego obiektu HPA:
- pobiera bieżącą wartość każdej skonfigurowanej metryki,
- oblicza pożądaną liczbę replik,
- aktualizuje pole
replicasw zasobie docelowym, jeśli to konieczne.
Sercem mechanizmu jest jeden wzór:
desiredReplicas = ceil( currentReplicas × currentMetricValue / desiredMetricValue )
Pytanie brzmi: jeśli liniowo przeskalujemy liczbę replik, żeby sprowadzić średnie wykorzystanie do wartości docelowej, ile podów potrzebujemy? ceil zaokrągla w górę, bo liczba replik nie może być ułamkowa.
Zanim kontroler zadziała zgodnie ze wzorem, sprawdza stosunek currentUtilization / targetUtilization. Jeśli ten stosunek mieści się w przedziale 0,9-1,1 (czyli w granicach 10% od wartości docelowej), HPA nic nie robi — niezależnie od tego, co sugerowałby wzór. Ma to zapobiegać ciągłemu, nerwowemu przeskalowywaniu, gdy wykorzystanie jest już blisko wartości docelowej.
Załóżmy 3 repliki, docelowe wykorzystanie CPU 70%, bieżące średnie wykorzystanie 90%:
desiredReplicas = ceil(3 × 90% / 70%) = ceil(3,86) = 4
| currentReplicas | bieżące wykorzystanie | cel | stosunek | ceil | desiredReplicas |
|---|---|---|---|---|---|
| 3 | 90% | 70% | 1,28 | 3,86 | 4 (skalowanie w górę) |
| 4 | 35% | 70% | 0,5 | 2,00 | 2 (skalowanie w dół) |
| 2 | 53% | 70% | 0,75 | 1,51 | 2 (bez zmian) |
| 2 | 73% | 70% | 1,04 | 2,08 | 2 (bez zmian) |
Ostatni wiersz pokazuje istotny szczegół: kontroler ma domyślnie tolerancję 0,1 (10%). Jeśli stosunek wartości bieżącej do docelowej mieści się w przedziale 0,9-1,1, nic się nie dzieje. Zapobiega to ciągłemu skalowaniu przy niewielkich wahaniach. Dlatego nie mamy tej aplikacji przeskalowanej do 3 podów, nawet jeśli wynik ceil jest odrobinę powyżej 2.
Nawet gdy desiredReplicas różni się od bieżącej wartości, skalowanie w dół nie nastąpi natychmiast: okno stabilizacji (domyślnie 300 sekund) sprawia, że kontroler wybiera najwyższą rekomendację z ostatniego okresu. Skalowanie w górę ma domyślnie okno stabilizacji równe 0, więc uruchamia się natychmiast po przekroczeniu progu przez metrykę (przy kolejnej synchronizacji, co ~15 sekund).
Wykorzystanie zawsze jest obliczane względem requestu kontenera, a nie limitu. Cel averageUtilization: 70 dla CPU oznacza 70% requestu CPU. Dlatego HPA na metrykach zasobowych po prostu nie działa bez requestów — kontroler zgłasza <unknown> oraz zdarzenie FailedGetResourceMetric.
Metryki Kubernetes HPA: Resource, Pods, Object, External
HPA może korzystać z czterech typów metryk:
- Resource - CPU i pamięć kontenerów, dostarczane przez metrics-server poprzez API
metrics.k8s.io.
Metryki niestandardowe przy użyciu API custom.metrics.k8s.io, na przykład z Prometheus adapterem:
- Pods - niestandardowe metryki na poda (np. liczba requestów na sekundę), uśredniane po Podach.
- Object - metryka opisująca inny obiekt Kubernetesa, na przykład liczba requestów na sekundę na Ingressie.
Metryki spoza klastra poprzez external.metrics.k8s.io:
- External - metryki spoza klastra, na przykład długość kolejki SQS.
Niestandardowe metryki Kubernetes HPA
CPU to proxy dla obciążenia, a nie samo obciążenie. Dla wielu systemów uczciwym sygnałem do skalowania są requesty na sekundę, długość kolejki albo opóźnienie konsumenta (consumer lag). HPA wspiera to poprzez API custom.metrics.k8s.io i external.metrics.k8s.io, zwykle udostępniane przez jedno z poniższych rozwiązań:
- Prometheus Adapter - udostępnia dowolne zapytanie Prometheusa jako metrykę HPA,
- KEDA - operator przeznaczony do autoskalowania z gotowymi scalerami dla Kafki, SQS, RabbitMQ, CloudWatch i dziesiątek innych źródeł. Pod spodem KEDA nadal tworzy obiekt HPA, więc wszystko z tego artykułu ma tu zastosowanie.
Jeśli zauważasz, że dostrajasz cele CPU, żeby pośrednio przybliżyć “requesty na poda”, to znak, że pora przejść na metrykę niestandardową.
HPA vs VPA w Kubernetesie
Oba autoskalery odpowiadają na różne pytania:
| HPA | VPA | |
|---|---|---|
| co się zmienia | liczba replik | requesty CPU/pamięci poda |
| kierunek | horyzontalny | wertykalny |
| dobre dla | usług bezstanowych, obciążeniowych | właściwego doboru requestów, batch jobów, baz danych |
Nie uruchamiaj HPA i VPA na tej samej metryce. VPA zmienia requesty, których HPA używa jako mianownika przy obliczaniu wykorzystania — oba kontrolery zaczynają się “gonić”, a liczba replik staje się nieprzewidywalna. Bezpieczne wzorce: VPA w trybie updateMode: Off jako silnik rekomendacji do ręcznego ustawiania requestów albo VPA zarządzające requestami przy jednoczesnym skalowaniu HPA na metrykach niestandardowych/zewnętrznych.
Najlepsze praktyki Kubernetes HPA
- Zawsze ustawiaj request CPU i memory Bez nich HPA nie może działać. To, jak requesty przekładają się na rzeczywisty czas CPU, opisujemy w CPU request i limit w praktyce.
- Zostaw zapas w wartości docelowej. Cel CPU na poziomie 70% oznacza, że pody regularnie działają powyżej tej wartości między okresami synchronizacji. Jeśli ustawisz zbyt niskie limity CPU to może to spowodować throttling CPU.
- Ustaw realistyczne minReplicas i maxReplicas.
minReplicas: 1na produkcyjnym API oznacza pojedynczego poda, który redukuje koszty, gdy nikt nie korzysta z aplikacji.maxReplicaspowinno mieścić się w rzeczywistej pojemności klastra — HPA skaluje pody, nie node’y. Żeby klaster miał wystarczająco miejsca, skorzystaj z Cluster Autoscalera lub Karpentera. - Usuń pole
replicasz manifestów zarządzanych przez HPA. W konfiguracji GitOps to klasyczny konflikt: Argo CD w kółko resetuje repliki do wartości z Gita. Usuń to pole lub skonfigurujignoreDifferencesw definicji aplikacji ArgoCD, żeby tylko HPA nim zarządzało. - Weryfikuj zdarzenia skalowania za pomocą:
kubectl describe hpa <nazwa>pokazuje decyzje kontrolera i każdy powód, dla którego nie mógł skalować.
Podsumowanie
HPA to jeden z tych mechanizmów Kubernetesa, które w demo wyglądają trywialnie, a w produkcji dopasowanie wszystkich parametrów okazują się bardziej skomplikowane. Wzór to jedna linijka, ale to, czy zadziała u Ciebie, zależy od danych wejściowych: poprawnych requestów, metryki faktycznie odzwierciedlającej obciążenie, sensownych celów i dopasowania tego do wzorca Twojego ruchu. Jeśli chcesz zweryfikować swoją konfigurację autoskalowania, właściwie dobrać requesty i limity albo zaprojektować pełną ścieżkę od HPA przez Cluster Autoscaler aż po kontrolę kosztów, nasz zespół oferuje konsulting Kubernetes oparty na danych i metrykach.


