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, the following ingress controllers are known to work:

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

Ambassador

Ambassador will be installed with the help of the Ambassador operator.

First install the CRDs with

  1. kubectl apply -f https://github.com/datawire/ambassador-operator/releases/latest/download/ambassador-operator-crds.yaml

Now install the kind-specific manifest for installing Ambassador with the operator in the ambassador namespace:

  1. kubectl apply -n ambassador -f https://github.com/datawire/ambassador-operator/releases/latest/download/ambassador-operator-kind.yaml
  2. kubectl wait --timeout=180s -n ambassador --for=condition=deployed ambassadorinstallations/ambassador

Ambassador is now ready for use. You can try the example in Using Ingress at this moment, but Ambassador will not automatically load the Ingress defined there. Ingress resources must include the annotation kubernetes.io/ingress.class: ambassador for being recognized by Ambassador (otherwise they are just ignored). So once the example has been loaded you can add this annotation with:

  1. kubectl annotate ingress example-ingress kubernetes.io/ingress.class=ambassador

Ambassador should be exposing your Ingress now. Please find additional documentation on Ambassador here.

Contour

Deploy Contour components.

  1. kubectl apply -f https://projectcontour.io/quickstart/contour.yaml

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

  1. {
  2. "spec": {
  3. "template": {
  4. "spec": {
  5. "nodeSelector": {
  6. "ingress-ready": "true"
  7. },
  8. "tolerations": [
  9. {
  10. "key": "node-role.kubernetes.io/master",
  11. "operator": "Equal",
  12. "effect": "NoSchedule"
  13. }
  14. ]
  15. }
  16. }
  17. }
  18. }

Apply it by running:

  1. kubectl patch daemonsets -n projectcontour envoy -p '{"spec":{"template":{"spec":{"nodeSelector":{"ingress-ready":"true"},"tolerations":[{"key":"node-role.kubernetes.io/master","operator":"Equal","effect":"NoSchedule"}]}}}}'

Now the Contour is all setup to be used. Refer to Using Ingress for a basic example usage.

Additional information about Contour can be found at: projectcontour.io

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.

  1. kind: Pod
  2. apiVersion: v1
  3. metadata:
  4. name: foo-app
  5. labels:
  6. app: foo
  7. spec:
  8. containers:
  9. - name: foo-app
  10. image: hashicorp/http-echo:0.2.3
  11. args:
  12. - "-text=foo"
  13. ---
  14. kind: Service
  15. apiVersion: v1
  16. metadata:
  17. name: foo-service
  18. spec:
  19. selector:
  20. app: foo
  21. ports:
  22. # Default port used by the image
  23. - port: 5678
  24. ---
  25. kind: Pod
  26. apiVersion: v1
  27. metadata:
  28. name: bar-app
  29. labels:
  30. app: bar
  31. spec:
  32. containers:
  33. - name: bar-app
  34. image: hashicorp/http-echo:0.2.3
  35. args:
  36. - "-text=bar"
  37. ---
  38. kind: Service
  39. apiVersion: v1
  40. metadata:
  41. name: bar-service
  42. spec:
  43. selector:
  44. app: bar
  45. ports:
  46. # Default port used by the image
  47. - port: 5678
  48. ---
  49. apiVersion: networking.k8s.io/v1
  50. kind: Ingress
  51. metadata:
  52. name: example-ingress
  53. spec:
  54. rules:
  55. - http:
  56. paths:
  57. - pathType: Prefix
  58. path: "/foo"
  59. backend:
  60. service:
  61. name: foo-service
  62. port:
  63. number: 5678
  64. - pathType: Prefix
  65. path: "/bar"
  66. backend:
  67. service:
  68. name: bar-service
  69. port:
  70. number: 5678
  71. ---

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"
  2. curl localhost/foo
  3. # should output "bar"
  4. curl localhost/bar