Kubernetes – Routing Services with Ingress

Kubernetes Ingress simplifies the routing of our external traffic (http & https) to our internal services. It can handle traffics from multiple domains for us.

Ingress supports implementations from multiple vendors such as NGNix, Kong, HAProxy, Ambassador and many others. They add many useful features to manage the communication with the outside world. They include features like static page caching, TLS termination, size compression, session affinity etc.

The Ingress module mainly consists of an Ingress API object that defines the requirements. And, an Ingress controller that fulfills the Ingress.

How does it simplify routing ?

Suppose we have two domains for two of our applications as shown.

Ingress lets us develop our features as separate services. For publishing, we can simply keep adding our services (service IP and port ) against the desired url paths as shown. And, its that simple! The Ingress controller is capable handling the rest for us.

How does the controller handle the Ingress routing request ?

To make the traffics from both the domains reach the Ingress Host, we can assign both the domains as host names to our Ingress Host IP. It is know as virtual hosting.

As the traffic from both the domains hit Ingress host, the Ingress controller would read the destination url in the request header. Based on the traffic routing rules, it would rout our requests to appropriate K8s services.

What other benefits do we get out of this routing feature ?

First, it separates the design of our back-end services from the our desired presentation. The reward feature and the beta version, as shown, even being deployed separately, are exposed under the same game app. It’s as if they are deployed together.

Second, it lets us share our Layer 4 Load Balancers for multiple services. A load balancer can manage the apps and expose them as internal services on different ports. Ingress can expose these services to outside, on the desired domains and url paths.

A sample Ingress object

The Ingress object shows the routing rules for the above example. A couple of path has been removed to keep it short.

The annotation under the metadata specifies the Ingress controller to be used. Here, we have used – nginx.ingress.kubernetes.io . The ngnix supports to import different features separately. ‘rewrite-target’ is one such feature.

As we can deploy multiple Ingress Controllers, it is important to specify this to point to the correct one.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
  name: ingress-routing-example
    nginx.ingress.kubernetes.io/rewrite-target: /
  - host: fungames.com
      - path: /
          serviceName: service-G1
          servicePort: 80
      - path: /reward
          serviceName: service-G2
          servicePort: 8080
  - host: prettygifts.com
      - path: /shop
          serviceName: service-P1
          servicePort: 8090
  - http:
      - path: /
          serviceName: service-D
          servicePort: 8090
Secure a Service using TLS termination

This is another feature supported by Ingress. Using TLS termination, we can create a secured tls channel between the client and the Ingress load balancer.

The ingress and the secret API object shows the configuration for the TLS termination. The highlighted lines tell the host-name to secure and the secret to use. The keys tls.crt and tls.key in the secret are the certificate and private key for tls communication.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
  name: ingress-tls-demo
  namespace: my-prortal
  - hosts:
      - ssl.demoservice.com
    secretName: tls-secret
  - host: ssl.demoservice.com
      - path: /cart
          serviceName: cart-service
          servicePort: 8080 
apiVersion: v1
kind: Secret
  name: tls-secret
  namespace: my-prortal
  tls.crt: [base64 encoded cert]
  tls.key: [base64 encoded key]
type: kubernetes.io/tls
Demo : How to expose a K8s Services using Ingress.

As we discussed above, its as simple as adding routing rule to our service. We will try this out using a simple hello-app application from google-samples.

Step 1: Deploy Ingress Controller

This maps the url to our service as per the mappings in the Ingress object.

Ingress controllers are not started by default, we need to start it on our cluster. Use the below command to enable and verify it on a minikube.

$ minikube addons enable ingress
* The 'ingress' addon is enabled

$ kubectl get pods -n kube-system | grep ingress
nginx-ingress-controller-6fc5bcc8c9-4ztcn   1/1     Running   0          2m36s
Step 2: Deploy the services on a NodePort and ensure its accessible

As we will map this service, we will ensure its working.

Follow the steps under these two tabs to deploy and verify the service.

$ kubectl create deployment hello --image=gcr.io/google-samples/hello-app:1.0
deployment.apps/hello created

$ kubectl expose deployment hello --type=NodePort --port=8080
service/hello exposed
$ kubectl get service hello
hello NodePort   <none>        8080:32321/TCP   78s

//Easy way to get the url
$ minikube service hello --url

//Verify if the service is working 
$ curl $(minikube service hello --url)
Hello, world!
Version: 1.0.0
Hostname: web-557f59c6cf-rt9cv
Step 3: Create host name for our minikube

We are creating a host name that hits our ingress controller deployed on minikube.

Check our minikube ip and add a host name to /etc/hosts as shown.

$ minikube ip

//Add this entry to /etc/hosts greetings.org
Step 4: Create the Ingress Object, add the routing rule and deploy

We will add a mapping for our service to expose it on a desired url.


apiVersion: networking.k8s.io/v1beta1 # for versions before 1.14 use extensions/v1beta1
kind: Ingress
  name: example-ingress
    nginx.ingress.kubernetes.io/rewrite-target: /$1
   - host: greetings.org
       - path: /say-hello
           serviceName: hello
           servicePort: 8080

We have configured to access our hello app at http://greetings.org/say-hello.

Let us deploy using ‘apply’ command and verify :

$ kubectl apply -f ingress.yaml
ingress.networking.k8s.io/example-ingress created

$ kubectl get ingresses
NAME              HOSTS           ADDRESS       PORTS   AGE
example-ingress   greetings.org   80      3m36s

$ kubectl describe ingresses example-ingress |head -20
Name:             example-ingress
Namespace:        default
Default backend:  default-http-backend:80 (<none>)
  Host           Path  Backends
  ----           ----  --------
                 /say-hello   hello:8080 (

We can verify our rules as well as the Host address where the Ingress is deployed as highlighted.

Step 6 – Lets verify if we are able access our app on our rout path

Time to test our Ingress Routing!

$ curl greetings.org/say-hello
Hello, world!
Version: 1.0.0
Hostname: hello-6649fc6cf7-tnhcn

Our routing is working ! We are able to access our service on our configured path.


Sitting at the edge server the Ingress can manage lot of features required as part of our communication with the outside world.

The major one being the Ingress (HTTP & HTTPS) traffic routing. This feature allows us to build applications using simpler services. It enables us to share our load balancers between multiple services. In simple terms, it provides the flexibility to expose any of our service on any url path available.

We can use the Ingress Controllers from multiple vendors. As a reverse proxy they provide many features for managing traffic. The features include TLS routing, session affinity, static page caching, Denial of Service, size compression etc.