This tutorial was contributed by Ambassador.

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.

Prerequisites

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 minikube start --driver=virtualbox --cpus 4 --memory 6000MB

Install Ambassador

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

Add the Ambassador repository with Helm.

  1. $ helm repo add datawire https://www.getambassador.io

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

Ambassador Edge Stack Integration - 图1

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

Configure Ambassador Edge Stack

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

consul-resolver.yaml

  1. $ kubectl apply -f consul-resolver.yaml

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.

Define and deploy the demo application

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

Ambassador Edge Stack Integration - 图3

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.

Create the Mapping for Quote-Consul

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

Ambassador Edge Stack Integration - 图5

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/
  1. {
  2. "server": "janky-elderberry-vtqtolsz",
  3. "quote": "The last sentence you read is often sensible nonsense.",
  4. "time": "2021-03-24T23:33:08.515530972Z"
  5. }

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

Encrypt traffic with the Consul connector

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.

The AES Consul connector retrieves the TLS certificate issued by the Consul CA and stores it in a Kubernetes secret for AES to use. The AES Consul Connector will install the following into your cluster:

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

Deploy the Ambassador Edge Stack Consul connector

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

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 success

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.

Consul UI service view that displays all services

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/
  1. {
  2. "server": "tasty-banana-2h6qpwme",
  3. "quote": "Nihilism gambles with lives, happiness, and even destiny itself!",
  4. "time": "2021-03-24T23:31:58.47597266Z"
  5. }

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 && \
  9. kubectl delete ns ambassador

Next steps

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 Ambassador site. You can learn more about other load balancer integrations with Consul by visiting the LoadBalancer collection