Month: June 2021

Adding Ingress to Your Multi-Node Kind Cluster

In my last post about Kubernetes I went through how to set up a Kind (Kubernetes in Docker) cluster on your Windows desktop. In this post I’ll show you how to add an nginx ingress controller to your cluster and do a quick demo of it working,

To get started there are a couple of pre-requisites you’ll need to have.

  1. kubectl – Kubenetes command line interface
  2. Docker Desktop – We’ll be running our cluster as a group of containers in Docker.
  3. Kind – Kind makes it easy to manage Kubernetes clusters on you desktop.

I went through the steps to get the pre-requisites set up in my previous post, so I’ll just put the chocolatey commands here in case you need them, but if you need more guidance on how to set up the pre-requisites please see the previous post: Running a Multi-Node Kubernetes Cluster on Windows with Kind.

choco install docker-desktop
choco install kubernetes-cli
choco install kind

In this post I’ll be working with the latest version of Kind (0.11.1). If you installed Kind previously using Chocolatey you can quickly upgrade with the following command.

choco upgrade kind --version=0.11.1

The first thing we’ll need to do is add a bit more to our configuration file (lines 6-18) for our Kind cluster so we can map the ports from our cluster to our local machine. (Note you can get all of the files in this post from GitHub. The yaml files are in the Kind.0.11.1 directory.)

# Four node (three workers) cluster config
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
  extraPortMappings:
  - containerPort: 80
    hostPort: 8080
    protocol: TCP
  - containerPort: 443
    hostPort: 4443
    protocol: TCP
- role: worker
- role: worker
- role: worker

To get our cluster up and running we simply run the following kind command pointing to our new configuration file.

kind create cluster --config=cluster-config.yaml

Now to deploy the ingress controller. There is a configuration file in the repository for kubernetes/ingress-nginx. You can apply this using the following command:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/kind/deploy.yaml  

Caution: These files have a habit of changing often as Kubernetes evolves, so what works today with a particular version of Kubernetes may not work tomorrow with the same version of Kubernetes because the file at that URL may have changed and no longer be compatible (or it may just be broken). I have copied the version of the file I am using with my cluster into my repository as ingress-nginx.yaml so that if (when) this happens there will be a working copy available for these instructions.

It will likely only take a few seconds for the command to complete, but it may take a minute or two for everything to actually complete inside the cluster and be ready to use. You can verify that everything is ready by running the following:

kubectl wait --for=condition=Ready pod -l app.kubernetes.io/component=controller -n ingress-nginx --timeout=300s
kubectl wait --for=condition=Complete job -l app.kubernetes.io/component=admission-webhook -n ingress-nginx --timeout=300s

This will wait until everything is in the proper state before returning.

Now that everything is set up let’s test it out by deploying an nginx pod, a service, and an ingress and verifying that we can indeed reach our running pod via the ingress. The following will create a pod from the nginx docker image, create a service to expose it and an ingress to allow us to connect to it from our local machine. Here’s the yaml for that:

apiVersion: v1
kind: Pod
metadata:
  name: ninja-web-pod
  labels:
    role: webserver
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: ninja-svc
spec:
  selector:
    role: webserver
  ports:
    - protocol: TCP
      port: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ninja-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: ninja.k8s.local
      http:
        paths:
          - backend:
              service:
                name: ninja-svc
                port:
                  number: 80
            path: /
            pathType: Prefix
            

Deploy the application using kubectl:

kubectl apply -f test-deploy.yaml

Note that I am specifying the host name ninja.k8s.local for my ingress. In order to use that host name we’ll also want to add a host file entry mapping it to your local machine.

127.0.0.1  ninja.k8s.local

And with that we should be able to access our pod @ http://ninja.k8s.local:8080/ and see the default nginx page served up.