Journey into Kubernetes - Ingress

·

5 min read

The last step in our cluster creation process -- creating an ingress controller. Let's talk about what that is.

Ingress means "going in". In the K8s scenario, this means traffic going into the cluster. Egress, the anytonym of ingress, means going out. That would be the traffic leaving the cluster such the service sending data out from inside the cluster. An ingress controller (IC) is essentially a gateway into the cluster.

There are many different ICs to choose from, but we're going to focus on the K8s supported ingress-nginx project (not to be confused with nginx-ingress which is supported by the folks behind nginx). Both nginx ICs are good choices, and the nginx-supported one even has a 'plus' version you must pay for with some extra features. However, for our purposes, and quite honestly purposes of many production-bound projects, we're good with ingress-nginx.

You can visit the project website here.

On the site, you can visit the Deployment section -> Installation guide and click on Azure. You must run one command to install everything... but before you do that, we need to modify the installation file, because it doesn't include our SSL certificate. Go ahead and download the YAML file. You can either grab the linke from the official website, or just right-click here and Save As deploy.yaml.

The above YAML file is a master installer which will create a lot of artifacts in your cluster. It creates a namespace (we already did this step in the previous article, so nothing new will happen here), some ConfigMaps, a ServiceAccount, a ClusterRole and ClusterRoleBinding, some Roles and Services and of course a Deployment of a special version of nginx. There's a lot of stuff that's created but worry not! Our focus here is pretty narrow.

We must modify the nginx configuration to read our SSL certificate. The default nginx configuration which we get from the above installation does not include this important flag, so we must do it ourselves. Inside the downloaded YAML file, look for lines:

# Source: ingress-nginx/templates/controller-deployment.yaml
apiVersion: apps/v1
kind: Deployment

This is the deployment for the nginx ingress controller. If you scroll down a bit, you'll see where the container spec is defined and these lines:

args:
  - /nginx-ingress-controller
  ...

Go ahead and add this right after /nginx-ingress-controller

- --default-ssl-certificate=ingress-nginx/aks-ingress-tls

You should have this complete args:

args:
  - /nginx-ingress-controller
  - --default-ssl-certificate=ingress-nginx/aks-ingress-tls
  - --publish-service=ingress-nginx/ingress-nginx-controller
  - --election-id=ingress-controller-leader
  - --ingress-class=nginx
  - --configmap=ingress-nginx/ingress-nginx-controller
  - --validating-webhook=:8443
  - --validating-webhook-certificate=/usr/local/certificates/cert
  - --validating-webhook-key=/usr/local/certificates/key

Save the modified installation YAML and apply it

kubectl apply -f deploy.yaml

Halfway there! The ingress controller is created. One last step we need to take is to tell the ingress controller where to route the incoming traffic.

Inside your integration folder, create a new file; ingress.yml and put this inside:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-fancyapi
  namespace: integration
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:
  - hosts:
    - yourcooldomain.io
    secretName: aks-ingress-tls
  rules:
  - host: integration.yourcooldomain.io
    http:
      paths:
      - backend:
          serviceName: fancyapi-service
          servicePort: 80

There are a few new things here. First, we're adding an annotation. Annotations are metadata. In this case, we're attaching metadata required by the nginx ingress controller.

Next, in the spec map, we have tls and a list of hosts. I defined a made-up host and attached the secret we created in the previous article to it. For this to work however, you'll need to edit the A record of the domain first to point yourcooldomain.io to the IP address of the ingress controller, and second add a wildcard CNAME of *.yourcooldomain.io. (you are likely to need the . at the end there, as it's a standard) as well. Also, it's important that the host yourcooldomain.io is the same host you defined when creating your SSL certificate!

Both the A record and the wildcard CNAME need to point to the IP address of the ingress service. You can find this IP address via the following command:

kubectl get svc -n=ingress-nginx

External IP is what you're looking for. Assuming your IP is 1.2.3.4, here's an example of what your DNS records should look like:

DNS TypeHostnameIP Address
A Recordyourcooldomain.io1.2.3.4
CNAME*.yourcooldomain.io.1.2.3.4

Your domain address provider is likely to have instructions on how to set this up.

In the rules map, we have a list again, but only one item. Here, we're saying "hey when someone hits integration.yourcooldomain.io, I want them to go to the backend service fancyapi-service on port 80". When you create your production ingress file inside the production namespace, you will possible just have yourcooldomain.io without a subdomain, or maybe www.yourcooldomain.io or something.

Almost there! Go ahead and apply this config to the K8s cluster:

kubectl apply -f ingress.yml

If your domain provider has updated their DNS entries, you can visit https://integration.yourcooldomain.io and you should be warned by your browser that the SSL certificate cannot be trusted. Thankfully, you know you can trust it, because you created it! If you skip the warning in the browser, you should arrive at your service!

Congratulations! You now have a namespaced cluster with a running service, an ingress controller and integrated SSL certificate. This is the end of the series, but there are at least 3 more Kubernetes articles to come. They will build on the knowledge we've gained in this series.

Happy Kubernetesing!


Resources

Did you find this article valuable?

Support Paul K by becoming a sponsor. Any amount is appreciated!