General Kubernetes

Kubernetes: NGINX Ingress Controller on GKE

What is an ingress?

An Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint. With an Ingress, there is no need to create a bunch of Load Balancers or exposing each service on the Node. You can simply consolidate your routing rules into a single resource.

Ingress Options

There are many Ingress options, but I am going to focus on the community NGINX version.

What Network Layer is an Ingress configured?

Ingress configures a Layer 7 (Application Layer) HTTP load balancer for Services and provides the following:

  • TLS (Transport Layer Security)
  • Name-based virtual hosting 
  • Path-based routing
  • Custom rules

Install via Helm

I installed the Ingress controller in the itsmetommy namespace and set controller.scope.enabled=true & controller.scope.namespace=itsmetommy so that the controller only watches my namespace instead of the default all namespaces.

  • controller.scope.enabled — limit the scope of the ingress controller
  • controller.scope.namespace — namespace to watch for ingress
helm install stable/nginx-ingress \
  --namespace itsmetommy \
  --name nginx-ingress \
  --set rbac.create=true \
  --set controller.publishService.enabled=true \
  --set controller.scope.enabled=true \
  --set controller.scope.namespace=itsmetommy


kubectl get service nginx-ingress-controller -w
NAME                       TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                      AGE
nginx-ingress-controller   LoadBalancer   80:31082/TCP,443:32255/TCP   115s


Clone my kubernetes-ingress-nginx repo that has Ingress examples.

git clone


Create deployments.

  kubectl create deploy service1 --image=itsmetommy/helloworld
  kubectl create deploy service2 --image=itsmetommy/helloworld
  kubectl create deploy service3 --image=itsmetommy/helloworld
  kubectl create deploy circle --image=itsmetommy/shape-circle
  kubectl create deploy heart --image=itsmetommy/shape-heart
  kubectl create deploy infinity --image=itsmetommy/shape-infinity
  kubectl create deploy lock --image=itsmetommy/shape-lock
  kubectl create deploy moon --image=itsmetommy/shape-moon
  kubectl create deploy pac-man --image=itsmetommy/shape-pac-man
  kubectl create deploy space-invader --image=itsmetommy/shape-space-invader
  kubectl create deploy square --image=itsmetommy/shape-square
  kubectl create deploy star --image=itsmetommy/shape-star
  kubectl create deploy triangle --image=itsmetommy/shape-triangle
  kubectl create deploy yin-yang --image=itsmetommy/shape-yin-yang


Create services.

  kubectl expose deploy service1 --port=80 --type=NodePort
  kubectl expose deploy service2 --port=80 --type=NodePort
  kubectl expose deploy service3 --port=80 --type=NodePort
  kubectl expose deploy circle --port=80 --type=NodePort
  kubectl expose deploy heart --port=80 --type=NodePort
  kubectl expose deploy infinity --port=80 --type=NodePort
  kubectl expose deploy lock --port=80 --type=NodePort
  kubectl expose deploy moon --port=80 --type=NodePort
  kubectl expose deploy pac-man --port=80 --type=NodePort
  kubectl expose deploy space-invader --port=80 --type=NodePort
  kubectl expose deploy square --port=80 --type=NodePort
  kubectl expose deploy star --port=80 --type=NodePort
  kubectl expose deploy triangle --port=80 --type=NodePort
  kubectl expose deploy yin-yang --port=80 --type=NodePort

Ingress Examples

I’m not going to go over every example, but I will go over a few.

Example 1

kubectl apply -f ingress-example-01.yaml


kubectl get ing -w
NAME                 HOSTS   ADDRESS         PORTS   AGE
ingress-example-01   *   80      5m22s


kubectl describe ing ingress-example-01
Name:             ingress-example-01
Namespace:        itsmetommy
Default backend:  circle:80 (
  Host  Path  Backends
  ----  ----  --------
  *     *     circle:80 (
Annotations:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"":"nginx"},"name":"ingress-example-01","namespace":"itsmetommy"},"spec":{"backend":{"serviceName":"circle","servicePort":80}}}  nginx
  Type    Reason  Age                  From                      Message
  ----    ------  ----                 ----                      -------
  Normal  CREATE  5m53s                nginx-ingress-controller  Ingress itsmetommy/ingress-example-01
  Normal  UPDATE  5m20s                nginx-ingress-controller  Ingress itsmetommy/ingress-example-01
  Normal  CREATE  2m54s                nginx-ingress-controller  Ingress itsmetommy/ingress-example-01
  Normal  UPDATE  80s (x2 over 2m20s)  nginx-ingress-controller  Ingress itsmetommy/ingress-example-01

Test (use your IP).

You should see a red circle.

Clean up.

kubectl delete -f ingress-example-01.yaml

Example 2

kubectl apply -f ingress-example-03.yaml


kubectl get ing -w
NAME                 HOSTS   ADDRESS         PORTS   AGE
ingress-example-03   *   80      69s


kubectl describe ing ingress-example-03
Name:             ingress-example-03
Namespace:        itsmetommy
Default backend:  default-http-backend:80 (
  Host  Path  Backends
  ----  ----  --------
        /foo   service1:80 (<none>)
        /bar   service2:80 (<none>)
Annotations:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"":"nginx"},"name":"ingress-example-03","namespace":"itsmetommy"},"spec":{"rules":[{"http":{"paths":[{"backend":{"serviceName":"service1","servicePort":80},"path":"/foo"},{"backend":{"serviceName":"service2","servicePort":80},"path":"/bar"}]}}]}}  nginx
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  96s   nginx-ingress-controller  Ingress itsmetommy/ingress-example-03
  Normal  UPDATE  46s   nginx-ingress-controller  Ingress itsmetommy/ingress-example-03

Test (use your IP).

curl -kL

curl -kL

curl -kL
<head><title>404 Not Found</title></head>
<center><h1>404 Not Found</h1></center>

Clean up.

kubectl delete -f ingress-example-03.yaml

Example 3

If you’ve followed my External DNS and Cert Manager blogs, this Ingress example should create DNS entries, along with having a valid SSL Certificate if you are using an existing Certificate. If not, add the annotation letsencrypt to each Ingress to auto generate the SSL Certificate.

kubectl apply -f ingress-example-08.yaml


kubkubectl get ing -w
NAME                 HOSTS   ADDRESS         PORTS   AGE
ingress-example-08,, + 10 more...   80, 443   36s


kubectl describe ing ingress-example-08
Name:             ingress-example-08
Namespace:        itsmetommy
Default backend:  default-http-backend:80 (
  itsmetommy-io-tls terminates,,,,,,,,,,,,
  Host                         Path  Backends
  ----                         ----  --------
                                  service1:80 (<none>)
                                  service1:80 (<none>)
                                  circle:80 (<none>)
                                  heart:80 (<none>)
                                  infinity:80 (<none>)
                                  lock:80 (<none>)
                                  moon:80 (<none>)
                                  pac-man:80 (<none>)
                                  space-invader:80 (<none>)
                                  square:80 (<none>)
                                  star:80 (<none>)
                                  triangle:80 (<none>)
                                  yin-yang:80 (<none>)
Annotations:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"":"nginx"},"name":"ingress-example-08","namespace":"itsmetommy"},"spec":{"rules":[{"host":"","http":{"paths":[{"backend":{"serviceName":"service1","servicePort":80}}]}},{"host":"","http":{"paths":[{"backend":{"serviceName":"service1","servicePort":80}}]}},{"host":"","http":{"paths":[{"backend":{"serviceName":"circle","servicePort":80}}]}},{"host":"","http":{"paths":[{"backend":{"serviceName":"heart","servicePort":80}}]}},{"host":"","http":{"paths":[{"backend":{"serviceName":"infinity","servicePort":80}}]}},{"host":"","http":{"paths":[{"backend":{"serviceName":"lock","servicePort":80}}]}},{"host":"","http":{"paths":[{"backend":{"serviceName":"moon","servicePort":80}}]}},{"host":"","http":{"paths":[{"backend":{"serviceName":"pac-man","servicePort":80}}]}},{"host":"","http":{"paths":[{"backend":{"serviceName":"space-invader","servicePort":80}}]}},{"host":"","http":{"paths":[{"backend":{"serviceName":"square","servicePort":80}}]}},{"host":"","http":{"paths":[{"backend":{"serviceName":"star","servicePort":80}}]}},{"host":"","http":{"paths":[{"backend":{"serviceName":"triangle","servicePort":80}}]}},{"host":"","http":{"paths":[{"backend":{"serviceName":"yin-yang","servicePort":80}}]}}],"tls":[{"hosts":["","","","","","","","","","","","",""],"secretName":"itsmetommy-io-tls"}]}}  nginx
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  59s   nginx-ingress-controller  Ingress itsmetommy/ingress-example-08
  Normal  UPDATE  48s   nginx-ingress-controller  Ingress itsmetommy/ingress-example-08

Test (use your domain) — version may vary.

Hello World! 3.0.0

Hello World! 3.0.0







Space Invader




Yin Yang

Clean up

  kubectl delete deploy service1
  kubectl delete deploy service2
  kubectl delete deploy service3
  kubectl delete deploy circle
  kubectl delete deploy heart
  kubectl delete deploy infinity
  kubectl delete deploy lock
  kubectl delete deploy moon
  kubectl delete deploy pac-man
  kubectl delete deploy space-invader
  kubectl delete deploy square
  kubectl delete deploy star
  kubectl delete deploy triangle
  kubectl delete deploy yin-yang
  kubectl delete svc service1
  kubectl delete svc service2
  kubectl delete svc service3
  kubectl delete svc circle
  kubectl delete svc heart
  kubectl delete svc infinity
  kubectl delete svc lock
  kubectl delete svc moon
  kubectl delete svc pac-man
  kubectl delete svc space-invader
  kubectl delete svc square
  kubectl delete svc star
  kubectl delete svc triangle
  kubectl delete svc yin-yang
  kubectl delete ing ingress-example-08

Delete Helm chart.

helm delete --purge nginx-ingress

Now that you’ve learned how to create a single nginx ingress (Load Balancer) and point it to multiple backend services within the same domain and namespace, what if you want a single entry point for all your services across all namespaces for multiple domains?

I suggest you move to Istio. I ended up moving to Istio because of this reason, and it allows for better routing options through Gateway’s and VirtualService’s.


By Tommy Elmesewdy

DevOps Engineer