Loading content...
As Kubernetes became the dominant container orchestration platform, a gap emerged: traditional API gateways weren't designed for Kubernetes' declarative, eventually-consistent operational model. They required separate management planes, didn't understand Kubernetes services, and couldn't leverage Kubernetes' native abstractions.
Ambassador (now Emissary-Ingress as a CNCF project) was purpose-built to fill this gap. It operates as a Kubernetes-native ingress controller powered by Envoy Proxy, configured entirely through Kubernetes Custom Resource Definitions (CRDs).
This page explores Ambassador's architecture, how it integrates with Kubernetes primitives, its Envoy foundation, and when it's the optimal choice for Kubernetes-based deployments.
By the end of this page, you will understand Ambassador's Kubernetes-native architecture, how CRD-based configuration works, the relationship with Envoy, deployment patterns in Kubernetes, and decision criteria for choosing Ambassador.
Being Kubernetes-native isn't about deploying on Kubernetes—any gateway can run in containers. True Kubernetes-native architecture means:
123456789101112131415161718192021222324252627282930313233343536373839404142
# Ambassador Mapping resource - defines a routeapiVersion: getambassador.io/v3alpha1kind: Mappingmetadata: name: user-service-mapping namespace: productionspec: hostname: api.example.com prefix: /users/ service: user-service.production:8080 timeout_ms: 10000 retry_policy: retry_on: "5xx" num_retries: 3 labels: ambassador: - request_label_group: - user-api---# Rate limiting configurationapiVersion: getambassador.io/v3alpha1kind: RateLimitServicemetadata: name: rate-limiter namespace: ambassadorspec: service: rate-limit-service.ambassador:8081 protocol_version: v3---# TLS configuration apiVersion: getambassador.io/v3alpha1kind: Hostmetadata: name: api-host namespace: ambassadorspec: hostname: api.example.com tlsSecret: name: api-tls-cert requestPolicy: insecure: action: RedirectAmbassador operates as a Kubernetes controller:
┌─────────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
├─────────────────────────────────────────────────────────────────┤
│ │
│ API Server (etcd) │
│ │ │
│ │ Watch CRDs (Mappings, Hosts, etc.) │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ Ambassador Edge │ │
│ │ Controller │◄── Reconciliation Loop │
│ └─────────┬───────────┘ │
│ │ │
│ │ Generate Envoy Configuration │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ Envoy Proxy │◄── xDS Configuration │
│ │ (Data Plane) │ │
│ └─────────────────────┘ │
│ │ │
│ │ Route Traffic │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ Backend Services │ │
│ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
This pattern means:
Ambassador's CRD-based configuration integrates perfectly with GitOps tools like ArgoCD or Flux. Your entire gateway configuration—routes, TLS, rate limits—lives in Git and is applied declaratively. Changes trigger automatic reconciliation.
Ambassador is fundamentally an Envoy management plane. Envoy handles all traffic; Ambassador translates Kubernetes CRDs into Envoy configuration.
Envoy was purpose-built for modern service mesh and edge proxy use cases:
| Ambassador CRD | Envoy Concept | Purpose |
|---|---|---|
| Mapping | Route | URL path → upstream service |
| Host | FilterChainMatch + TLS | TLS termination, hostname |
| TLSContext | DownstreamTlsContext | TLS settings, protocols |
| RateLimitService | RateLimitFilter | External rate limit service |
| AuthService | ExtAuthz Filter | External authentication |
| TracingService | HttpTracer | Distributed tracing config |
| Module | Various | Global Ambassador settings |
Envoy's xDS APIs (discovery services) enable dynamic configuration:
Ambassador implements an xDS server that Envoy connects to, pushing configuration updates in real-time. This is why configuration changes apply instantly—Ambassador updates xDS, Envoy receives new config via streaming gRPC.
Understanding Envoy internals helps debug Ambassador issues. Ambassador diagnostics expose raw Envoy config at /ambassador/v0/diag/. Complex issues may require reading Envoy documentation. If your team already knows Envoy, Ambassador has a lower learning curve.
12345678910111213141516171819202122232425262728293031323334353637383940
# Header-based routingapiVersion: getambassador.io/v3alpha1kind: Mappingmetadata: name: canary-usersspec: prefix: /api/v1/users service: users-v2.production:8080 headers: x-canary-user: "true" weight: 100---# Default route for non-canaryapiVersion: getambassador.io/v3alpha1 kind: Mappingmetadata: name: stable-usersspec: prefix: /api/v1/users service: users-v1.production:8080 weight: 100---# Weighted traffic splitting (10% canary)apiVersion: getambassador.io/v3alpha1kind: Mapping metadata: name: users-canary-splitspec: prefix: /api/v1/users service: users-v1.production:8080 weight: 90---apiVersion: getambassador.io/v3alpha1kind: Mappingmetadata: name: users-canary-newspec: prefix: /api/v1/users service: users-v2.production:8080 weight: 10Ambassador integrates with external authentication services via the AuthService CRD:
12345678910111213141516171819202122232425262728
apiVersion: getambassador.io/v3alpha1kind: AuthServicemetadata: name: jwt-auth namespace: ambassadorspec: auth_service: auth-service.auth:3000 proto: http path_prefix: /auth allowed_request_headers: - Authorization - X-API-Key allowed_authorization_headers: - X-User-ID - X-User-Roles timeout_ms: 5000 failure_mode_allow: false---# Apply auth to specific routesapiVersion: getambassador.io/v3alpha1kind: Mappingmetadata: name: protected-apispec: prefix: /api/ service: api-service:8080 # Auth is applied globally by default # Use bypass_auth: true to exclude specific routesAmbassador supports external rate limit services (envoy-ratelimit) and provides descriptors for granular control:
12345678910111213141516171819202122232425
apiVersion: getambassador.io/v3alpha1kind: RateLimitServicemetadata: name: ratelimitspec: service: ratelimit.ratelimit:8081 protocol_version: v3---apiVersion: getambassador.io/v3alpha1kind: Mappingmetadata: name: rate-limited-apispec: prefix: /api/ service: api-service:8080 labels: ambassador: - request_label_group: - source_cluster: key: x-api-key header: X-API-Key - destination_cluster: key: service_name generic_key: value: api-service| Category | Features |
|---|---|
| Routing | Path, header, query param matching; regex; prefix/exact; weighted splitting |
| Load Balancing | Round-robin, ring-hash, maglev, least-request; health checking |
| Resilience | Timeouts, retries, circuit breaking, outlier detection |
| Security | External auth, TLS termination, mTLS, CORS |
| Observability | Prometheus metrics, distributed tracing (Zipkin, Jaeger, Datadog) |
| Protocols | HTTP/1.1, HTTP/2, gRPC, WebSocket, TCP |
# Install via Helm
helm repo add datawire https://app.getambassador.io
helm install ambassador datawire/emissary-ingress \
--namespace ambassador \
--create-namespace \
--set replicaCount=3
12345678910111213141516171819202122232425262728293031323334
replicaCount: 3 resources: limits: cpu: 2000m memory: 1Gi requests: cpu: 500m memory: 512Mi autoscaling: enabled: true minReplicas: 3 maxReplicas: 10 targetCPUUtilizationPercentage: 70 affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: service operator: In values: - ambassador topologyKey: topology.kubernetes.io/zone service: type: LoadBalancer annotations: service.beta.kubernetes.io/aws-load-balancer-type: "nlb" service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"Large organizations often deploy multiple Ambassador instances:
Ambassador supports namespaced configuration (v3.x) where CRDs only apply to the Ambassador in that namespace, enabling multi-tenant deployments.
Ambassador/Envoy memory usage scales with route count and connection count. Start with 512Mi and monitor. For 1000+ routes or 50K+ concurrent connections, increase to 2Gi+. CPU scales with request rate—1 CPU core handles ~10K RPS for simple routes.
| Aspect | Ambassador/Emissary | NGINX Ingress | Contour | Traefik |
|---|---|---|---|---|
| Underlying Proxy | Envoy | NGINX | Envoy | Go (native) |
| Config Model | CRDs | Annotations + CRDs | CRDs (HTTPProxy) | CRDs + annotations |
| Dynamic Config | Full xDS (hot) | Reload (brief drop) | Full xDS (hot) | Native (hot) |
| gRPC Support | Excellent | Good | Excellent | Good |
| Rate Limiting | External service | Annotations | External service | Built-in (basic) |
| Auth Integration | External AuthService | OAuth proxy sidecar | External | Forward Auth |
| Learning Curve | Moderate | Low | Low-Moderate | Low |
| Enterprise Version | Ambassador Edge Stack | NGINX Plus | N/A | Traefik Enterprise |
Ambassador Edge Stack (formerly Ambassador Pro) is the commercial offering with additional enterprise features:
| Feature | Emissary-Ingress (OSS) | Ambassador Edge Stack |
|---|---|---|
| Core Routing | ✅ | ✅ |
| External Auth | ✅ | ✅ |
| Rate Limiting | External only | Built-in + External |
| OAuth2/OIDC Filter | ❌ | ✅ Native |
| JWT Validation | External auth | ✅ Built-in |
| Developer Portal | ❌ | ✅ |
| RBAC for Teams | K8s RBAC only | ✅ Enhanced |
| Advanced Metrics | Prometheus only | ✅ Enhanced dashboards |
| Commercial Support | ❌ | ✅ 24/7 SLA |
12345678910111213141516171819202122232425262728
apiVersion: getambassador.io/v3alpha1kind: FilterPolicymetadata: name: oauth2-policyspec: rules: - host: api.example.com path: /api/* filters: - name: oauth2-filter namespace: ambassador arguments: scopes: - api:read - api:write---apiVersion: getambassador.io/v3alpha1kind: Filtermetadata: name: oauth2-filterspec: OAuth2: authorizationURL: https://auth.example.com/oauth2/authorize tokenURL: https://auth.example.com/oauth2/token clientID: ambassador-client secret: ambassador-oauth-secret protectedOrigins: - origin: https://api.example.comEdge Stack pricing is typically per-cluster or per-node. Evaluate whether built-in OAuth and rate limiting justify the cost versus implementing external services with OSS Emissary-Ingress. Many organizations start with OSS and upgrade to Edge Stack when specific enterprise features are needed.
What's Next:
Having explored Ambassador as a Kubernetes-native gateway built on Envoy, we'll next examine Envoy itself—the service proxy that powers not just Ambassador but also Istio, Contour, and numerous other cloud-native projects.
You now understand Ambassador's Kubernetes-native architecture, CRD-based configuration, Envoy foundation, and when it's the optimal choice for Kubernetes deployments.