Как стать автором
Поиск
Написать публикацию
Обновить

Защищаем контейнеры с нуля: практическое руководство по Docker security и Kubernetes security contexts

Уровень сложностиПростой
Время на прочтение4 мин
Количество просмотров2.4K

Привет, Кореша! Вы когда-нибудь задумывались о безопасности контейнеров, работающих в продакшене? Docker и Kubernetes предоставляют широкий набор инструментов, которые могут быть использованы плохими людьми. Безопасность контейнеров — это не просто волшебная защита, а многослойная система, охватывающая весь процесс от сборки до запуска в кластере.

В этой статье мы разберем практические шаги по защите ваших контейнеров, от написания безопасного Dockerfile до настройки политик безопасности в Kubernetes.

Этап 1: Безопасность на этапе сборки (Dockerfile)

Безопасность начинается с образа. Ваша цель — создать минимальный, неизменяемый и безопасный артефакт.

1. Используйте минимальные базовые образы
Чем меньше пакетов внутри, тем меньше шанс для атаки.

Нельзя:

dockerfile

FROM ubuntu:latest  # Полноценная ОС со всеми утилитами и уязвимостями
RUN apt update && apt install -y python3
COPY app.py .
CMD ["python3", "app.py"]

Можно:

dockerfile

FROM python:3.11-slim-bookworm  # Урезанный официальный образ на основе Debian slim
COPY app.py .
CMD ["python3", "app.py"]

Идеально (для Go, Java, Node.js):

dockerfile

# Multi-stage build - идеальный вариант
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp .

# Финальный образ на основе "scratch" (абсолютно пустой) или distroless
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/myapp /
CMD ["/myapp"]

Образ distroless от Google содержит только ваше приложение и его минимальные зависимости, без shell, package manager и других стандартных утилит. Взломщику просто нечем будет воспользоваться.

2. Не запускайте процессы от root
Это золотое правило контейнерной безопасности.

Плохо:

dockerfile

FROM node:20
COPY . .
RUN npm install
CMD ["node", "index.js"] # Запускается от root!

Хорошо:

dockerfile

FROM node:20-slim

# Создаем непривилегированного пользователя и группу
RUN groupadd -r appgroup && useradd -r -g appgroup appuser

# Меняем владельца файлов приложения
COPY --chown=appuser:appgroup . /app
WORKDIR /app
RUN npm install

# Переключаемся на непривилегированного пользователя
USER appuser

CMD ["node", "index.js"]

3. Сканируйте образы на уязвимости
Интегрируйте сканирование в CI/CD пайплайн.

bash

# Пример с Trivy (бесплатный и открытый сканер)
trivy image my-app:latest

# Или с Docker Scout
docker scout quickview my-app:latest

Этап 2: Безопасность на этапе выполнения (Kubernetes Security Contexts)

Kubernetes предоставляет мощный инструмент — securityContext, который позволяет fine-grained настройку прав контейнера.

1. Запрещаем запуск от root
Даже если в образе забыли указать USER.

yaml

apiVersion: v1
kind: Pod
metadata:
  name: security-demo
spec:
  containers:
  - name: sec-ctx-demo
    image: node:20-slim
    securityContext:
      runAsNonRoot: true # Kubernetes не даст запустить pod, если он работает от root
      runAsUser: 1000 # Явно указываем UID
      runAsGroup: 3000 # Явно указываем GID

2. Ограничиваем возможности (Capabilities)
По умолчанию контейнер получает множество ненужных привилегий. Отзовите всё и дайте только необходимое.

yaml

securityContext:
  capabilities:
    drop: ["ALL"] # Отзываем ВСЕ возможности
    add: ["NET_BIND_SERVICE"] # Добавляем только одну: возможность занять порт ниже 1024

3. Запрещаем эскалацию привилегий
Важная настройка, которая не позволяет процессу внутри контейнера получить больше прав, чем у него есть.

yaml

securityContext:
  allowPrivilegeEscalation: false

4. Режим только для чтения (ReadOnlyRootFilesystem)
Идеальная практика для неизменяемых контейнеров. Если вашему приложению не нужно ничего писать на диск — включайте.

yaml

securityContext:
  readOnlyRootFilesystem: true
# Но если нужно писать логи во временную папку
volumeMounts:
- name: temp-vol
  mountPath: /tmp
  readOnly: false

volumes:
- name: temp-vol
  emptyDir: {}

Этап 3: Системные политики (Pod Security Standards)

SecurityContext — это хорошо для одного пода. Но что если нужно применить политики ко всему кластеру? Здесь на помощь приходят Pod Security Admission (встроено в K8s с v1.25+) или более старый PodSecurityPolicy (устарел).

Уровни политик PSA:

  • Privileged: Без ограничений, для системных workloads.

  • Baseline: Минимальные ограничения, блокирующие известные эскалации привилегий.

  • Restricted: Жесткие ограничения, следующие best practices.

Пример Namespace с политикой Restricted:

yaml

apiVersion: v1
kind: Namespace
metadata:
  name: my-app
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: v1.29

Теперь при попытке создать под без securityContext в этом неймспейсе он будет отвергнут.

Этап 4: Следующий уровень — AppArmor и seccomp

Для параноиков и тех, кому нужна максимальная защита

Seccomp — ограничивает системные вызовы, которые может делать процесс.

yaml

securityContext:
  seccompProfile:
    type: RuntimeDefault # Используем профиль по умолчанию, предоставленный container runtime

Можно создавать и свои кастомные профили, чтобы запрещать опасные вызовы вроде execve.

Практический чеклист для внедрения

  1. Сборка: Используйте multi-stage сборку и distroless/scratch образы.

  2. Запуск: Всегда запускайте контейнеры от непривилегированного пользователя (USER в Dockerfile + runAsNonRoot: true в K8s).

  3. Политики: Настройте Pod Security Admission на уровне неймспейсов как минимум с baseline уровнем.

  4. Сканирование: Встройте сканирование образов на уязвимости (Trivy) в CI/CD.

  5. Сетевые политики: Не забывайте про NetworkPolicy для изоляции трафика между подами.

Заключение

Безопасность контейнеров — это не продукт, а процесс и правильная конфигурация. Начиная с минимального образа и заканчивая строгими политиками в кластере, вы выстраивайте многоуровневую защиту, которая серьезно усложнит жизнь злоумышленнику.

Если нужен шаблон правильных контейнеров, конфиг PSS, загляните на bfd cards, где эти вопросы разбираются регулярно.

А какие практики безопасности используете вы? Делитесь в комментариях!

Теги:
Хабы:
+7
Комментарии5

Публикации

Ближайшие события