Ingress

This guide covers setting up ingress on a kind cluster.

Setting Up An Ingress Controller 🔗︎

Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster.

  1. Create a cluster: There are two primary methods to direct external traffic to Services inside the cluster:

    1. using a LoadBalancer.
    2. leverage KIND’s extraPortMapping config option when creating a cluster to forward ports from the host.
  2. Deploy an Ingress controller, we document Ingress NGINX here but other ingresses may work including Contour and Kong, you should follow their docs if you choose to use them.

NOTE: You may also want to consider using Gateway API instead of Ingress. Gateway API has an Ingress migration guide.

You can use blixt to test Gateway API with kind https://github.com/kubernetes-sigs/blixt#usage

Create Cluster 🔗︎

Option 1: LoadBalancer 🔗︎

Create a kind cluster and run Cloud Provider KIND to enable the loadbalancer controller which ingress-nginx will use through the loadbalancer API.

kind create cluster

Option 2: extraPortMapping 🔗︎

Create a single node kind cluster with extraPortMappings to allow the local host to make requests to the Ingress controller over ports 80/443.

cat <<EOF | kind create cluster --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

If you want to run with multiple nodes you must ensure that your ingress-controller is deployed on the same node where you have configured the PortMapping, in this example you can use a nodeSelector to specify the control-plane node name.

nodeSelector:
  kubernetes.io/hostname: "kind-control-plane"

Ingress NGINX 🔗︎

kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml

Now the Ingress is all setup. Wait until is ready to process requests running:

kubectl wait --namespace ingress-nginx \
  --for=condition=ready pod \
  --selector=app.kubernetes.io/component=controller \
  --timeout=90s

Refer Using Ingress for a basic example usage.

Using Ingress 🔗︎

The following example creates simple http-echo services and an Ingress object to route to these services.

kind: Pod
apiVersion: v1
metadata:
  name: foo-app
  labels:
    app: foo
spec:
  containers:
  - command:
    - /agnhost
    - serve-hostname
    - --http=true
    - --port=8080
    image: registry.k8s.io/e2e-test-images/agnhost:2.39
    name: foo-app
---
kind: Service
apiVersion: v1
metadata:
  name: foo-service
spec:
  selector:
    app: foo
  ports:
  # Default port used by the image
  - port: 8080
---
kind: Pod
apiVersion: v1
metadata:
  name: bar-app
  labels:
    app: bar
spec:
  containers:
  - command:
    - /agnhost
    - serve-hostname
    - --http=true
    - --port=8080
    image: registry.k8s.io/e2e-test-images/agnhost:2.39
    name: bar-app
---
kind: Service
apiVersion: v1
metadata:
  name: bar-service
spec:
  selector:
    app: bar
  ports:
  # Default port used by the image
  - port: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
  - http:
      paths:
      - pathType: Prefix
        path: /foo
        backend:
          service:
            name: foo-service
            port:
              number: 8080
      - pathType: Prefix
        path: /bar
        backend:
          service:
            name: bar-service
            port:
              number: 8080
---

Apply the contents

kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/usage.yaml

Now verify that the ingress works

Option 1: LoadBalancer 🔗︎

Check the External IP assigned to the Ingress controller by the LoadBalancer

kubectl -n ingress-nginx get services
NAME                                 TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.96.33.233   192.168.8.5   80:31753/TCP,443:30288/TCP   27d
ingress-nginx-controller-admission   ClusterIP      10.96.80.178   <none>        443/TCP                      27d
# get the loadalancer IP

LOADBALANCER_IP=$(kubectl get services \
   --namespace ingress-nginx \
   ingress-nginx-controller \
   --output jsonpath='{.status.loadBalancer.ingress[0].ip}')

# should output "foo-app"

curl ${LOADBALANCER_IP}/foo

# should output "bar-app"

curl ${LOADBALANCER_IP}/bar

Option 2: extraPortMapping 🔗︎

The Ingress controller ports will be exposed in your localhost address

# should output "foo-app"

curl localhost/foo

# should output "bar-app"

curl localhost/bar