Ambassador Edge Stack (AES) is an API gateway that serves as an ingress controller into your Kubernetes cluster. AES offers a comprehensive set of security functionality, supports a broad range of protocols, and supports progressive releases with modern traffic management.

You can use Consul with AES for service discovery and end-to-end TLS, including mTLS between services. This capability is particularly useful when deploying AES in hybrid clouds, where applications are deployed on VMs and Kubernetes. In this environment, AES can securely route over TLS to any application regardless of where it is deployed.

In this tutorial, you will register a service with Consul and use AES to dynamically route requests to that service based on Consul’s service discovery catalog.

Before you start, you will need the following.

  • kubectl v1.21+
  • Helm v3.5.4+
  • An active Kubernetes Cluster
  • Properly configured permissions depending on your platform

NOTE: You may use Minikube with the VirtualBox driver in this tutorial. However, be aware that this deployment is intended for a public cloud environment. If you decide to use Minikube then ensure you are starting Minikube with sufficient resources

Install Ambassador

Install AES with the Ambassador Helm chart. You can reference the for detailed installation instructions and options.

Add the Ambassador repository with Helm.

Next, create a namespace for Ambassador and install the Helm chart.

  1. $ kubectl create namespace ambassador && \
  2. helm install ambassador --namespace ambassador datawire/ambassador && \
  3. kubectl -n ambassador wait --for condition=available --timeout=90s deploy -lproduct=aes

Verify the deployment is successful by retrieving the Ambassador services information.

  1. $ kubectl -n ambassador get svc
  2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  3. ambassador LoadBalancer 10.104.22.0 10.104.22.0 80:30249/TCP,443:32184/TCP 4m2s
  4. ambassador-admin ClusterIP 10.105.158.155 <none> 8877/TCP,8005/TCP 4m2s
  5. ambassador-redis ClusterIP 10.102.28.18 <none> 6379/TCP 4m2s

Install Consul

You can install Consul on a variety of platforms. A few common platforms include GKE, AKS, and EKS. For more information on installing Consul with these popular platforms, check out the following links.

Add the HashiCorp repository to install Consul with Helm.

  1. $ helm repo add hashicorp https://helm.releases.hashicorp.com

Copy the below Consul installation values into a new YAML file.

  1. global:
  2. datacenter: dc1
  3. ui:
  4. service:
  5. type: 'LoadBalancer'
  6. syncCatalog:
  7. enabled: true
  8. server:
  9. replicas: 1
  10. bootstrapExpect: 1
  11. connectInject:
  12. enabled: true

consul-values.yaml

Install Consul with Helm and the consul-values.yaml file.

  1. $ helm install -f consul-values.yaml hashicorp hashicorp/consul --version "0.34.1"

To verify your deployment, ensure that all Consul pods are running.

  1. $ kubectl get pods
  2. NAME READY STATUS RESTARTS AGE
  3. hashicorp-consul-96fgh 1/1 Running 0 51s
  4. hashicorp-consul-connect-injector-webhook-deployment-cfd756cqrb 1/1 Running 0 51s
  5. hashicorp-consul-connect-injector-webhook-deployment-cfd75dkghr 1/1 Running 0 51s
  6. hashicorp-consul-server-0 1/1 Running 0 51s
  7. hashicorp-consul-sync-catalog-cfdc976cf-mb5ss 1/1 Running 0 51s
  8. hashicorp-consul-webhook-cert-manager-549b7d6798-kqvlq 1/1 Running 0 51s

You must have the AES quickstart completed or properly installed AES for this section to work.

The ConsulResolver allows services to register with Consul, it is opt-in and must be configured. For each Mapping you want to use with the ConsulResolver, you will apply the resolver: consul-dc1 value. If the ConsulResolver is not specified, the default resolver will be used.

Enable AES to discover services registered to Consul by creating the ConsulResolver. Copy the configuration values into a new YAML file and apply them with kubectl.

  1. ---
  2. apiVersion: getambassador.io/v2
  3. kind: ConsulResolver
  4. metadata:
  5. name: consul-dc1
  6. spec:
  7. address: http://hashicorp-consul-server-0.hashicorp-consul-server.default.svc.cluster.local:8500
  8. datacenter: dc1

Ambassador Edge Stack Integration - 图2

Register an application with Consul

To test AES’s routing functionality, resister a demo application with Consul. AES will use the endpoint data from Consul once the service is registered.

Create a specification that will register the quote pod as a Consul service with the name quote-consul.

  1. ---
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. spec:
  6. replicas: 1
  7. strategy:
  8. type: RollingUpdate
  9. selector:
  10. matchLabels:
  11. app: quote-consul
  12. template:
  13. metadata:
  14. labels:
  15. app: quote-consul
  16. annotations:
  17. 'consul.hashicorp.com/connect-inject': 'false'
  18. spec:
  19. containers:
  20. - name: backend
  21. image: docker.io/datawire/quote:0.5.0
  22. ports:
  23. - name: http
  24. containerPort: 8080
  25. - name: CONSUL_IP
  26. valueFrom:
  27. fieldRef:
  28. fieldPath: status.hostIP
  29. - name: POD_IP
  30. valueFrom:
  31. fieldRef:
  32. fieldPath: status.podIP
  33. - name: SERVICE_NAME
  34. value: 'quote-consul'
  35. readinessProbe:
  36. httpGet:
  37. path: /health
  38. port: 8080
  39. initialDelaySeconds: 30
  40. periodSeconds: 3
  41. resources:
  42. limits:
  43. cpu: '0.1'
  44. memory: 100Mi

quote.yaml

The quote application contains code to automatically register itself with Consul, with the CONSUL_IP and POD_IP environment variables specified within the quote container spec.

Note, the SERVICE_NAME environment variable in the quote deployment specifies the service name for Consul. The default value is set to quote-consul, so you only need to include it if you want to change the service name.

Deploy the demo application in Kubernetes. Note that in practice this application can be deployed anywhere in your data center (e.g., on VMs).

  1. $ kubectl apply -f quote.yaml

Verify success

Verify the quote pod is registered with Consul. You can verify the quote pod is registered correctly by accessing the Consul UI.

  1. $ kubectl port-forward service/hashicorp-consul-ui 8500:80

Navigate to http://localhost:8500/ from a web browser, the service named quote-consul should be displayed.

Consul UI service view that displays all services

Route to Consul services

Now that you have a demo application registered with Consul, you can configure AES to route traffic to it.

Copy the following configuration values into a new YAML file.

  1. ---
  2. apiVersion: getambassador.io/v2
  3. kind: Mapping
  4. metadata:
  5. name: consul-quote-mapping
  6. spec:
  7. prefix: /quote-consul/
  8. service: quote-consul
  9. resolver: consul-dc1
  10. load_balancer:
  11. policy: round_robin

quote-mapping.yaml

Install the Mapping to your cluster with kubectl.

  1. $ kubectl apply -f quote-mapping.yaml

Verify success

Add the Ambassador IP as an environment variable.

  1. export AMBASSADOR_LB_ENDPOINT=$(kubectl -n ambassador get svc ambassador \
  2. -o "go-template={{range .status.loadBalancer.ingress}}{{or .ip .hostname}}{{end}}")

NOTE: If using Minikube, be aware that this deployment uses the Kubernetes resource type LoadBalancer. To circumvent this limitation and expose an external IP address in Minikube, you may follow the steps suggested in this StackOverflow post. You may also use the command minikube tunnel as an alternative. If you choose to use minikube tunnel then issue the command in a different shell session.

Send a request to the quote-consul API with curl. Replace $AMBASSADOR_LB_ENDPOINT with your Ambassador IP.

  1. $ curl --location --insecure http://$AMBASSADOR_LB_ENDPOINT/quote-consul/

The response demonstrates that you are successfully routing traffic to the quote application, the location of which is registered in Consul.

AES can use certificates stored in Consul to originate encrypted TLS connections from AES to services in the Consul service mesh. This requires the use of the AES Consul connector.

  • RBAC resources
  • the Consul connector service
  • a TLSContext named ambassador-consul to load the ambassador-consul-connect secret into Ambassador Edge Stack

Deploy Ambassador Edge Stack Consul connector with the following command.

  1. $ kubectl apply -f https://www.getambassador.io/yaml/consul/ambassador-consul-connector.yaml

Deploy another demo application

Deploy a new version of the demo application and configure it to inject the Consul sidecar proxy by setting consul.hashicorp.com/connect-inject to true.

Copy the following configuration values into a new YAML file.

  1. ---
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. name: quote-connect
  6. spec:
  7. replicas: 1
  8. strategy:
  9. type: RollingUpdate
  10. selector:
  11. app: quote-connect
  12. template:
  13. metadata:
  14. labels:
  15. app: quote-connect
  16. annotations:
  17. 'consul.hashicorp.com/connect-inject': 'true'
  18. spec:
  19. - name: quote
  20. image: docker.io/datawire/quote:0.5.0
  21. ports:
  22. - name: http
  23. containerPort: 8080
  24. readinessProbe:
  25. httpGet:
  26. path: /health
  27. port: 8080
  28. initialDelaySeconds: 30
  29. periodSeconds: 3
  30. resources:
  31. limits:
  32. cpu: '0.1'
  33. memory: 100Mi
  34. ---
  35. apiVersion: v1
  36. kind: Service
  37. metadata:
  38. name: quote-connect
  39. annotations:
  40. a8r.io/description: 'Quote of the moment service'
  41. a8r.io/owner: 'No owner'
  42. a8r.io/chat: '#ambassador'
  43. a8r.io/bugs: 'https://github.com/datawire/qotm/issues'
  44. a8r.io/documentation: 'https://github.com/datawire/qotm/blob/master/README.md'
  45. a8r.io/repository: 'https://github.com/datawire/qotm'
  46. a8r.io/support: 'http://a8r.io/Slack'
  47. a8r.io/runbook: 'https://github.com/datawire/qotm/blob/master/README.md'
  48. a8r.io/incidents: 'https://github.com/datawire/qotm/issues'
  49. a8r.io/dependencies: 'None'
  50. spec:
  51. ports:
  52. - name: http
  53. port: 80
  54. targetPort: 8080
  55. selector:
  56. app: quote-connect

Ambassador Edge Stack Integration - 图6

quote-connect.yaml

Annotations attach metadata to Kubernetes objects. You can use annotations to link external information to objects, working in a similar, yet different, fashion to labels. For more information on annotations, you can check out this article, or get started with annotations in your own cluster .

Apply the demo application to your cluster with kubectl

  1. $ kubectl apply -f quote-connect.yaml

This will deploy a demo application called quote-connect with the Consul Connect sidecar proxy. The sidecar proxy will register the application with Consul, require TLS to access the application, and expose other Consul service segmentation features.

Verify the quote-connect application is registered in Consul by accessing the Consul UI on http://localhost:8500/ after configuring port forwarding.

  1. $ kubectl port-forward service/hashicorp-consul-ui 8500:80

The quote service should be displayed in the Consul UI. It gets its name from the container’s name property we defined in the YAML above.

Create the Mapping for Consul service mesh

Create a Mapping to route to the quote service in Consul.

  1. ---
  2. apiVersion: getambassador.io/v2
  3. kind: Mapping
  4. metadata:
  5. name: quote-connect-mapping
  6. spec:
  7. prefix: /quote-connect/
  8. service: quote-connect-sidecar-proxy
  9. resolver: consul-dc1
  10. tls: ambassador-consul
  11. load_balancer:
  12. policy: round_robin

Ambassador Edge Stack Integration - 图8

quote-connect-mapping.yaml

Apply the mapping to your cluster.

  1. $ kubectl apply -f quote-connect-mapping.yaml

Verify success

Send a request to the /quote-connect/ API. Replace $AMBASSADOR_LB_ENDPOINT with your Ambassador IP, if you didn’t set the environment variable through the AES quickstart.

  1. $ curl --location --insecure http://$AMBASSADOR_LB_ENDPOINT/quote-connect/

The response demonstrates that you are securely routing traffic to the quote application through the Consul Connect service mesh sidecar proxy.

Clean-up

You can remove all deployed resources by issuing the command below.

  1. $ kubectl delete -f quote-connect-mapping.yaml && \
  2. kubectl delete -f quote-connect.yaml && \
  3. kube delete -f https://www.getambassador.io/yaml/consul/ambassador-consul-connector.yaml && \
  4. kubectl delete -f quote-mapping.yaml && \
  5. kubectl delete -f quote.yaml && \
  6. kubectl delete -f consul-resolver.yaml && \
  7. helm uninstall hashicorp && \
  8. helm uninstall ambassador -n ambassador && \

In this tutorial you configured AES to route traffic to a service registered with Consul.

To learn more about Ambassador Edge Stack’s use cases and features, review the . You can learn more about other load balancer integrations with Consul by visiting the LoadBalancer collection