Learning Platform
Глоссарий Troubleshooting
Урок 12.05 · 20 мин
Средний
ambassadorservice meshEnvoyconnection poolingcomparisonnative sidecar

Ambassador pattern + сравнение паттернов

Ambassador — это контейнер, который проксирует исходящие соединения main приложения, инкапсулируя всю сложность работы с внешним миром. App connects на localhost:port своего ambassador, а ambassador обрабатывает: TLS, retries, circuit breaking, sharding, connection pooling. Канонический пример — Envoy в service mesh (Istio, Linkerd, Consul Connect). Сейчас, после стабилизации native sidecar (GA v1.33), ambassador почти всегда реализован как sidecar — паттерн жив концептуально, но синтаксически слился с sidecar.


Reverse proxy: NGINX, HAProxy, TLS termination

Что делает ambassador

Главная идея: main app не должен знать о сложности внешнего мира. Он просто делает HTTP GET http://localhost:8080/orders — а ambassador разруливает:

  • куда реально идёт запрос (какой Service, какой instance);
  • как он шифруется (mTLS с цепочкой сертификатов);
  • как реагирует на ошибки (retries с exponential backoff, circuit breaker);
  • как наблюдается (distributed tracing, metrics, logging);
  • как балансируется (round-robin, weighted, locality-aware).

App в этой модели — простой: один localhost endpoint, никаких внешних libraries для retry/TLS/tracing. Ambassador — сложный: вся network logic вынесена сюда.

Ambassador: разделение ответственности
main appПростой код. HTTP GET к localhost:port, никаких TLS, retries, balancing. Не знает имён реальных сервисов, не знает про сертификаты, не знает топологию.
localhost (no network)
ambassadorEnvoy. Принимает запрос на localhost:8080. Решает: какой реальный destination, какие certs, retry policy, circuit breaker state. Делает outbound mTLS соединение к destination Pod.
mTLS, retries, tracing
destinationРеальный target service. Может быть в другом namespace, другом cluster, federated mesh. Ambassador разрешает endpoint через xDS API control plane.

Use case 1: Service mesh (Istio, Linkerd)

Главный production пример ambassador. Istio инжектит Envoy sidecar в каждый Pod через mutating webhook. Все исходящие соединения main app перехватываются iptables redirect и идут через Envoy.

# До mutating webhook
spec:
  containers:
  - name: app
    image: my-app

# После Istio sidecar injection (упрощённо)
spec:
  initContainers:
  - name: istio-init                # обычный init для iptables setup
    image: istio/proxyv2
    securityContext:
      capabilities:
        add: [NET_ADMIN, NET_RAW]
    command: ['istio-iptables']    # настраивает redirect outbound на :15001
  - name: istio-proxy               # ambassador как native sidecar
    image: istio/proxyv2
    restartPolicy: Always
    ports:
    - containerPort: 15001          # outbound listener
    - containerPort: 15006          # inbound listener
  containers:
  - name: app
    image: my-app

Envoy ambassador даёт:

  • mTLS между всеми Pods mesh: автоматический cert rotation, identity SPIFFE;
  • traffic management: weighted routing, canary, A/B;
  • resilience: timeout, retry, circuit breaker, outlier detection;
  • observability: tracing headers, metrics, access logs;
  • security: AuthorizationPolicy, RequestAuthentication.

Use case 2: DB connection pooling

Postgres на каждое соединение делает новый процесс — heavy. Если у вас 100 app instances, каждый имеет pool из 20 соединений — 2000 процессов на одной БД, она ляжет. Решение — pgbouncer как ambassador: app connects на localhost:5432, pgbouncer keeps connection pool to real postgres.

apiVersion: v1
kind: Pod
metadata:
  name: app-with-pgbouncer
spec:
  initContainers:
  - name: pgbouncer
    image: bitnami/pgbouncer:1.22
    restartPolicy: Always
    env:
    - name: POSTGRESQL_HOST
      value: 'postgres.db.svc.cluster.local'
    - name: POSTGRESQL_PORT
      value: '5432'
    - name: PGBOUNCER_PORT
      value: '5432'                  # листенер на localhost:5432
    - name: PGBOUNCER_POOL_MODE
      value: 'transaction'
  containers:
  - name: app
    image: my-app:v1
    env:
    - name: DATABASE_URL
      value: 'postgres://app@localhost:5432/myapp'   # localhost, не реальный

App думает, что подключается к postgres напрямую. Pgbouncer держит, скажем, 10 реальных соединений в pool, переиспользует их для всех app requests.


Use case 3: Sharding logic

App говорит на localhost, ambassador смотрит на ключ запроса и роутит на нужный shard:

app  →  localhost:8080  →  ambassador  →  shard-1.db (для user_id < 1000)
                                        →  shard-2.db (для 1000 ≤ user_id < 2000)
                                        →  shard-3.db (для user_id ≥ 2000)

App не знает про shards. Ambassador инкапсулирует topology. Изменилась схема шардирования — обновили ambassador config, app не трогаем.


Killer момент: ambassador сегодня — это просто native sidecar

Концептуально ambassador — отдельный паттерн (он именно про outbound proxy, тогда как sidecar — про дополнение функциональности). Но синтаксически в Kubernetes:

# Sidecar (логирование)
spec:
  initContainers:
  - name: log-shipper
    image: fluent-bit
    restartPolicy: Always

# Ambassador (Envoy)
spec:
  initContainers:
  - name: envoy
    image: istio/proxyv2
    restartPolicy: Always

# Adapter (Prometheus exporter)
spec:
  initContainers:
  - name: redis-exporter
    image: prom/redis_exporter
    restartPolicy: Always

Все три — один и тот же механизм native Sidecar. Различие только в том, что делает контейнер внутри. Kubernetes не знает, что один из них adapter, а другой ambassador.

TIP

С приходом native sidecar (GA v1.33) разделение adapter/ambassador/sidecar практически исчезло из манифеста. На CKAD оно полезно для проектирования и обсуждений архитектуры, но в kubectl/YAML вы пишете initContainers + restartPolicy: Always для всех трёх. Знайте имена паттернов на уровне «концепция и канонический пример», без преувеличения важности.


Итоговое сравнение 4 паттернов

Init / Sidecar / Adapter / Ambassador
InitSequential setup перед main. Завершается до старта main containers. Use cases: wait for db, run migrations, generate config. Resource: max() по init containers.
SidecarДополняет main новой функциональностью (логирование, метрики наружу, refresh секретов). Работает параллельно с main, restart по rp Always. Resource: sum() с main.
AdapterПреобразует output main в формат для внешней системы (custom logs → JSON, native metrics → Prometheus exposition). Работает параллельно, реализуется как native sidecar.
AmbassadorПроксирует outbound соединения main. App к localhost, ambassador к реальному destination с mTLS/retries/sharding. Канонический пример — Envoy в service mesh. Реализуется как native sidecar.
PatternЧто делаетЖизненный циклYAML location
InitSetup перед mainзавершается до maininitContainers (без restartPolicy)
SidecarДополняет mainпараллельно с maininitContainers + restartPolicy: Always
AdapterTransform outputпараллельно с maininitContainers + restartPolicy: Always
AmbassadorProxy outboundпараллельно с maininitContainers + restartPolicy: Always

Adapter и ambassador синтаксически — native sidecar. Init — это единственный концептуально и синтаксически отдельный механизм.


Что выбрать для своей задачи: дерево решений

  1. Setup до старта main, потом не нужен? → Init container.
  2. Long-running рядом с main для дополнительной функции (логи, метрики, secrets)? → native Sidecar.
  3. Long-running, преобразующий output main в чужой формат? → Adapter (синтаксически — native sidecar).
  4. Long-running, проксирующий outbound app для mTLS/retries/sharding? → Ambassador (синтаксически — native sidecar).
  5. Независимый процесс, общается с main по HTTP/gRPC? → Отдельный Deployment + Service. Не multi-container.

Проверка знанийKnowledge check
Что такое ambassador pattern и какой канонический пример его реализации в современном Kubernetes?
ОтветAnswer
Ambassador — контейнер-proxy для исходящих соединений main app. App connects на localhost:port, ambassador handles mTLS, retries, circuit breaking, sharding, observability. Канонический пример — Envoy proxy в service mesh (Istio, Linkerd). Современно реализуется как native sidecar (GA v1.33): container в spec.initContainers с restartPolicy: Always.
Проверка знанийKnowledge check
Pgbouncer в Pod рядом с app: какой паттерн и почему?
ОтветAnswer
Ambassador. Pgbouncer — это proxy для outbound соединений app к postgres. App connects на localhost:5432, pgbouncer держит pool реальных соединений к postgres.db.svc и переиспользует их. Это разгружает базу (один процесс на N клиентов вместо N процессов). App не знает про connection pooling, всё инкапсулировано в ambassador.
Проверка знанийKnowledge check
Чем синтаксически отличаются sidecar, adapter и ambassador в Kubernetes манифесте?
ОтветAnswer
Никак. Все три реализуются одинаково: container в spec.initContainers с restartPolicy: Always (native sidecar, GA v1.33). Различия — концептуальные: sidecar добавляет функциональность, adapter трансформирует output, ambassador проксирует outbound. Kubernetes не знает, какую роль играет ваш контейнер — он просто видит native sidecar.
Проверка знанийKnowledge check
Тебе нужно добавить mTLS ко всем outbound соединениям app, app модифицировать нельзя. Какой паттерн использовать?
ОтветAnswer
Ambassador. Sidecar контейнер Envoy (или Linkerd-proxy) в том же Pod. iptables redirect outbound на Envoy. Envoy делает mTLS с downstream. App продолжает делать plain HTTP к localhost — ничего не знает про TLS. Реализация — Istio sidecar injection или ручное добавление Envoy как native sidecar (initContainer + restartPolicy: Always).

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. Что делает ambassador pattern в multi-container Pod?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5