Local kubernetes cluster with ingress

January 29, 2022

For a local cluster, I stopped using Minikube and now only use KinD (Kubernetes in Docker), that use docker containers as kubernetes nodes.

To install, just have a look here

Customize KinD to have Ingress

You can choose to start you KinD cluster with a simple: kind create cluster, but it is getting interesting to give it some custom YAML config in order to connect your localhost to the cluster (official documentation)

# kind-local.yaml
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: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP

Start a local cluster with the config:

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

Ingress

You now can apply the ingress files to your cluster:

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

# To wait for the creation to finish:
kubectl wait --namespace ingress-nginx --for=condition=complete job --selector=app.kubernetes.io/component=admission-webhook --timeout=120s
kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=120s

Once it is done, it should be easy to access it from your localhost.

Here is a simple app I use to test if it is working:

# Apply it with saving this a file and run `kubectl apply -f my-test-pod.yaml`
---
kind: Pod
apiVersion: v1
metadata:
  name: test-app
  labels:
    app: test-app
spec:
  containers:
  - name: test-app
    image: hashicorp/http-echo:0.2.3
    args:
    - "-text=Hello World!"
---
kind: Service
apiVersion: v1
metadata:
  name: test-service
spec:
  selector:
    app: test-app
  ports:
  - port: 5678
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
spec:
  rules:
  - http:
      paths:
      - pathType: Prefix
        path: "/test-app"
        backend:
          service:
            name: test-service
            port:
              number: 5678
---

You should now be able to reach it with using your browser: http://127.0.0.1.nip.io/test-app. The ingress will notice the endpoint and redirect you to the corresponding service.

And here you are! Now you can test your applications deployments with a local URL, without using production/staging/any cluster and without having to add a custom entry to /etc/hosts.

A bit more about the 127.0.0.1.nip.io magic on their website: https://nip.io/, or with other DNS:

"nip.io maps <anything>[.-]<IP Address>.nip.io in "dot", "dash" or "hexadecimal" notation to the corresponding <IP Address>"

Pretty useful :)

Bash script to tie everything together

And here is a full script to automatically run the steps above:

#!/bin/bash
echo -e '\n[BOOSTRAPING CLUSTER]\n'
kind create cluster --config=cluster-kind.yaml

echo -e '\n[Ingress]\n'
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
echo "› Waiting for Ingress to be ready..."
kubectl wait --namespace ingress-nginx --for=condition=complete job --selector=app.kubernetes.io/component=admission-webhook --timeout=120s
kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=120s
echo "› Done!"

Deletion

kind delete cluster will clean your entire cluster (therefore the bash script is quite useful to recreate the cluster with the ingress).