HardТеория7 min

Kubernetes паттерны

Sidecar, Ambassador, Adapter, Operator, Init Container -- продвинутые паттерны проектирования в Kubernetes

Обзор паттернов

Kubernetes предоставляет примитивы (Pod, Container), из которых складываются архитектурные паттерны. Эти паттерны решают типовые задачи: логирование, мониторинг, проксирование, инициализация.

Паттерн Описание Количество контейнеров
Init Container Выполняется до основного 1+ init + 1 main
Sidecar Работает рядом с основным 2+ (main + sidecar)
Ambassador Прокси для внешних вызовов 2 (main + proxy)
Adapter Преобразование формата данных 2 (main + adapter)
Operator Расширение API Kubernetes Отдельный Pod

Init Container

Init Container выполняется перед запуском основного контейнера. Используется для подготовки среды.

# Init container: wait for database and run migrations
apiVersion: v1
kind: Pod
metadata:
  name: api-server
spec:
  initContainers:
    # Init 1: Wait for PostgreSQL to be ready
    - name: wait-for-db
      image: busybox:1.36
      command: ['sh', '-c']
      args:
        - |
          until nc -z postgres-service 5432; do
            echo "Waiting for PostgreSQL..."
            sleep 2
          done
          echo "PostgreSQL is ready!"

    # Init 2: Run database migrations
    - name: run-migrations
      image: myapp/api:v1.2.3
      command: ['php', 'bin/console', 'doctrine:migrations:migrate', '--no-interaction']
      env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: url

    # Init 3: Warm up cache
    - name: warmup-cache
      image: myapp/api:v1.2.3
      command: ['php', 'bin/console', 'cache:warmup']

  containers:
    - name: api
      image: myapp/api:v1.2.3
      ports:
        - containerPort: 8080

Типичные задачи для Init Container

Задача Описание
Ожидание зависимостей Подождать пока БД/Redis станут доступны
Миграции БД Запустить migrations перед стартом
Скачивание конфигов Загрузить конфигурацию из Vault/S3
Настройка прав Изменить owner/permissions для volumes
Прогрев кэша Сгенерировать кэш Symfony/Laravel

Sidecar

Sidecar работает параллельно основному контейнеру в одном Pod, расширяя его функциональность.

# Sidecar: log collector + metrics exporter
apiVersion: v1
kind: Pod
metadata:
  name: api-with-sidecars
spec:
  containers:
    # Main container: PHP application
    - name: api
      image: myapp/api:v1.2.3
      ports:
        - containerPort: 8080
      volumeMounts:
        - name: logs
          mountPath: /var/log/app

    # Sidecar 1: Log shipping to centralized logging
    - name: log-shipper
      image: fluent/fluent-bit:2.1
      volumeMounts:
        - name: logs
          mountPath: /var/log/app
          readOnly: true
        - name: fluent-bit-config
          mountPath: /fluent-bit/etc
      resources:
        requests:
          cpu: "50m"
          memory: "64Mi"
        limits:
          cpu: "100m"
          memory: "128Mi"

    # Sidecar 2: Prometheus metrics exporter
    - name: php-fpm-exporter
      image: hipages/php-fpm_exporter:2.2
      ports:
        - containerPort: 9253
          name: metrics
      env:
        - name: PHP_FPM_SCRAPE_URI
          value: "tcp://127.0.0.1:9000/status"
      resources:
        requests:
          cpu: "10m"
          memory: "32Mi"

  volumes:
    - name: logs
      emptyDir: {}
    - name: fluent-bit-config
      configMap:
        name: fluent-bit-config
<?php

declare(strict_types=1);

/**
 * PHP application designed for sidecar pattern
 *
 * Writes structured logs to file (sidecar ships them)
 * Exposes FPM status for metrics sidecar
 */
final class SidecarAwareApplication
{
    /**
     * Write structured JSON logs to file
     * Sidecar (Fluent Bit) reads and ships to Elasticsearch
     */
    public function log(string $level, string $message, array $context = []): void
    {
        $entry = json_encode([
            'timestamp' => (new \DateTimeImmutable())->format('c'),
            'level' => $level,
            'message' => $message,
            'context' => $context,
            'request_id' => $_SERVER['HTTP_X_REQUEST_ID'] ?? uuid_create(),
            'service' => 'api',
        ]) . "\n";

        file_put_contents('/var/log/app/app.log', $entry, FILE_APPEND | LOCK_EX);
    }
}
## Ambassador

Ambassador -- прокси-контейнер для управления исходящими соединениями. Основной контейнер общается с Ambassador через localhost.

# Ambassador: connection pooling proxy for PostgreSQL
apiVersion: v1
kind: Pod
metadata:
  name: api-with-pgbouncer
spec:
  containers:
    # Main: PHP application connects to localhost:5432
    - name: api
      image: myapp/api:v1.2.3
      env:
        - name: DATABASE_URL
          value: "pgsql://app:password@localhost:5432/myapp"

    # Ambassador: PgBouncer connection pooler
    - name: pgbouncer
      image: bitnami/pgbouncer:1.21
      ports:
        - containerPort: 5432
      env:
        - name: POSTGRESQL_HOST
          value: "postgres-primary.default.svc.cluster.local"
        - name: POSTGRESQL_PORT
          value: "5432"
        - name: PGBOUNCER_POOL_MODE
          value: "transaction"
        - name: PGBOUNCER_MAX_CLIENT_CONN
          value: "200"
        - name: PGBOUNCER_DEFAULT_POOL_SIZE
          value: "20"
      resources:
        requests:
          cpu: "50m"
          memory: "64Mi"

Типичные Ambassador-прокси

Прокси Назначение
PgBouncer Connection pooling для PostgreSQL
Envoy Service mesh proxy (Istio sidecar)
stunnel TLS termination для legacy протоколов
HAProxy Load balancing для внешних сервисов

Adapter

Adapter преобразует данные или интерфейс основного контейнера для совместимости с внешними системами.

# Adapter: convert PHP logs format to Prometheus metrics
apiVersion: v1
kind: Pod
metadata:
  name: api-with-adapter
spec:
  containers:
    - name: api
      image: myapp/api:v1.2.3
      volumeMounts:
        - name: metrics
          mountPath: /tmp/metrics

    # Adapter: reads custom metrics file, exposes as Prometheus
    - name: metrics-adapter
      image: prom/statsd-exporter:v0.26
      ports:
        - containerPort: 9102
          name: metrics
      args:
        - "--statsd.mapping-config=/config/mapping.yml"
      volumeMounts:
        - name: adapter-config
          mountPath: /config

  volumes:
    - name: metrics
      emptyDir: {}
    - name: adapter-config
      configMap:
        name: metrics-adapter-config

Operator

Operator -- расширение Kubernetes, которое автоматизирует управление сложными приложениями. Operator следит за Custom Resources и выполняет действия.

                    ┌─────────────────┐
                    │  Custom Resource │
                    │  (CRD)          │
                    │                 │
                    │ spec:           │
                    │   replicas: 3   │
                    │   version: 16   │
                    └────────┬────────┘
                             │ watches
                    ┌────────┴────────┐
                    │    Operator     │
                    │    Controller   │
                    │                 │
                    │ Reconcile loop: │
                    │ observe → diff  │
                    │ → act           │
                    └────────┬────────┘
                             │ manages
              ┌──────────────┼──────────────┐
              ▼              ▼              ▼
        ┌──────────┐  ┌──────────┐  ┌──────────┐
        │ Pod: PG  │  │ Pod: PG  │  │ Pod: PG  │
        │ Primary  │  │ Replica  │  │ Replica  │
        └──────────┘  └──────────┘  └──────────┘

Популярные операторы

Operator Управляет
CloudNativePG PostgreSQL clusters
Strimzi Apache Kafka clusters
Redis Operator Redis Sentinel/Cluster
cert-manager TLS certificates
Prometheus Operator Monitoring stack
# Using CloudNativePG Operator
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: app-database
spec:
  instances: 3

  postgresql:
    parameters:
      max_connections: "200"
      shared_buffers: "256MB"
      work_mem: "8MB"

  storage:
    size: 50Gi
    storageClass: fast-ssd

  backup:
    barmanObjectStore:
      destinationPath: s3://my-backups/pgdata
      s3Credentials:
        accessKeyId:
          name: s3-creds
          key: ACCESS_KEY_ID
        secretAccessKey:
          name: s3-creds
          key: SECRET_ACCESS_KEY
    retentionPolicy: "30d"

  monitoring:
    enablePodMonitor: true

Когда какой паттерн

Задача Паттерн
Подготовка среды перед запуском Init Container
Сбор логов, метрик Sidecar
Connection pooling, proxy Ambassador
Преобразование формата данных Adapter
Управление stateful приложением Operator
Service mesh (mTLS, routing) Sidecar (Envoy)
Миграции БД Init Container
TLS termination Ambassador/Sidecar

Итоги

  • Init Container решает задачи подготовки: ожидание зависимостей, миграции, прогрев кэша
  • Sidecar расширяет функциональность основного контейнера без изменения его кода
  • Ambassador проксирует исходящие соединения (PgBouncer, Envoy)
  • Adapter преобразует форматы данных для совместимости с внешними системами
  • Operator автоматизирует управление сложными приложениями через CRD и reconciliation loop