An Intro to Ambassador

In the Cloud Native world, the use of proxies is growing in popularity. One such use-case for a proxy is to support API gateway functionality. Ambassador is one of these API gateways. Read on to learn more!

What is Ambassador?

Ambassador is an open-source API gateway based on the Envoy proxy and meant for k8s environments. It was created by the Datawire team to support primarily North/South traffic within a distributed architecture running on k8s. Ambassador is a configuration wrapper for Envoy. It was created because native Envoy configuration is hard to understand and configure properly.

Basics

Different Ambassador instances can run within an environment by specifying different IDs. For example, from a deployment.yaml:

...
spec:
  template:
    spec:
      containers:
      - env:
        - name: AMBASSADOR_ID
          value: myID
...

Configuration is done via annotations in k8s. Here is an example of a mapping:

apiVersion: v1
kind: Service
metadata:
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name:  test-mapping
      ambassador_id: myID
      prefix: /
      host: test-mapping.default.svc.cluster.local
      service: test-mapping.test.svc.cluster.local
...

Note, prior to version 0.50.0, configuration could also be done via configmaps, but this is no longer supported.

Ambassador can be configured to route authentication traffic to a dedicated authentication service. If this is configured then EVERY call goes to the authentication service first and must return a status code of 200 before being routed downstream:

---
apiVersion: v1
kind: Service
metadata:
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Module
      name:  ambassador
      ambassador_id: myID
      ---
      apiVersion: ambassador/v0
      kind:  Module
      name:  tls
      ambassador_id: myID
      config:
        server:
          enabled: True
...
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      ambassador_id: myID
      kind:  AuthService
      name:  authentication
      auth_service: "auth:3000"
      path_prefix: "/auth/api/check"
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      ambassador_id: myID
      name: auth
      prefix: /auth/
      rewrite: /auth/
      service: auth:3000
...

Given Ambassador is based on Envoy, it supports the majority of features that Envoy does. This includes things like tracing:

apiVersion: v1
kind: Service
metadata:
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Module
      name:  ambassador
      ambassador_id: myID
      ---
      apiVersion: ambassador/v0
      kind: TracingService
      name: tracing
      ambassador_id: myID
      service: collector.default.svc.cluster.local:9411
      driver: zipkin
...

From a monitoring perspective, statsd is supported and can be converted to Prometheus format (from a deployment.yaml):

...
    spec:
      containers:
      - env:
        - name: STATSD_ENABLED
          value: "true"
      - args:
        - --statsd.listen-udp=:8125
        - --statsd.mapping-config=/statsd-exporter/mapping-config.yaml
        image: prom/statsd-exporter:v0.7.0
        imagePullPolicy: IfNotPresent
        name: statsd-sink
        ports:
        - containerPort: 9102
          name: metrics
          protocol: TCP
        - containerPort: 8125
          name: listener
          protocol: TCP
        volumeMounts:
        - mountPath: /statsd-exporter/
          name: stats-exporter-mapping-config
          readOnly: true
...

A Grafana dashboard exists specifically for Ambassador:

Gotchas

After using Ambassador for a while I figured I would share some gotchas I have experienced along the way:

  • If configuration is not working ensure the proper ambassador_id is specified and any configuration names are unique (e.g. if you have multiple mappings)
  • If you are using configmaps you should be moving off. In any case, any changes to a configmap requires a restart of all impacted Ambassador pods to take effect.
  • If things are not working and you cannot track it down use the diagnostics page — the UI will highlight issues and in worst case debug logging will usually help pinpoint the issue.
  • If it is not in the documentation do not expect it to work — while Ambassador is based on Envoy and certain Envoy overrides can be applied, they are limited at best. If what you are trying to do is not in the documentation then it is unlikely to be available or supported.
  • I have run into issues where upgrading a deployment (not service) results in gateway timeouts — the workaround is to kick the impacted Ambassador pods (issue appears to be routing to non-existing pods).

Summary

If you are look for an API gateway optimized for north/south traffic on k8s then Ambassador is a solid choice. Ambassador is based on the production ready Envoy proxy and offers many of the same features. The latest information about Ambassador, check the documentation.

© 2019 – 2018, Steve Flanders. All rights reserved.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back To Top