Kubernetes Developer Workshop

🌎 Helm & Ingress

🔥 At this point in the workshop you have a choice:

Only go through one of these two sections, not both!


For this section we'll touch on two slightly more advanced topics, these being the use of Helm and introducing an ingress controller to our cluster. The ingress will let us further refine & improve the networking aspects of the app we've deployed.

🗃️ Namespaces

So far we've worked in a single Namespace called default, but Kubernetes allows you create additional Namespaces in order to logically group and separate your resources.

Namespaces do not provide any form of network boundary or isolation of workloads, and the underlying resources (Nodes) remain shared. There are ways to achieve higher degress of isolation, but it is a matter well beyond the scope of this workshop.

Create a new namespace called ingress:

kubectl create namespace ingress

Namespaces are simple idea but they can trip you up, you will have to add --namespace or -n to any kubectl commands you want to use against a particular namespace. The following alias can be helpful to set a namespace as the default for all kubectl commands, meaning you don't need to add -n, think of it like a Kubernetes equivalent of the cd command.

# Note the space at the end
alias kubens='kubectl config set-context --current --namespace '

🪖 Introduction to Helm

Helm is an CNCF project which can be used to greatly simplify deploying applications to Kubernetes, either applications written and developed in house, or external 3rd party software & tools.

We'll add the Helm chart repository for the ingress we will be deploying, this is done with the helm repo command. This is a public repo & chart of the extremely popular NGINX ingress controller (more on that below).

The repo name ingress-nginx can be any name you wish to pick, but the URL has to be pointing to the correct place.

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

helm repo update

🚀 Ingress & Ingress Controller

An Ingress is a Kubernetes resource that manages external HTTP(S) access to services within a cluster. It provides routing rules to manage how requests are directed to various services based on the request's host or path. An Ingress Controller is a reverse proxy that implements the rules defined in Ingress resources, handling the actual routing of traffic.

📚 Kubernetes Docs: Ingress
📚 Kubernetes Docs: Ingress Controllers

Ingress controller diagram showing routing of traffic to backend services

Helm greatly simplifies deploying the NGINX ingress controller, down to a single command:

helm install my-ingress ingress-nginx/ingress-nginx \
  --namespace ingress \
  --set controller.replicaCount=2

Check the status of both the pods and services with kubectl get svc,pods --namespace ingress, ensure the pods are running and the service has an external public IP.

You can also use the helm CLI to query the status, here's some simple and common commands:

🔀 Reconfiguring The App With Ingress

Now we can modify the app we've deployed to route through our new ingress controller, but a few simple changes are required first. As the ingress controller will be fronting all requests, the services in front of the deployments should be switched back to internal i.e. ClusterIP.

Apply these three changes with kubectl and now the app will be temporarily unavailable. Note, if you have changed namespace with kubens you should switch back to the default namespace before running the apply!

If run kubectl get svc you should see both services are now of type ClusterIP and have no external IP associated.

The next thing is to configure the ingress by creating an Ingress resource. This can be a fairly complex resource to set-up, but it boils down to a set of HTTP path mappings (routes) and which backend Service should serve them. Here is the completed manifest file ingress.yaml:

Click here for the Ingress YAML
apiVersion: networking.k8s.io/v1
kind: Ingress

metadata:
  name: nanomon
  labels:
    name: nanomon

spec:
  # Important we leave this blank, as we don't have DNS configured
  # Blank means these rules will match ALL HTTP requests hitting the controller IP
  host:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          # Routing for the frontend
          - pathType: Prefix
            path: "/"
            backend:
              service:
                name: frontend
                port:
                  number: 80

          # Routing for the API
          - pathType: Prefix
            path: "/api"
            backend:
              service:
                name: api
                port:
                  number: 80

Apply the same as before with kubectl, validate the status with:

kubectl get ingress

It may take it a minute for it to be assigned an address, note the address will be the same as the external IP of the ingress-controller. You can check this with:

kubectl get svc -n ingress | grep LoadBalancer

Visit this IP in your browser, if you check the "About" screen and click the "More Details" link it should take you to the API, which should now be served from the same IP as the frontend.

🖼️ Cluster & Architecture Diagram

We've reached the final state of the application deployment, yes I promise this time! The resources deployed into the cluster & in Azure at this stage can be visualized as follows. This is a slightly simplified version from previously in order to fit everything in, so things like the Deployment resources have been omitted

architecture diagram

Note the addition of the ingress controller Deployment and Service in the ingress namespace, and the Ingress resource alongside the other resources in the default namespace.

🎉 Completion!

Congratulations, you've reached the end of the workshop! You should now have a pretty good understanding of the core concepts of Kubernetes, and have deployed a simple but complete application into a real cluster.