Skip to content

Latest commit

 

History

History
307 lines (217 loc) · 8.47 KB

File metadata and controls

307 lines (217 loc) · 8.47 KB

Linkerd and Ingress

This is the documentation - and executable code! - for the Service Mesh Academy Ingress workshop. The easiest way to use this file is to execute it with demosh.

Things in Markdown comments are safe to ignore when reading this later. When executing this with demosh, things after the horizontal rule below (which is just before a commented @SHOW directive) will get displayed.

This workshop requires that you have a running Kubernetes cluster. The README is written assuming that you're using a local cluster that has ports exposed to the local network: you can use CREATE.md to set up a k3d cluster that will work well. If you want to use some other kind of cluster, make sure that the DNS is set up, and modify the DNS names to match for the rest of the instructions.


In this workshop, we will deploy Linkerd to a cluster, then demonstrate three different ingress controllers working with Linkerd:

All manifests used in the demo are in the /manifests directory, for some additional work after the workshop, check out the homework assignment in HOMEWORK.md.

First things first: make sure that everything is set up for the workshop.

#@$SHELL CREATE.md
#@$SHELL INSTALL-LINKERD.md
#@$SHELL INSTALL-EMOJIVOTO.md

OK, everything should be ready to go!

Emissary-ingress

We'll start with Emissary-ingress. Emissary is an open-source, Envoy-based, Kubernetes-native API gateway. It's a CNCF incubating project; read more about it at https://www.getambassador.io/products/api-gateway, or check out its source at https://github.com/emissary-ingress/emissary.

The simplest way to install Emissary-ingress is to follow the quick start: https://www.getambassador.io/docs/emissary/latest/tutorials/getting-started. The instructions below are taken directly from that, except that we're setting replicaCount=1 to reduce the replice count from 3 to 1, to make things easier on the k3d cluster. (You wouldn't want to do this in production!)

First we'll get our Helm repo set up...

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

...then we can install Emissary's CRDs.

kubectl apply -f https://app.getambassador.io/yaml/emissary/3.9.1/emissary-crds.yaml

Installing the CRDs also installs the conversion webhook, so let's wait for that.

kubectl rollout status -n emissary-system deploy

Once that's running, we create Emissary's namespace, including Linkerd's auto-injection annotation, so that Emissary's Pods will automatically get brought into the Linkerd mesh.

kubectl create ns emissary
kubectl annotate ns emissary linkerd.io/inject=enabled

Then it's time to install Emissary itself:

helm install emissary-ingress --namespace emissary \
     datawire/emissary-ingress \
     --set replicaCount=1

Then we can wait for the deployments to be ready:

kubectl rollout status -n emissary deployments

Now that Emissary-ingress is installed, let's quickly configure it. Emissary is configured using its own CRDs: at minimum, it requires a Listener, a Host, and one or more Mappings to actually route traffic. We're not going to dig to far into these, but we'll take a quick look:

bat emissary-yaml/listeners-and-hosts.yaml
bat emissary-yaml/emojivoto-mapping.yaml

We can install these resources with kubectl apply...

kubectl apply -f emissary-yaml/listeners-and-hosts.yaml
kubectl apply -f emissary-yaml/emojivoto-mapping.yaml

...and Emissary should be happy to route requests for us now.

If we look at the Linkerd Viz dashboard, we can see that Emissary is meshed, and that it's talking to Emojivoto's web service.

linkerd viz dashboard

OK! Let's clean up Emissary-ingress to get ready for NGINX. First, we'll delete the Service so that nothing is competing for the port we need to use for NGINX.

kubectl delete svc -n emissary emissary-ingress

Then we'll summarily delete Emissary's namespaces.

kubectl delete ns emissary emissary-system

NGINX

Next up: NGINX, an open-source web server and API server that predates even Kubernetes. You can read more about it at https://nginx.com/; its source is at https://hg.nginx.org/nginx/.

We'll install NGINX using Helm, per the instructions at https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-helm/:

helm repo add nginx-stable https://helm.nginx.com/stable
helm repo update

We're modifying the instructions slightly to use an nginx namespace, which we've annotated for Linkerd injection.

kubectl create ns nginx
kubectl annotate ns nginx linkerd.io/inject=enabled
helm install nginx \
     -n nginx \
     nginx-stable/nginx-ingress

Once installed, let's make sure everything is running.

kubectl rollout status -n nginx deploy

For routing, NGINX uses an Ingress resource with the nginx IngressClass (which was just installed by Helm):

bat nginx-yaml/nginx-ingress.yaml

Applying it with kubectl apply should cause NGINX to route requests to Emojivoto.

kubectl apply -f nginx-yaml/nginx-ingress.yaml

Let's check that in the browser.

In the Linkerd Viz dashboard, we'll now see that NGINX is meshed, and that it's talking to Emojivoto's web service.

linkerd viz dashboard

OK! Let's clean up NGINX the same way we dealt with Emissary.

kubectl delete svc -n nginx nginx-nginx-ingress-controller
kubectl delete ns nginx

Envoy Gateway

Finally, let's take a quick look at Envoy Gateway, a new open-source project for managing Envoy Proxy as a standalone Kubernetes ingress controller, using the Gateway API. Read more about Envoy Gateway at https://gateway.envoyproxy.io/; its source is at https://github.com/envoyproxy/gateway.

We'll install Envoy Gateway using its quickstart, which you can find at https://gateway.envoyproxy.io/v0.6.0/user/quickstart.html:

kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v0.6.0/install.yaml
kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available

OK, we should be good to go!

Envoy Gateway uses the Gateway API's Gateway resource to define which port to listen on, etc., and HTTPRoute resources to define how requests will get routed. The interesting thing, though, is that when the Gateway resource is created or edited, Envoy Gateway will create a new Deployment, in the envoy-gateway-system namespace, for the actual Envoy Proxy itself. Since these Deployments are dynamic, we need to tell Linkerd to do automatic injection on the entire envoy-gateway-system namespace:

kubectl annotate ns envoy-gateway-system linkerd.io/inject=enabled

After doing that, we'll need to restart the running Envoy Gateway controller:

kubectl rollout restart -n envoy-gateway-system deployments
kubectl rollout status -n envoy-gateway-system deployments

OK! Now, finally, we can install the Gateway API resources needed to route to Emojivoto:

bat envoy-gateway-yaml/gateway.yaml
kubectl apply -f envoy-gateway-yaml/gateway.yaml

We should also wait for the Envoy Proxy deployment to be spun up:

kubectl rollout status -n envoy-gateway-system deployments

At this point, Envoy Gateway should be able to route to Emojivoto for us.

And, as always, the Linkerd Viz dashboard should show that Envoy Gateway is meshed, and that it's talking to Emojivoto's web service.

linkerd viz dashboard

So there you have it! Three separate ingress controllers, all working cleanly with Linkerd!

You can find the source for this workshop at

https://github.com/BuoyantIO/service-mesh-academy/tree/main/linkerd-and-ingress

and, as always, we welcome feedback. Join us at https://slack.linkerd.io/ for more.