Chapter 35 of 47 · Pod patterns

Adapter and ambassador containers

Two special kinds of sidecar. An adapter is a translator: it takes what your app produces and turns it into the format the outside world expects. An ambassador is a messenger: your app hands it outgoing calls, and it deals with the complicated outside world on the app's behalf.

Three helpers, one Pod

All three are sidecars (chapter 34). What differs is the direction of the work. Click each helper:

Sidecar, adapter and ambassador around one appThe app sits in the middle of a Pod. A sidecar adds a feature beside it. An adapter sits between the app and a monitoring system that reads from it. An ambassador sits between the app and an outside service the app calls. POD posts posts appyour code sidecaradds a feature adaptertranslates OUT ambassadorproxies calls OUT Prometheus reads Redis / DB

Adapter

Faces inward-looking tools like monitoring. Others read from it; it reads from your app and answers in a standard format.

The adapter: a translator

Imagine six services written by six teams. One logs JSON, one plain text, one exposes stats at /stats, another at /debug/vars. Your monitoring tool wants one format from everyone. Rewriting six apps is a lot of work. Instead, put a small adapter next to each app that converts its output into the standard format.

Without adapters

The monitoring team must understand every app's special format. Every new app means new monitoring code.

With adapters

Every Pod looks the same from outside: same port, same format. The app does not change at all.

Common adapters: metrics exporters (turn app or database stats into Prometheus format), log normalisers (turn odd log lines into structured JSON).

Example: metrics for Prometheus

Say posts already has an endpoint /stats that returns its own JSON. Prometheus expects a plain-text format at /metrics. Step through:

  1. // posts app, unchanged
    GET http://localhost:4000/stats
    { "postsCreated": 1284, "avgResponseMs": 41 }

    The app speaks its own language.

  2. Prometheus ──GET──▶ posts-pod:9100/metrics   (the adapter's port)

    Prometheus asks the adapter, not the app.

  3. adapter ──GET──▶ localhost:4000/stats      (same Pod, so localhost works)

    The adapter fetches the app's own stats. Same Pod, shared network (chapter 6).

  4. # answer from the adapter, in Prometheus format
    posts_created_total 1284
    posts_response_ms_avg 41

    Translated. Prometheus is happy, and posts never knew Prometheus existed.

containers:
  - name: posts
    image: micro-posts:1.0
    ports: [{ containerPort: 4000 }]
  - name: metrics-adapter
    image: example/json-to-prometheus:1.2
    args: ["--source=http://localhost:4000/stats", "--listen=:9100"]
    ports: [{ containerPort: 9100, name: metrics }]

The ambassador: a messenger

A country's ambassador handles a foreign country's language, customs and paperwork, so the people at home do not have to. An ambassador container does the same for calls going out of your app:

App calls localhost, ambassador calls the real service POD comments comments appcalls localhost:6379 ambassadorTLS, auth, retries secure Managed Rediscloud, TLS + password

Your code stays as simple as on your laptop: "connect to localhost:6379". Locally that is a plain Redis; in production it is the ambassador, which knows where the real Redis is and how to talk to it safely.

Ambassador examples

containers:
  - name: query
    image: micro-query:1.0
    env:
      - name: DB_HOST
        value: "127.0.0.1"          # just localhost
  - name: cloud-sql-proxy
    image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.11.0
    args: ["--port=5432", "my-project:europe-west1:blog-db"]

Cloud providers ship proxies like this: they handle encrypted connections and cloud login, so your app connects to 127.0.0.1:5432 without any cloud-specific code.

From ambassador to service mesh

Take the ambassador idea, put one proxy next to every Pod, and let it handle incoming traffic too: that is a service mesh such as Istio or Linkerd. The proxies give you encryption between all services, retries, traffic splitting for canaries (chapter 15) and detailed metrics, with no app changes. It is powerful, but a mesh is a big piece of infrastructure; one hand-written ambassador is the small version of the same idea.

Which one is it?

SidecarAdapterAmbassador
JobAdd a featureMake the app look standard to othersMake outside services look simple to the app
DirectionAnyOutside world reads the appApp calls the outside world
Examplegit-sync, log shipperPrometheus exporterCloud SQL proxy, Redis proxy

Recap

Quick check

Why is an ambassador easier to test than code that talks to the cloud directly?
Show answer

The app only knows localhost:6379. On a laptop you run a plain Redis there; in production the ambassador sits there. The app code is the same everywhere.

Adapter and ambassador patterns: common questions

What is the difference between an adapter and an ambassador container?

An adapter translates what the app exposes, such as metrics, into a standard format for others. An ambassador proxies the app outgoing calls, handling addresses, security and retries.