Project Status: Experimental
Ambassador, the "Kubernetes-native API gateway for microservices built on Envoy", currently pulls its configuration (mainly Mappings of URL prefixes to Kubernetes Services) from annotations on Services; I wanted Ambassador to be even more Kubernetes native, so I've created a Mapping CRD and a controller that maintains a dummy Service for each Mapping, annotated according to the Mapping's Spec.
From "Kubernetes Custom Resource, Controller and Operator Development Tools" (Admiralty blog); the post discusses Metacontroller, Kubebuilder, and the Operator SDK. As a use case, three different yet functionally equivalent Ambassador operators were created, one with each tool. This repository was built with Metacontroller v0.2.0.
- Install Ambassador (steps 1 and 2). N.B.: you may have to wait a few minutes before the Ambassador Service's external IP is provisioned, but keep going, it's only blocking for step 6 below.
- Install Metacontroller.
- Install ambassador-shim-metacontroller, which consists of:
- a CustomResourceDefinition: Mapping,
- a CompositeController that hooks to
- a Service, backed by a Deployment, which implements the Mapping controller:
If you need more flexibility, you can build your own manifest from the different parts in the repository; if you use kustomize, you can start fromkubectl apply -f https://raw.githubusercontent.com/admiraltyio/ambassador-shim-metacontroller/master/kustomize/kustomized.yaml
kustomize/kustomization.yaml
. - Deploy the sample: a stock NGINX Deployment and corresponding Service and Mapping:
kubectl apply -f https://raw.githubusercontent.com/admiraltyio/ambassador-shim-metacontroller/master/examples/mapping/ambassadorshim_v1alpha1_mapping.yaml
- Verify that the Mapping was configured and is up-to-date, i.e., that a corresponding dummy Service was created and properly annotated:
kubectl get mapping foo -o yaml kubectl get service foo-ambassadorshim -o yaml
- Once the external IP from step 1 is provisioned, you can access the foo service at /foo/:
EXTERNAL_IP=$(kubectl get service ambassador -o jsonpath="{.status.loadBalancer.ingress[0].ip}") curl http://$EXTERNAL_IP/foo/
This shim is a proof of concept that only supports the most basic feature of Ambassador: mapping a prefix to a Service. It could be expanded (full Mapping Spec and Status, other CRDs, etc.) into a fully-featured side-car of Ambassador, or merge with it. See the full discussion in the blog post.