Introduction

Navigating container orchestration often requires establishing routes for external traffic to get to applications within a Kubernetes cluster. One fundamental component that addresses this challenge is the Ingress Controller. An Ingress Controller acts as the gateway between external requests and apps residing inside, efficiently managing external access to services running on the cluster.

In this tutorial, you will learn how to use the Ambassador Edge Stack ingress (AES for short). Then, you're going to discover how to have TLS certificates automatically deployed and configured for your hosts, and route traffic to your backend applications.

Table of contents

ambassador illustration for: Table of contents
  • [Prerequisites](#prerequisites)
  • [Step 1 – Installing the Ambassador Edge Stack](#step-1-installing-the-ambassador-edge-stack)
  • [Step 2 – Defining the Listener for Ambassador Edge Stack](#step-2-defining-the-listener-for-ambassador-edge-stack)
  • [Step 3 – Defining the Hosts for Ambassador Edge Stack](#step-3-defining-the-hosts-for-ambassador-edge-stack)
  • [Step 4 – Configuring DNS for Ambassador Edge Stack](#step-4-configuring-dns-for-ambassador-edge-stack)
  • [Step 5 – Creating the Ambassador Edge Stack Backend Services](#step-5-creating-the-ambassador-edge-stack-backend-services)
  • [Step 6 – Configuring the Ambassador Edge Stack Mappings for Hosts](#step-6-configuring-the-ambassador-edge-stack-mappings-for-hosts)
  • [Step 7 – Enabling Proxy Protocol](#step-7-enabling-proxy-protocol)
  • [Step 8 – Verifying the Ambassador Edge Stack Setup](#step-8-verifying-the-ambassador-edge-stack-setup)
  • [Conclusion](#conclusion)

Prerequisites

To complete this tutorial, you will need:

  • A Git client to clone the Starter Kit repository.
  • Helm for managing Ambassador Edge Stack releases and upgrades.
  • Doctl for cloud provider API interaction.
  • Kubectl for Kubernetes interaction.
  • Curl for testing the sample backend applications.
  • Ensure that doctl and kubectl point to your Kubernetes cluster. Refer to Authenticate cloud provider API and Creating the DOKS Cluster from the DOKS setup tutorial.

Ambassador Edge Stack 2.x introduces some changes that aren't backward-compatible with 1.x. If you already have an existing installation that uses 1.x and you would like to upgrade to version 2.x, please follow this Upgrade to newer version guide.

Step 1 - Installing the Ambassador Edge Stack

In this step, you will deploy the Ambassador Edge Stack to your DOKS cluster via Helm.

First, clone the Starter Kit repository and change the directory to your local copy.

				
					git clone https://kubernetes.io/docs/home/

cd Kubernetes-Starter-Kit-Developers
				
			

Next, add the Helm repo and list the available charts:

				
					helm repo add datawire https://app.getambassador.io

helm repo update datawire

helm search repo datawire
				
			

The output looks similar to the following:

				
					NAME CHART VERSION APP VERSION DESCRIPTION
datawire/ambassador 6.9.4 1.14.3 A Helm chart for Datawire Ambassador
datawire/ambassador-operator 0.3.0 v1.3.0 A Helm chart for Kubernetes
datawire/edge-stack 7.3.2 2.2.2 A Helm chart for Ambassador Edge Stack
datawire/emissary-ingress 7.3.2 2.2.2 A Helm chart for Emissary Ingress
datawire/telepresence 2.6.5 2.6.5 A chart for deploying the server-side component...
				
			

The chart of interest is datawire/edge-stack, which will install Ambassador Edge Stack on the cluster. Please visit the ambassador-edge-stack page for more details about this chart.

Before installing Ambassador Edge Stack 2.x itself, it is required to configure your Kubernetes cluster to support the getambassador.io/v3alpha1 and getambassador.io/v2 configuration resources.

				
					kubectl apply -f https://app.getambassador.io/yaml/edge-stack/2.3.0/aes-crds.yaml
				
			

Ambassador Edge Stack 2.x includes a Deployment in the emissary-system namespace called edge-stack-apiext. This is the API server extension that supports converting Ambassador Edge Stack CRDs between getambassador.io/v3alpha1 and getambassador.io/v2. This Deployment needs to be running at all times.

Open and inspect the 03-setup-ingress-controller/assets/manifests/ambassador-values-v7.3.2.yaml file provided in the Starter Kit repository using an editor of your choice (preferably with YAML lint support).

				
					code 03-setup-ingress-controller/assets/manifests/ambassador-values-v7.3.2.yaml
				
			

If you want to re-use the existing Load Balancer to preserve your DNS settings and other Load Balancer configurations, make sure to modify the ambassador-values-v7.3.2.yaml file to add the annotation for your existing Load Balancer. Similarly, you can enable Proxy Protocol as part of the modules section in the ambassador-values-v7.3.2.yaml file. Please refer to the How To Migrate Load Balancers guide for more details.

Finally, install Ambassador Edge Stack using Helm (a dedicated ambassador namespace will be created as well):

				
					HELM_CHART_VERSION="7.3.2"

helm install edge-stack datawire/edge-stack --version "$HELM_CHART_VERSION" \
 --namespace ambassador \
 --create-namespace \
 -f "03-setup-ingress-controller/assets/manifests/ambassador-values-v${HELM_CHART_VERSION}.yaml"
				
			

In this case, Ambassador Helm Chart version 7.3.2 was picked that maps to the 2.2.2 release of Ambassador Edge Stack (see the output from Step 2.). It’s a good practice in general to lock on a specific version. This helps to have predictable results and allows versioning control via Git.

You can verify Ambassador deployment status via:

				
					helm ls -n ambassador
				
			

The output looks similar to (notice that the STATUS column value is deployed):

				
					NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
edge-stack ambassador 1 2022-02-03 09:56:55.80197 +0200 EET deployed edge-stack-7.3.2 2.2.2
				
			

Next, check Kubernetes resources created for the ambassador namespace. Notice the deployment and replicaset resources which should be healthy and the LoadBalancer resource having an external IP assigned.

				
					kubectl get all -n ambassador
				
			

The output looks similar to:

				
					NAME READY STATUS RESTARTS AGE
pod/edge-stack-5bdc64f9f6-hhwdc 1/1 Running 0 6m14s
pod/edge-stack-5bdc64f9f6-xz9jl 1/1 Running 0 6m14s
pod/edge-stack-agent-bcdd8ccc8-m9blv 1/1 Running 0 6m14s
pod/edge-stack-redis-64b7c668b9-69c5p 1/1 Running 0 6m14s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/edge-stack LoadBalancer 10.245.189.240 68.183.252.190 80:30323/TCP,443:30510/TCP 6m14s
service/edge-stack-admin ClusterIP 10.245.170.181 <none> 8877/TCP,8005/TCP 6m14s
service/edge-stack-redis ClusterIP 10.245.205.49 <none> 6379/TCP 6m14s

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/edge-stack 2/2 2 2 6m14s
deployment.apps/edge-stack-agent 1/1 1 1 6m14s
deployment.apps/edge-stack-redis 1/1 1 1 6m14s

NAME DESIRED CURRENT READY AGE
replicaset.apps/edge-stack-5bdc64f9f6 2 2 2 6m14s
replicaset.apps/edge-stack-agent-bcdd8ccc8 1 1 1 6m14s
replicaset.apps/edge-stack-redis-64b7c668b9 1 1 1 6m14s
				
			

Finally, list all load balancer resources from your cloud account to print the IP, ID, Name, and Status:

				
					doctl compute load-balancer list --format IP,ID,Name,Status
				
			

The output looks similar to the following snippet. It should contain the new load balancer resource created for Ambassador Edge Stack in a healthy state.

				
					IP ID Name Status
68.183.252.190 0471a318-a98d-49e3-aaa1-ccd855831447 acdc25c5cfd404fd68cd103be95af8ae active
				
			

In the next step, you will learn how to create the Listener CRDs that tell the Ambassador Edge Stack what port to listen on.

Step 2 - Defining the Listener for Ambassador Edge Stack

The Listener CRD defines where and how Ambassador Edge Stack should listen for requests from the network (e.g. DO Load Balancer), and which Host definitions should be used to process those requests.

A typical Listener configuration looks like this:

				
					apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
 name: http-listener
spec:
 port: 8080
 protocol: HTTPS
 securityModel: XFP
 hostBinding:
 namespace:
 from: ALL
				
			

In the above configuration:

  • port: The network port on which Ambassador Edge Stack should listen.
  • protocol: The protocol Type on which Ambassador Edge Stack will use.
  • protocolStack: Allows configuring exactly which protocols will be layered together.
  • securityModel: Defines how the Listener will decide whether a request is secure or insecure.
  • hostBinding: Mechanism for determining which Hosts will be associated with this Listener.

Ambassador Edge Stack offers multiple configurations for protocolStack and our recommendation is to secure the XFP flag for all the connections. If the X-Forwarded-Proto header is present in the requests, the AES will automatically redirect all requests from HTTP over to HTTPS for added security. For more details, please visit the AES Listener CRD official documentation.

First, change the directory to where you cloned the Starter Kit repository.

				
					cd Kubernetes-Starter-Kit-Developers
				
			

Next, apply the manifest to create the Listener:

				
					kubectl apply -f 03-setup-ingress-controller/assets/manifests/ambassador/ambassador_listener.yaml
				
			

Inspect the AES Listener:

				
					kubectl describe listener.getambassador.io
				
			

The output looks similar to the following snippet. Notice the creation of host bindings through the Spec.Host Binding field:

				
					Name: http-listener
API Version: getambassador.io/v3alpha1
Kind: Listener
...
Spec:
 Host Binding:
 Namespace:
 From: ALL
 Port: 8080
 Protocol: HTTPS
 Security Model: XFP
 Stats Prefix: http-listener
 Events: <none>

Name: https-listener
API Version: getambassador.io/v3alpha1
Kind: Listener
...
Spec:
 Host Binding:
 Namespace:
 From: ALL
 Port: 8443
 Protocol: HTTPS
 Security Model: XFP
 Stats Prefix: https-listener
Events: <none>
				
			

In the next step, you will learn how to create the Host CRDs that tell Ambassador how to expose backend hosts (services) to the outside world.

Step 3 - Defining the Hosts for Ambassador Edge Stack

The Host CRD handles TLS termination automatically by using HTTP-01 ACME challenge to request TLS certificates from a well-known Certificate Authority (like Let's Encrypt). Certificate creation and renewal happen automatically once you configure and enable this feature in the Host CRD.

The custom Host resource defines how Ambassador Edge Stack will be visible to the outside world. It collects all the following information in a single configuration resource.

A typical Host configuration looks like below:

				
					apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
 name: echo-host
 namespace: ambassador
spec:
 hostname: echo.starter-kit.online
 acmeProvider:
 email: echo@gmail.com
 tlsSecret:
 name: tls2-cert
 requestPolicy:
 insecure:
 action: Redirect
 additionalPort: 8080
				
			

Explanations for the above configuration:

  • hostname: The hostname by which Ambassador Edge Stack will be reachable.
  • acmeProvider: Tells Ambassador Edge Stack what Certificate Authority to use and request certificates from. The email address is used by the Certificate Authority to notify about any lifecycle events of the certificate.
  • tlsSecret: The Kubernetes Secret name to use for storing the certificate after the Ambassador Edge Stack ACME challenge finishes successfully.
  • requestPolicy: Tells how Ambassador Edge Stack should handle secure and insecure requests.

  • The hostname must be reachable from the internet so the CA can POST to an endpoint in Ambassador Edge Stack.
  • In general, the registrant email address is mandatory when using ACME and it should be valid to receive notifications about certificates' expiry.
  • The Ambassador Edge Stack built-in ACME client knows to handle HTTP-01 challenges only. For other ACME challenge types like DNS-01, an external certificate management tool is required (e.g. Cert-Manager).

For more details, please visit the AES Host CRD official documentation.

The following examples configure the TLS-enabled hosts for this tutorial: echo_host and quote_host.

First, change the directory to where you cloned the Starter Kit repository.

				
					cd Kubernetes-Starter-Kit-Developers
				
			

Then, apply the manifests:

				
					kubectl apply -f 03-setup-ingress-controller/assets/manifests/ambassador/echo_host.yaml

kubectl apply -f 03-setup-ingress-controller/assets/manifests/ambassador/quote_host.yaml
				
			

Finally, inspect the AES hosts:

				
					kubectl get hosts -n ambassador
				
			

The output looks similar to the following:

				
					NAME HOSTNAME STATE PHASE COMPLETED PHASE PENDING AGE
echo-host echo.starter-kit.online Pending ACMEUserRegistered ACMECertificateChallenge 3s
quote-host quote.starter-kit.online Pending ACMEUserRegistered ACMECertificateChallenge 3s
				
			

It takes around 30 seconds to get the signed certificate for the hosts. At this point, you have the Ambassador Edge Stack installed and the hosts configured. But you still don't have the networking (eg. DNS and Load Balancer) configured to route traffic to the cluster

Take a look and see what happens to the echo-host:

				
					kubectl describe host echo-host -n ambassador
				
			

The output looks similar to the following:

				
					Events:
 Type Reason Age From Message
 ---- ------ ---- ---- -------
 Normal Pending 32m Ambassador Edge Stack waiting for Host DefaultsFilled change to be reflected in snapshot
 Normal Pending 32m Ambassador Edge Stack creating private key Secret
 Normal Pending 32m Ambassador Edge Stack waiting for private key Secret creation to be reflected in snapshot
 Normal Pending 32m Ambassador Edge Stack waiting for Host status change to be reflected in snapshot
 Normal Pending 32m Ambassador Edge Stack registering ACME account
 Normal Pending 32m Ambassador Edge Stack ACME account registered
 Normal Pending 32m Ambassador Edge Stack waiting for Host ACME account registration change to be reflected in snapshot
 Normal Pending 16m (x4 over 32m) Ambassador Edge Stack tlsSecret "tls2-cert"."ambassador" (hostnames=["echo.starter-kit.online"]): needs updated: tlsSecret does not exist
 Normal Pending 16m (x4 over 32m) Ambassador Edge Stack performing ACME challenge for tlsSecret "tls2-cert"."ambassador" (hostnames=["echo.starter-kit.online"])...
 Warning Error 16m (x4 over 32m) Ambassador Edge Stack obtaining tlsSecret "tls2-cert"."ambassador" (hostnames=["echo.starter-kit.online"]): acme: Error -> One or more domains had a problem:
[echo.starter-kit.online] acme: error: 400 :: urn:ietf:params:acme:error:dns :: DNS problem: SERVFAIL looking up A for echo.starter-kit.online - the domain's nameservers may be malfunctioning
...
				
			

As seen above, the last event tells that there's no A record to point to the echo host for the starter-kit.online domain, which results in a lookup failure. You will learn how to fix this issue in the next step of the tutorial.

Step 4 - Configuring DNS for Ambassador Edge Stack

In this step, you will configure DNS within your cloud account using a domain that you own. Then, you will create the domain A records for each host: echo and quote.

Keep in mind that the cloud provider is not a domain name registrar. You need to buy a domain name first from Google, GoDaddy, etc.

First, please execute the following command to create a new domain (starter-kit.online):

				
					doctl compute domain create starter-kit.online
				
			

The output looks similar to the following:

				
					Domain TTL
starter-kit.online 0
				
			

You need to ensure that your domain registrar is configured to point to the cloud provider name servers.

Next, you will add the required A records for the hosts you created earlier. First, you need to identify the load balancer's external IP created by the Ambassador Edge Stack deployment:

				
					kubectl get svc -n ambassador
				
			

The output looks similar to the following snippet. Notice the EXTERNAL-IP column value for the ambassador service.

				
					NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
edge-stack LoadBalancer 10.245.189.240 68.183.252.190 80:30323/TCP,443:30510/TCP 6m14s
edge-stack-admin ClusterIP 10.245.170.181 <none> 8877/TCP,8005/TCP 6m14s
edge-stack-redis ClusterIP 10.245.205.49 <none> 6379/TCP 6m14s
				
			

Then, add the records (please replace the <> placeholders accordingly). You can change the TTL value as per your requirement:

				
					doctl compute domain records create starter-kit.online --record-type "A" --record-name "echo" --record-data "&lt;YOUR_LB_IP_ADDRESS&gt;" --record-ttl "30"

doctl compute domain records create starter-kit.online --record-type "A" --record-name "quote" --record-data "&lt;YOUR_LB_IP_ADDRESS&gt;" --record-ttl "30"
				
			

[info]

If you have only one load balancer in your account, then please use the following snippet:

				
					LOAD_BALANCER_IP=$(doctl compute load-balancer list --format IP --no-header)

doctl compute domain records create starter-kit.online --record-type "A" --record-name "echo" --record-data "$LOAD_BALANCER_IP" --record-ttl "30"

doctl compute domain records create starter-kit.online --record-type "A" --record-name "quote" --record-data "$LOAD_BALANCER_IP" --record-ttl "30"
				
			

List the available records for the starter-kit.online domain:

				
					doctl compute domain records list starter-kit.online
				
			

The output looks similar to the following:

				
					ID Type Name Data Priority Port TTL Weight
164171755 SOA @ 1800 0 0 1800 0
164171756 NS @ www.progressiverobot.com 0 0 1800 0
164171757 NS @ www.progressiverobot.com 0 0 1800 0
164171758 NS @ www.progressiverobot.com 0 0 1800 0
164171801 A echo 143.244.208.191 0 0 3600 0
164171809 A quote 143.244.208.191 0 0 3600 0
				
			

Next, check the AES host status:

				
					kubectl get hosts -n ambassador
				
			

The output looks similar to the following (the STATE column should display Ready):

				
					NAME HOSTNAME STATE PHASE COMPLETED PHASE PENDING AGE
echo-host echo.starter-kit.online Ready 2m11s
quote-host quote.starter-kit.online Ready 2m12s
				
			

In case the hosts are still in a pending state, it might be due to the DNS propagation delay. Please wait for a couple of minutes and verify your host's STATE column again.

[info]

Information: Now, the network traffic will reach the AES enabled cluster, but you need to configure the backend service paths for each host. All DNS records have one thing in common: time to live (TTL). It determines how long a record can remain cached before it expires. Greater TTL values give visitors faster performance and lower TTL values ensure that DNS changes are picked up quickly. All DNS records require a minimum TTL value of 30 seconds. For more information, please visit the How to Create, Edit and Delete DNS Records page.

In the next step, you will create two simple backend services to help you test the Ambassador Edge Stack setup.

Step 5 - Creating the Ambassador Edge Stack Backend Services

In this step, you will deploy two example backend services (applications), named echo and quote to test the Ambassador Edge Stack setup.

You can have multiple TLS enabled hosts on the same cluster. On the other hand, you can have multiple deployments and services as well. So for each backend application, a corresponding Kubernetes Deployment and Service has to be created.

First, you define a new namespace for the quote and echo backend applications.

First, change the directory where the Starter Kit repository was cloned:

				
					cd Kubernetes-Starter-Kit-Developers
				
			

Next, create the backend namespace:

				
					kubectl create ns backend
				
			

Then, create the echo and quote deployments.

				
					kubectl apply -f 03-setup-ingress-controller/assets/manifests/ambassador/echo_deployment.yaml

kubectl apply -f 03-setup-ingress-controller/assets/manifests/ambassador/quote_deployment.yaml
				
			

Finally, create the corresponding services:

				
					kubectl apply -f 03-setup-ingress-controller/assets/manifests/ambassador/echo_service.yaml

kubectl apply -f 03-setup-ingress-controller/assets/manifests/ambassador/quote_service.yaml
				
			

Inspect the deployments and services you just created:

				
					kubectl get deployments -n backend
				
			

The output looks similar to the following snippet. Notice the echo and quote deployments.

				
					NAME READY UP-TO-DATE AVAILABLE AGE
echo 1/1 1 1 2m22s
quote 1/1 1 1 2m23s
				
			

And,

				
					kubectl get svc -n backend
				
			

The output looks similar to the following snippet. Notice the echo and quote services.

				
					NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo ClusterIP 10.245.175.185 &lt;none&gt; 80/TCP 2m32s
quote ClusterIP 10.245.158.116 &lt;none&gt; 80/TCP 2m33s
				
			

In the next step, you will create the AES Mappings for the quote and echo backend applications.

Step 6 - Configuring the Ambassador Edge Stack Mappings for Hosts

In this step, you will create the Ambassador Edge Stack mappings, so that your backend applications are ready for inbound/outbound traffic.

A typical Mapping definition looks like below:

				
					apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
 name: quote-backend
 namespace: ambassador
spec:
 prefix: /quote/
 host: quote.starter-kit.online
 service: quote.backend
				
			

Mapping manages traffic routing for the quote and echo services. Each mapping has a set of fields.

  • name – a string identifying the Mapping (e.g. in diagnostics).
  • prefix – the URL prefix identifying your resource.
  • service – the name of the service handling the resource; must include the namespace (e.g. myservice.othernamespace) if the service is in a different namespace than Ambassador Edge Stack.

First, change the directory to where the Starter Kit repository was cloned on your local machine:

				
					cd Kubernetes-Starter-Kit-Developers
				
			

Next, create a Mapping for echo and quote backend applications:

				
					kubectl apply -f 03-setup-ingress-controller/assets/manifests/ambassador/echo_mapping.yaml

kubectl apply -f 03-setup-ingress-controller/assets/manifests/ambassador/quote_mapping.yaml
				
			

Inspect the AES mappings:

				
					kubectl get mappings -n ambassador
				
			

The output looks similar to the following snippet. Notice the echo-backend and quote-backend lines, and how each maps to a SOURCE HOST, followed by a SOURCE PREFIX, and finally a destination service – DEST SERVICE.

				
					NAME SOURCE HOST SOURCE PREFIX DEST SERVICE STATE REASON
edge-stack-devportal /documentation/ 127.0.0.1:8500
edge-stack-devportal-api /openapi/ 127.0.0.1:8500
edge-stack-devportal-assets /documentation/(assets|styles)/(.*)(.css) 127.0.0.1:8500
edge-stack-devportal-demo /docs/ 127.0.0.1:8500
echo-backend echo.starter-kit.online /echo/ echo.backend
quote-backend quote.starter-kit.online /quote/ quote.backend
				
			

In the next step, you will learn how to use the the cloud provider Proxy Protocol with Ambassador Edge Stack.

Step 7 - Enabling Proxy Protocol

An L4 load balancer replaces the original client IP with its own IP address. This is a problem, as you will lose the client IP visibility in the application, so you need to enable proxy protocol. The proxy protocol enables an L4 Load Balancer to communicate the original client IP. For this to work, you need to configure both load balancers and AES. After deploying the [AES Backend Services](#step-5-creating-the-ambassador-edge-stack-backend-services), and manually enabling the proxy protocol, you need to configure Ambassador Module to enable AES to use the proxy protocol.

For different load balancers configurations, please refer to the examples from the official the cloud provider Cloud Controller Manager documentation. The Proxy protocol on the the cloud provider LoadBalancer needs to be enabled with the following annotations:

  • service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol
  • service.beta.kubernetes.io/do-loadbalancer-tls-passthrough

Edit the Helm values file provided in the Starter Kit repository using an editor of your choice (preferably with YAML lint support).

				
					code 03-setup-ingress-controller/assets/manifests/ambassador-values-v7.3.2.yaml
				
			

Uncomment the annotations settings from the service section.

				
					emissary-ingress: null
service:
 type: LoadBalancer
 annotations:
 service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: 'true'
 service.beta.kubernetes.io/do-loadbalancer-tls-passthrough: 'true'
				
			

You must NOT create a load balancer with Proxy support by using the the cloud provider web console, as any setting done outside DOKS is automatically overridden by DOKS reconciliation.

Save the values file and apply changes using Helm:

				
					HELM_CHART_VERSION="7.3.2"

helm upgrade edge-stack datawire/edge-stack --version "$HELM_CHART_VERSION" \
--namespace ambassador \
-f "03-setup-ingress-controller/assets/manifests/ambassador-values-v${HELM_CHART_VERSION}.yaml"
				
			

Open and inspect the 03-setup-ingress-controller/assets/manifests/ambassador/ambassador_listener.yaml file provided in the Starter Kit repository using an editor of your choice (preferably with YAML lint support).

				
					code 03-setup-ingress-controller/assets/manifests/ambassador/ambassador_listener.yaml
				
			

In the spec section, you will need to comment out the protocol field and enable the protocolStack for both listeners, like in the example below:

				
					...
spec:
 port: 8080
 # protocol: HTTPS
 protocolStack:
 - PROXY
 - HTTP
 - TCP
...
spec:
 port: 8443
 # protocol: HTTPS
 protocolStack:
 - PROXY
 - TLS
 - HTTP
 - TCP
...
				
			

Finally, save the file and apply the manifest.

				
					kubectl apply -f 03-setup-ingress-controller/assets/manifests/ambassador/ambassador_listener.yaml
				
			

Test the echo service via curl (notice that your Public IP will be present in X-Forwarded-For and X-Envoy-External-Address headers):

				
					curl -Li https://echo.starter-kit.online/echo/
				
			
				
					echo/ main!
HTTP/1.1 200 OK
content-type: text/plain
date: Thu, 23 Dec 2021 10:16:18 GMT
content-length: 356
x-envoy-upstream-service-time: 0
server: envoy

Request served by echo-5d8d65c665-8spcr

HTTP/1.1 GET /

Host: echo.starter-kit.online
X-Envoy-Original-Path: /echo/
Content-Length: 0
User-Agent: curl/7.77.0
X-Forwarded-Proto: https
X-Request-Id: 51e37d36-b810-4c77-8f65-e4f99f5d6b37
Accept: */*
X-Forwarded-For: 79.119.116.72
X-Envoy-External-Address: 79.119.116.72
X-Envoy-Expected-Rq-Timeout-Ms: 3000
				
			

In the next step, you will test the AES mappings configuration, and perform HTTP requests on the backend services using curl.

Step 8 - Verifying the Ambassador Edge Stack Setup

In this step, you have two hosts configured with TLS termination: quote.starter-kit.online and echo.starter-kit.online. Creating AES Mappings makes it easy to have TLS termination support and API Gateway capabilities.

By pinging quote.starter-kit.online or echo.starter-kit.online in the terminal, if you can see that packets are being sent to the AES external IP, then it means AES is using the mapping feature to reach the endpoints. Next, you're going to verify if service mappings are working.

First, inspect the Ambassador services:

				
					kubectl get svc -n ambassador
				
			

The output looks similar to:

				
					NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
edge-stack LoadBalancer 10.245.39.13 68.183.252.190 80:31499/TCP,443:30759/TCP 2d8h
edge-stack-admin ClusterIP 10.245.68.14 &lt;none&gt; 8877/TCP,8005/TCP 2d8h
edge-stack-redis ClusterIP 10.245.9.81 &lt;none&gt; 6379/TCP 2d8h
				
			

Next, ping the quote service host:

				
					ping quote.starter-kit.online
				
			

The output looks similar to the following snippet. Notice that it hits the AES external IP: 68.183.252.190.

				
					PING quote.starter-kit.online (68.183.252.190): 56 data bytes
64 bytes from 68.183.252.190: icmp_seq=0 ttl=54 time=199.863 ms
64 bytes from 68.183.252.190: icmp_seq=1 ttl=54 time=202.999 ms
...
				
			

Now, verify the quote backend service response using curl:

				
					curl -Li http://quote.starter-kit.online/quote/
				
			

The output looks similar to the following snippet. Notice how it automatically redirects and is using https instead.

				
					HTTP/1.1 301 Moved Permanently
location: https://quote.starter-kit.online/quote/
date: Thu, 12 Aug 2021 18:28:43 GMT
server: envoy
content-length: 0

HTTP/1.1 200 OK
content-type: application/json
date: Thu, 12 Aug 2021 18:28:43 GMT
content-length: 167
x-envoy-upstream-service-time: 0
server: envoy

{
 "server": "avaricious-blackberry-5xw0vf5k",
 "quote": "The last sentence you read is often sensible nonsense.",
 "time": "2021-08-12T18:28:43.861400709Z"
}
				
			

Finally, do the same for the echo service:

				
					curl -Li http://echo.starter-kit.online/echo/
				
			

The output looks similar to the following snippet. Notice how it automatically redirects and is using https instead.

				
					HTTP/1.1 301 Moved Permanently
location: https://echo.starter-kit.online/echo/
date: Thu, 12 Aug 2021 18:31:27 GMT
server: envoy
content-length: 0

HTTP/1.1 200 OK
content-type: text/plain
date: Thu, 12 Aug 2021 18:31:28 GMT
content-length: 331
x-envoy-upstream-service-time: 0
server: envoy

Request served by echo-5d5bdf99cf-cq8nh

HTTP/1.1 GET /

Host: echo.starter-kit.online
X-Forwarded-Proto: https
X-Envoy-Internal: true
X-Request-Id: 07afec17-4535-4157-bf5f-ad19dafb7bff
Content-Length: 0
X-Forwarded-For: 10.106.0.3
User-Agent: curl/7.64.1
Accept: */*
X-Envoy-Expected-Rq-Timeout-Ms: 3000
X-Envoy-Original-Path: /echo/
				
			

Given that proxy protocol is configured, you should see the original client IP in the HTTP request header as well.

Conclusion

In this tutorial, you learned how to set up an Ingress Controller for your DOKS cluster using the Ambassador Edge Stack. Then, you discovered how AES simplifies some of the common tasks, like handling TLS certificates for your applications – enabling TLS termination, routing traffic to backend services, and adjusting resource requests and limits for the stack.

Learn More

Next, observability plays a key role in every production-ready system. In the next step, you will learn how to enable monitoring for your DOKS cluster using Prometheus.