Ingress

This guide covers setting up ingress on a kind cluster.

Setting Up An Ingress Controller

We can leverage KIND’s extraPortMapping config option when creating a cluster to forward ports from the host to an ingress controller running on a node.

We can also setup a custom node label by using node-labels in the kubeadm InitConfiguration, to be used by the ingress controller nodeSelector.

  1. Create a cluster
  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 blixit to test Gateway API with kind https://github.com/kubernetes-sigs/blixt#usage

Create Cluster

Create a kind cluster with extraPortMappings and node-labels.

  • extraPortMappings allow the local host to make requests to the Ingress controller over ports 80/443
  • node-labels only allow the ingress controller to run on a specific node(s) matching the label selector
  1. cat <<EOF | kind create cluster --config=-
  2. kind: Cluster
  3. apiVersion: kind.x-k8s.io/v1alpha4
  4. nodes:
  5. - role: control-plane
  6. kubeadmConfigPatches:
  7. - |
  8. kind: InitConfiguration
  9. nodeRegistration:
  10. kubeletExtraArgs:
  11. node-labels: "ingress-ready=true"
  12. extraPortMappings:
  13. - containerPort: 80
  14. hostPort: 80
  15. protocol: TCP
  16. - containerPort: 443
  17. hostPort: 443
  18. protocol: TCP
  19. EOF

Ingress NGINX

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

The manifests contains kind specific patches to forward the hostPorts to the ingress controller, set taint tolerations and schedule it to the custom labelled node.

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

  1. kubectl wait --namespace ingress-nginx \
  2. --for=condition=ready pod \
  3. --selector=app.kubernetes.io/component=controller \
  4. --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.

Note, this example uses an nginx-specific Ingress annotation which may not be supported by all Ingress implementations.

  1. kind: Pod
  2. apiVersion: v1
  3. metadata:
  4. name: foo-app
  5. labels:
  6. app: foo
  7. spec:
  8. containers:
  9. - command:
  10. - /agnhost
  11. - netexec
  12. - --http-port
  13. - "8080"
  14. image: registry.k8s.io/e2e-test-images/agnhost:2.39
  15. name: foo-app
  16. ---
  17. kind: Service
  18. apiVersion: v1
  19. metadata:
  20. name: foo-service
  21. spec:
  22. selector:
  23. app: foo
  24. ports:
  25. # Default port used by the image
  26. - port: 8080
  27. ---
  28. kind: Pod
  29. apiVersion: v1
  30. metadata:
  31. name: bar-app
  32. labels:
  33. app: bar
  34. spec:
  35. containers:
  36. - command:
  37. - /agnhost
  38. - netexec
  39. - --http-port
  40. - "8080"
  41. image: registry.k8s.io/e2e-test-images/agnhost:2.39
  42. name: bar-app
  43. ---
  44. kind: Service
  45. apiVersion: v1
  46. metadata:
  47. name: bar-service
  48. spec:
  49. selector:
  50. app: bar
  51. ports:
  52. # Default port used by the image
  53. - port: 8080
  54. ---
  55. apiVersion: networking.k8s.io/v1
  56. kind: Ingress
  57. metadata:
  58. name: example-ingress
  59. annotations:
  60. nginx.ingress.kubernetes.io/rewrite-target: /$2
  61. spec:
  62. rules:
  63. - http:
  64. paths:
  65. - pathType: Prefix
  66. path: /foo(/|$)(.*)
  67. backend:
  68. service:
  69. name: foo-service
  70. port:
  71. number: 8080
  72. - pathType: Prefix
  73. path: /bar(/|$)(.*)
  74. backend:
  75. service:
  76. name: bar-service
  77. port:
  78. number: 8080
  79. ---

Apply the contents

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

Now verify that the ingress works

  1. # should output "foo-app"
  2. curl localhost/foo/hostname
  3. # should output "bar-app"
  4. curl localhost/bar/hostname