- Advanced configuration topics
- Upgrading Ambassador
- Statistics and Monitoring
- Need Help?
Self-Service Routing and Deployment Control
Traditionally, API Gateways have focused on operators as the primary user. Ambassador considers both developers and operators to be first-class citizens.
Decentralized, declarative configuration
The Ambassador model is a decentralized, declarative configuration model. What does this mean?
Decentralized. Ambassador is designed so that lots of developers can individually configure a specific aspect of Ambassador's configuration (usually a route). Ambassador then aggregates these individual bits of configuration into a master configuration for the gateway.
Declarative. In Ambassador, the user declares the desired end state of the configuration. Ambassador then figures out how to achieve that desired end state. If the desired end state is already in effect, no change happens. This is a contrast from an imperative model (most frequently seen as a REST API configuration), which forces the user to understand how to configure the gateway.
Ambassador configuration in practice
In a typical Ambassador deployment, each service is owned by a developer or development team. This team writes the code, tests, and deploys the service. In order to deploy this service, a team must create a Kubernetes manifest that specifies the desired end state of the service. For example, the
my-service service could be defined as below:
kind: Service apiVersion: v1 metadata: name: my-service spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376
Because a Kubernetes
service is the fundamental abstraction by which new services are exposed to other services and end users, Ambassador extends the
service with custom annotations. For example:
kind: Service apiVersion: v1 metadata: name: my-service annotations: getambassador.io/config: | --- apiVersion: ambassador/v0 kind: Mapping name: my_service_mapping prefix: /my-service/ service: my-service spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376
With this approach, there is no centralized Ambassador configuration file -- the routing configuration for Ambassador is associated with each individual service. This offers numerous benefits:
- Agility: Service owners can change their Ambassador configuration without worrying about other end users or going through a central operations function.
- Organizational scalability: Configuring individual routes in Ambassador is the responsibility of service owners, instead of a centralized team.
- Maintainability: If a service is deleted, the route disappears with the service. All of the machinery used to manage Kubernetes manifests can be used with Ambassador without modification.
It's possible as a migration strategy to start with a centralized Ambassador configuration that contains all the necessary mappings (you can create a dummy
service for this). In general, though, this approach is not recommended.
Astute Kubernetes observers may note that this decentralized model is not unique to Ambassador. In fact, Ingress controllers and Ingress resources can be used in a similar way. In this approach, a Kubernetes service stays unmodified, and a separate Ingress resource can be added to the Kubernetes manifest. You'd end up with something that looks like:
kind: Service apiVersion: v1 metadata: name: my-service spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376 --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: my-service-ingress spec: backend: serviceName: my-service servicePort: 80
Ambassador has chosen not to support ingress resources for the following reasons:
- The ingress API is extremely limited, and supports only a small subset of Ambassador's features
- The ingress API has been in beta for a number of years, and there is the possibility of it being deprecated altogether
- Having a separate object that is associated with the