Local Kubernetes with K3D and nginx-ingress

Some notes for running a local, multi-node Kubernetes cluster with k3d, and configuring it with nginx-ingress.

This is a useful approach to learn more about how the various components fit together, and to enable local testing without having to spin up a full blown Kubernetes cluster on a cloud provider.

Configure and Run K3d

Create a config file, k3d-conf.yaml.

Notable parts:

  • ports: this will configure the provided nginx loadbalancer to be available on localhost port 8080
  • k3s extraArgs: this will prevent the default svc loadbalancer being deployed to the nodes
apiVersion: k3d.io/v1alpha4
kind: Simple
metadata:
  name: mycluster
image: rancher/k3s:v1.26.0-k3s2
agents: 3
ports:
  - port: 8080:80 # same as '--port 8080:80@loadbalancer'
    nodeFilters:
      - loadbalancer
options:
  k3s:
    extraArgs:
      - arg: --disable=traefik
        nodeFilters:
          - server:*

Then start up the cluster with:

k3d cluster create --config k3d-conf.yaml

Once started, inspecting the pods should show something like the following (note a lack of any traefik loadbalancers as we disabled them):

Install Nginx-ingress

Once the K3d cluster is up and running, install and deploy ingress-nginx via helm:

helm upgrade --install ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx --namespace ingress-nginx --create-namespace

Once installed, inspecting the pods and services should show something like this:

The svclb-ingress-nginx-controller-* pods are created by K3s via a Service controller in reaction to the creation of the ingress-nginx-controller service.

Deploy a Workload

At this point a workload can be deployed, via a Deployment, Service and Ingress.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
      environment: test
  minReadySeconds: 5
  template:
    metadata:
      labels:
        app: nginx
        environment: test
    spec:
      containers:
      - name: nginx
        image: nginx:1.17
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
    environment: test
  type: ClusterIP
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
spec:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx-service
                port:
                  number: 80

Lastly, navigate to http://localhost:8080 to ensure everything is working:

Resources