Zacznijmy od twardych danych: aż 73% incydentów w środowiskach kontenerowych wynika bezpośrednio z luk w łańcuchu dostaw oraz błędnych konfiguracji klastra. Co ciekawe, ponad połowę tych zagrożeń da się zablokować jeszcze zanim kod w ogóle trafi na produkcję – już na etapie budowania obrazu. Ten przewodnik przeprowadzi Cię przez kompletną ścieżkę bezpieczeństwa: od podpisywania obrazów i generowania SBOM, przez rygorystyczne egzekwowanie polityk w samym Kubernetesie, aż po monitoring w czasie rzeczywistym.

Bezpieczny łańcuch dostaw: zasada „trust but verify”

Jeśli chcesz mieć pewność, że do Twojego klastra nie trafi nic podejrzanego, musisz uszczelnić cały proces dostarczania oprogramowania. Kluczem jest zabezpieczenie pipeline’u: od skanowania zależności, przez izolowane środowiska budowania, aż po weryfikację podpisów i SBOM (Software Bill of Materials) na etapie wpuszczania do klastra.

Oto krótka checklista, która pozwoli Ci utrzymać porządek w tym obszarze:

  • Wydzielone konta dla CI: Stosuj oddzielne konta i klucze o ograniczonym zakresie (scoped), pamiętaj o ich rotacji i nadawaj tylko minimalne uprawnienia.
  • Ulotne środowiska buildów: Korzystaj z tzw. ephemeral runners i hermetyzuj procesy budowania, aby po zakończeniu zadania nie pozostawał żaden stan.
  • Przypinanie wersji: Stosuj konkretne, „przypięte” wersje akcji i pluginów, a także weryfikuj ich sumy kontrolne (checksums).
  • Generowanie SBOM: Twórz spis komponentów oprogramowania (SBOM) już na etapie builda (np. narzędziem Syft) i dołączaj go do obrazu.
  • Skanowanie obrazów: Używaj skanerów takich jak Trivy czy Grype i ustaw twardy próg – błąd builda w przypadku wykrycia podatności o wysokim stopniu ryzyka (High/Critical).
  • Podpisy i attestacje: Podpisuj obrazy (np. narzędziem cosign), przechowuj klucze w bezpiecznym KMS, a logi podpisów rejestruj w Sigstore Rekor.
  • Polityki admission: Wykorzystaj Kyverno (reguła verifyImages) do egzekwowania obecności prawidłowych podpisów i SBOM przed wpuszczeniem obrazu do klastra.
  • Higiena rejestru: Stosuj rejestr z mirrorami, włączonym skanowaniem i politykami retencji, aby automatycznie usuwać stare obrazy.
  • Monitoring dryfu: Śledź zmiany wersji i reaguj na nie automatycznymi Pull Requestami, wykorzystując narzędzia takie jak Dependabot czy OSV.

Minimalny, nieinwazyjny proces SBOM wygląda następująco: generujesz SBOM (Syft), dołączasz go jako artefakt, skanujesz (Grype/Trivy), blokujesz publikację przy krytycznych błędach, a na koniec podpisujesz obraz i attestacje cosign, rejestrując ślad w Rekor. W samym klastrze wymuszasz regułę Kyverno verifyImages – bez ważnego podpisu i SBOM wdrożenie po prostu się nie uda. Eksperci radzą też, aby trzymać się hermetycznych buildów i niezmiennych tagów (bazujących na SHA), a w rejestrze włączyć skanowanie przy każdym pushu oraz retencję, by „zgnite” obrazy same znikały z obiegu.

Pamiętaj o „zakazach bez dyskusji”: nigdy nie używaj tagu latest, nie zapominaj o SBOM, nie pobieraj obrazów z publicznych rejestrów bez mirrorów i kontroli. Unikaj braku przypiętych wersji, wspólnych sekretów dla CI oraz braku sum kontrolnych dla artefaktów. Zdefiniuj polityki bezpieczeństwa jako kod (OPA/Kyverno), loguj każde potwierdzenie w Rekor i egzekwuj te zasady na wejściu do klastra. Wtedy bezpieczeństwo przestaje być tylko życzeniem, a staje się twardą bramką.

Hardening obrazów i kontenerów

Minimalizacja powierzchni ataku to nie fanaberia, lecz czysty zysk. Obrazy typu distroless czy UBI-micro są pozbawione zbędnych warstw, co oznacza mniej podatności CVE i mniej potencjalnych wektorów ataku. Pozbądź się powłoki shell, kompilatorów i narzędzi debugujących. Jeśli to możliwe, buduj aplikacje statycznie i pakuj do obrazu bez biblioteki libc.

Przestań ufać zwykłym tagom. Zamiast image:tag używaj digestów (sha256) i wprowadź politykę „no latest”. Unikalny skrót obrazu sprawdzisz komendą docker inspect, a w admission controller (np. OPA Gatekeeper czy Kyverno) możesz wymusić uruchamianie kontenerów wyłącznie po konkretnym hashu.

Pamiętaj: w kontenerze nie ma miejsca dla administratorów. Uruchamiaj aplikacje jako użytkownik niebędący rootem, ustaw system plików jako tylko do odczytu (readOnlyRootFilesystem), a katalogi do zapisu montuj jawnie. Katalog /tmp powinien być montowany jako niemodyfikowalny tmpfs. Bezwzględnie unikaj flagi setuid.

Uprawnienia tnij do kości: najpierw odejmij wszystkie (drop ALL capabilities), a potem dodaj tylko te absolutnie niezbędne (np. NET_BIND_SERVICE dla niskich portów). Najczęściej usuwane uprawnienia to NET_RAW, SYS_ADMIN, SYS_PTRACE i MKNOD. Zastosuj profil seccomp (domyślny dockerowy lub przycięty) oraz AppArmor lub SELinux w trybie wymuszania (enforce), a nie tylko permissive.

Aby uniknąć ataków DoS, pilnuj limitów zasobów (limits/requests), ustaw sensowny OOMScoreAdj i przemyśl politykę restartów. Prosty wzorzec YAML, który działa, to: runAsNonRoot: true, readOnlyRootFilesystem: true oraz capabilities: drop: [ALL]. Na koniec zrób „smoke test”: spróbuj uruchomić sh lub ping z wnętrza kontenera – jeśli się uda, cofnij się i dotnij profil bardziej.

W praktyce najlepiej budować obrazy produkcyjne wieloetapowo (multi-stage build), skanować je w CI, podpisywać i weryfikować przy wdrożeniu. W Kubernetesie włącz Pod Security Admission (PSA) w trybie restricted, dodaj zasady Gatekeepera/Kyverno (tylko digest, bez roota, read-only FS), a profile seccomp i AppArmor ustaw jako wymagane. W runtime monitoruj naruszenia, np. uruchomienie powłoki, za pomocą Falco i blokuj incydenty w zarodku.

Polityki i kontrola w Kubernetes: zasady egzekwowane

Same rekomendacje, bez automatycznego wymuszania, to proszenie się o kłopoty. Ustal standardy i zamień je w twarde reguły. W krytycznych przestrzeniach nazw włącz Pod Security Admission w trybie strict, a w pozostałych – baseline. Wpuść do klastra „strażnika” w postaci Kyverno lub Gatekeepera: wymagaj obrazów po digestach, kontenerów bez roota, z systemem plików tylko do odczytu oraz bez dostępu do hostPath i hostNetwork.

Zasadę „Zero Trust” w RBAC stosuj w praktyce: jedna aplikacja to jedno konto usługowe (ServiceAccount) i jedna rola. Żadnych uprawnień typu cluster-admin. Zabezpiecz zasoby klastra za pomocą ResourceQuota i LimitRange – wymuś definiowanie requests/limits oraz limity na liczbę obiektów, aby uniknąć problemu „hałaśliwego sąsiada”. Na węzłach wyłącz anonimowe uwierzytelnianie, wymuś TLS, zablokuj port tylko do odczytu (readOnlyPort=0) i włącz ochronę domyślnych ustawień jądra (protectKernelDefaults=true). Obrazy powinny pochodzić tylko z zaufanych rejestrów, najlepiej przez prywatny mirror, i być skanowane przy wejściu.

Jak sprawdzić skuteczność tych działań? Włącz audyt w cykl każdego sprintu: uruchamiaj narzędzia kube-bench i Polaris, ustawiając próg akceptacji na powyżej 90%. Wszelkie odchylenia zgłaszaj jako priorytetowe zadania do naprawy. Polityki traktuj jak kod – przechowuj je w repozytorium, wdrażaj przez CI/CD i poddawaj recenzji. Taka dyscyplina sprawia, że bezpieczeństwo w Kubernetesie jest realnie egzekwowane, a nie tylko teoretyczne.

Izolacja komunikacji i tajemnic

Sieć w klastrze nie może być otwarta „z przyzwyczajenia”. Zacznij od polityki NetworkPolicy typu deny-all dla każdej przestrzeni nazw, a dopiero potem dodawaj konkretne reguły zezwalające na ruch dla poszczególnych aplikacji. Osobno kontroluj ruch wychodzący (egress): stwórz białą listę domen/IP i zablokuj dowolne wyjścia do internetu. Dla ruchu przychodzącego ustaw Ingress z TLS 1.2+, włącz HSTS, ogranicz metody HTTP i zastosuj WAF z limitowaniem zapytań (rate limiting).

Wyraźnie oddziel strefę publiczną od prywatnej – frontend nie powinien mieć dostępu tam, gdzie nie musi. Aby szyfrować ruch wewnątrz klastra, włącz service mesh (np. Istio lub Linkerd) i wymuś mTLS w trybie STRICT, co zapewni weryfikację tożsamości workloadów na każdym etapie komunikacji. Do rejestru obrazów używaj sekretów imagePullSecrets per namespace, z rotacją co 90 dni i dostępem ograniczonym do konkretnych repozytoriów. Pamiętaj też o danych w spoczynku: szyfruj wolumeny (PVC), twórz zaszyfrowane backupy i regularnie testuj ich odtwarzanie – brak testu restore to brak backupu.

Koniec z trzymaniem haseł i kluczy w ConfigMap. Postaw na rozwiązania takie jak External Secrets Operator lub SealedSecrets. Klucze przechowuj w KMS/HSM, pamiętając o ich rotacji i wersjonowaniu. To eliminuje ryzyko przypadkowych wycieków i zapewnia ślad audytowy. Dbaj o polityki RBAC, aby tylko uprawnione serwisy miały dostęp do wrażliwych danych.

Prosty test szczelności: zablokuj ruch wychodzący do nieznanej domeny i sprawdź, czy aplikacja nadal działa. Jeśli pojawią się błędy, doprecyzuj reguły i usuń „magiczne”, nieudokumentowane zależności. To świetny sposób na wyłapanie ukrytych połączeń i uporządkowanie ruchu. Jeśli nie jesteś czegoś pewien, załóż, że powinno być to zabronione, i dopiero potem dodaj minimalny wyjątek.

Runtime i reakcja na incydenty

Skuteczny monitoring to taki, który analizuje zachowanie systemu w czasie rzeczywistym, a nie tylko generuje wykresy. Wykorzystaj reguły eBPF w narzędziach takich jak Falco czy Tetragon, aby wyłapywać podejrzane zdarzenia: uruchomienie powłoki sh/bash w kontenerze, próby zapisu do plików binarnych czy skanowanie portów z wnętrza poda. Integruj logi audytowe Kubernetesa z systemem SIEM i koreluj zdarzenia z danymi z admission controller oraz metadanymi z rejestru kontenerów – alerty muszą być osadzone w kontekście. Kontroluj też dryf konfiguracyjny: porównuj SBOM z tym, co faktycznie działa, a każdy nowy plik w systemie plików tylko do odczytu traktuj jako incydent.

Gdy sytuacja robi się gorąca, stosuj izolację w locie: oznacz węzeł jako niedostępny (taint/cordon), objmij namespace kwarantanną (NetworkPolicy deny-all), zatrzymaj tylko podejrzany ReplicaSet i zrób snapshot dysku do analizy.

Oto krótki playbook na wypadek awarii:

  1. Potwierdź alert i zweryfikuj hash obrazu.
  2. Zeskaluj do zera podejrzany Deployment.
  3. Zbierz artefakty (logi, opisy zasobów, zdarzenia, warstwy obrazu).
  4. Przejrzyj uprawnienia ServiceAccount i tokeny, wykonaj ich natychmiastową rotację.
  5. Zaaplikuj łatki w politykach bezpieczeństwa i przeprowadź analizę przyczyn źródłowych (RCA) w ciągu 48 godzin.

Utrzymuj zespół w formie poprzez kwartalne ćwiczenia („game day”). Celuj w czas wykrycia (MTTD) poniżej 2 minut i czas naprawy (MTTR) poniżej 30 minut. Po każdym ćwiczeniu aktualizuj reguły. Mierz skuteczność twardymi danymi: odsetkiem odrzuconych niepodpisanych obrazów, poziomem zgodności podów ze standardem PSA baseline oraz czasem publikacji SBOM.

Na koniec dwa przykłady z życia. W pewnym fintechu Falco wykryło uruchomienie powłoki przez serwer nginx. Analiza wykazała podejrzane tworzenie sekretów. Dzięki natychmiastowej izolacji węzła i przestrzeni nazw oraz zatrzymaniu podatnego kontenera, incydent opanowano. Snapshot dysku ujawnił złośliwy plik binarny nieobecny w SBOM. Wdrożenie reguły blokującej niepodpisane obrazy pozwoliło obniżyć MTTR do 22 minut. W firmie e-commerce narzędzie Tetragon wykryło nietypowe połączenia wychodzące. Playbook zadziałał błyskawicznie: zeskalowanie do zera, zrzut logów, przycięcie RBAC i blokada ruchu egress pozwoliły na wykrycie zagrożenia w 45 sekund, bez wycieku danych.