Docker і Kubernetes: посібник із безпеки контейнерів
Контейнери змінили підхід до розгортання програмного забезпечення — але багато команд запускають їх із root-доступом, застарілими образами та відкритими секретами. Ось повний посібник із посилення захисту.
Зміст
- Хибне уявлення про безпеку контейнерів
- Посилення захисту образів Docker
- Використання мінімальних базових образів
- Багатоетапна збірка
- Ніколи не запускайте від імені root
- Сканування образів на вразливості
- Безпека середовища виконання Docker
- Відмова від привілеїв
- Seccomp і AppArmor
- Ніколи не використовуйте --privileged
- Посилення захисту Kubernetes
- Стандарти безпеки Pod
- RBAC: принцип найменших привілеїв для облікових записів служб
- Управління секретами
- Мережеві політики
- Безперервна оцінка стану безпеки
Хибне уявлення про безпеку контейнерів
Поширена помилка — вважати, що контейнери забезпечують потужну ізоляцію, аналогічну до віртуальних машин. Це не так. Контейнери спільно використовують ядро хоста — вразливість, що дозволяє вийти за межі контейнера і виконати код у ядрі хоста, надає доступ до кожного контейнера на цьому хості, а також до самого хоста. Безпека контейнерів полягає у зменшенні радіуса ураження скомпрометованого контейнера, а не в припущенні, що межа є непроникною.
Поверхня атаки охоплює образ контейнера, конфігурацію середовища виконання, платформу оркестрації, мережу та рівень управління секретами. Посилення захисту має охопити їх усі.
Посилення захисту образів Docker
Використання мінімальних базових образів
Кожен пакет у базовому образі є потенційною вразливістю. Надавайте перевагу distroless-образам (образи Google без оболонки, менеджера пакетів або інструментів ОС) або Alpine Linux (musl libc, apk, ~5 МБ):
# Замість ubuntu:22.04
FROM gcr.io/distroless/java21-debian12
До Distroless-образів не можна підключитися через оболонку в інтерактивному режимі — це суттєво обмежує можливості зловмисника у разі компрометації контейнера.
Багатоетапна збірка
Залежності збірки (компілятори, інструменти збірки, тестові фреймворки) ніколи не мають потрапляти до продакшен-образу:
FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN go build -o server .
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/server /server
ENTRYPOINT ["/server"]
Фінальний образ містить лише скомпільований бінарний файл і його залежності середовища виконання.
Ніколи не запускайте від імені root
За замовчуванням процеси в контейнерах виконуються від імені root (UID 0). Якщо відбувається вихід за межі контейнера, зловмисник отримує root на хості. Завжди створюйте користувача без привілеїв root:
RUN useradd -u 1001 -r appuser
USER appuser
Поєднуйте це з файловою системою --read-only і --tmpfs /tmp для місць, де потрібний запис.
Сканування образів на вразливості
Інтегруйте сканування образів у свій конвеєр CI/CD:
# Trivy — швидкий, комплексний сканер вразливостей
trivy image myapp:latest
# Grype — альтернатива з підтримкою SBOM
grype myapp:latest
Перервіть збірку, якщо виявлено CVE з рівнем High або Critical. Регулярно перебудовуйте та оновлюйте базові образи — не лише при зміні коду застосунку.
Безпека середовища виконання Docker
Відмова від привілеїв
Привілеї Linux розбивають модель root «все або нічого» на дискретні одиниці. Відмовляйтеся від усіх привілеїв і додавайте назад лише ті, що потрібні застосунку:
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp
Seccomp і AppArmor
Профіль seccomp за замовчуванням Docker блокує ~44 небезпечних системних виклики. Використовуйте його явно і розгляньте власний профіль для чутливих робочих навантажень. Профілі AppArmor або SELinux додають обов'язковий контроль доступу поверх ядра:
docker run --security-opt seccomp=profile.json myapp
docker run --security-opt apparmor=docker-default myapp
Ніколи не використовуйте --privileged
Прапор --privileged надає контейнеру майже повний доступ до хоста, вимикаючи всю ізоляцію безпеки. Він іноді потрібен для специфічних випадків (наприклад, запуску Docker усередині Docker), але його слід повністю уникати в продакшені та сприймати як негайний тривожний сигнал під час перевірок безпеки.
Посилення захисту Kubernetes
Стандарти безпеки Pod
Kubernetes застосовує політики безпеки через Pod Security Standards (які замінили застарілий PodSecurityPolicy):
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
Профіль restricted вимагає: відсутності привілейованих контейнерів, відсутності root-користувача, відсутності підвищення привілеїв, обов'язкового профілю seccomp, відмови від усіх привілеїв.
RBAC: принцип найменших привілеїв для облікових записів служб
Кожен pod виконується з обліковим записом служби. За замовчуванням цей обліковий запис може звертатися до API Kubernetes. Застосовуйте принцип найменших привілеїв:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-role
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get"]
Виконуйте аудит за допомогою kubectl auth can-i --list --as=system:serviceaccount:default:myapp. Вимикайте автоматичне монтування токенів облікового запису служби, коли це не потрібно: automountServiceAccountToken: false.
Управління секретами
Secrets у Kubernetes кодуються в Base64, а не шифруються, за замовчуванням. Використовуйте:
- Шифрування у спокої: увімкніть
EncryptionConfigurationв API-сервері для шифрування секретів у etcd - Зовнішні менеджери секретів: AWS Secrets Manager, HashiCorp Vault або GCP Secret Manager через External Secrets Operator
- Ніколи не зберігайте секрети в ConfigMaps, змінних середовища в специфікаціях Deployment (видимих через
kubectl describe) або образах контейнерів
Мережеві політики
За замовчуванням усі pods у кластері Kubernetes можуть спілкуватися між собою. Впроваджуйте NetworkPolicy для мікросегментації:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
spec:
podSelector: {}
policyTypes: [Ingress]
Потім додавайте явні правила дозволу лише для необхідних шляхів комунікації. Використовуйте CNI-плагін, який застосовує NetworkPolicy (Calico, Cilium, Weave).
Безперервна оцінка стану безпеки
- Використовуйте Falco (інструмент безпеки середовища виконання CNCF) для виявлення підозрілої поведінки під час виконання: несподіваних запусків оболонки, вихідних з'єднань до нових IP-адрес, спроб підвищення привілеїв
- Скануйте конфігурації кластера за допомогою kube-bench (CIS Kubernetes Benchmark) та оператора Trivy
- Увімкніть журналювання аудиту на API-сервері Kubernetes і надсилайте журнали до SIEM
- Регулярно ротуйте дайджести образів і автоматизуйте оновлення залежностей за допомогою Renovate або Dependabot