Install a Kubernetes Ingress

November 23, 2024 note-to-self k8s

This is for my own understanding. It might be wrong but reflects my current understanding.

Install an Ingress controller

Create a Cluster

(using kind)

cat <<EOF | kind create cluster --name kind-ingress --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
    extraPortMappings:
    - containerPort: 80
      hostPort: 80
      protocol: TCP
    - containerPort: 443
      hostPort: 443
      protocol: TCP
EOF

This setup maps ports 80 and 443 from localhost to the ingress. It's like having to map ports in virtual box, back when that was a thing.


Install the nginx Ingress Controller

Apply the official nginx ingress manifest from Kubernetes:

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

That deployment configures the controller. If you look at the URL, it's specific to kind. There are versions for cloud providers, too.


3. Verify

kubectl get pods -n ingress-nginx

You should an ingress-nginx-controller pod in the Running state.


4. Create the ingress Resource

So, we have the cluster and ingress installed. This is akin to having a server and nginx or apache set up, but no app behind it. So, if you loaded the URL, you'd only get a stock/default page. We need an app for it to refer to, and set up the routing since the files won't be on the same machine as the server.

This is just some standard hello-world sample image:

kubectl create deployment hello-world --image=gcr.io/google-samples/hello-app:1.0
kubectl expose deployment hello-world --port=8080

Example Ingress YAML:

cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-world-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: "hello-world.local"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: hello-world
            port:
              number: 8080
EOF

5. Test

Add an entry to your /etc/hosts file so your local machine routes traffic to the kind cluster:

sudo echo "127.0.0.1 hello-world.local" >> /etc/hosts

Now, you can access the service:

curl http://hello-world.local

Add TLS support


1. Generate TLS Certificates

To test with TLS, a self-signed certificate is needed. For production, you would use something like Let's Encrypt.

Generate a TLS certificate and key locally:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt \
  -subj "/CN=hello-world.local/O=hello-world"

Apply the certificate to the cluster as a secret:

kubectl create secret tls hello-world-tls \
  --cert=tls.crt --key=tls.key

2. Update the Ingress Resource

The configuration needs to be updated to reflect the secret.

Updated Ingress YAML:

cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-world-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
  - hosts:
    - hello-world.local
    secretName: hello-world-tls  # TLS secret created earlier
  rules:
  - host: hello-world.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: hello-world
            port:
              number: 8080
EOF

3. Verify

Apply the updated Ingress resource:

kubectl apply -f hello-world-ingress.yaml

Check the status of the Ingress:

kubectl describe ingress hello-world-ingress

4. Test as https

Your /etc/hosts should already have the entry for hello-world.local but if not, add it.

Now, access the service via HTTPS (the --insecure hides the self-signed security warning):

curl --insecure https://hello-world.local