Practical Guide to implement ingress-nginx Ingress Controller in an enterprise
As mentioned in kubernetes.io documentation, Ingress exposes HTTP and HTTPS routes from outside of the cluster to services within the cluster. Traffic routing is controlled by the rules defined on the Ingress resource. An Ingress may be configured to give services externally reachable URLs, load balance traffic, terminate SSL / TLS, and offer name-based virtual hosting.
An Ingress controller is responsible for fulfilling the Ingress, usually with a load balancer.
In this article, we will go over how to expose a SPA (Single Page Application) via Https within an enterprise as an intranet application. SPA application typically has a front-end application that is supported by an application to provide access to data and services such as authentication and authorization. This article assumes that the reader has some level of understanding on Kubernetes that includes Kubernetes objects and Kubectl commands.
Please refer this link to get an understanding on Kubernetes objects: https://kubernetes.io/docs/tasks/manage-kubernetes-objects/
Kubectl cheat sheet can be found at: https://kubernetes.io/docs/reference/kubectl/cheatsheet/
Assume that the front-end app name: XYZ-Web and API app: XYZ-API, are deployed in a Kubernetes cluster. Our goal is to make these apps accessible outside of the Kubernetes cluster. Via Https.
This following diagram illustrates the communication between the client (browser) and Kubernetes cluster:
This article assumes that both web and API containers are listening on port:9443 for HTTPS service. Typically, in an enterprise, HTTPS is used. So, we will keep HTTPS in the scope for this article.
As per the above diagram, both UI and API PODs are front ended by ClusterIP services that expose the PODs to other objects within the cluster.
Create an Ingress Controller
We need to have an Ingress controller to satisfy an Ingress. In this article, we will use ingress-nginx, created and maintained by Kubernetes community and Azure Kubernetes cluster.
There are various Ingress Controllers available in the market. Please refer to this link: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers
Differences between various flavors of Nginx ingress controllers available in the market can be found at: https://github.com/nginxinc/kubernetes-ingress/blob/master/docs/nginx-ingress-controllers.md
Deployment descriptors to create ingress-nginx can be found at: https://kubernetes.github.io/ingress-nginx/deploy/
For azure, we need to use the following deployment descriptor:
Following changes need to be made, at the minimum to align it with the target deployment environment:
Under load balancer service type (Refer controller-service.yaml section ), add the following annotations:
The above annotations are needed to use azure internal load balancer and the subnet, where load balancer resides.
Mention the internal load balancer IP.
DNS names such as xyz-web-nonprod.foo.com and xyz-api-nonprod.foo.com can be created, which points to this load balancer IP.
After making the above two changes, controller-service.yaml will look similar to as follows:
In some organizations, Kubernetes clusters won’t have the access to pull the images from the public repositories. In such case, Kubernetes admins of an organization or team will have to pull the image from a public repository, apply the any org specific configurations, scan it for any vulnerabilities using software such as Twistlock, and upload it in their internal repositories.
For example, refer to the following controller-deployment.yaml
In the above example, azure container registry, named xyznonprod is used. Please note that an Image Pull Secret:xyzsecret was mentioned in the above example.
Steps to create an image pull secret can be found at:
After making the changes mentioned above, ingress controller can be created by using the kubectl command:
kubectl apply -f deploy.yaml
Note:Deployment descriptor for the ingress-controllers is deploy.yaml in our example.
If the deployment is successful, following objects will be running under the chosen namespace, say ingress-nginx:
ingress-nginx-controller and ingress-nginx-controller-admission
Create an Ingress object
Ingress object deployment descriptor is trivial. Please add the following annotation:
nginx.ingress.kubernetes.io/backend-protocol: “HTTPS” to allow HTTPS traffic only.
Note, the TLS secret: xyznonprod is mentioned, which is used to secure the ingress. TLS secret can be created using the following command:
kubectl create secret tls xyznonprod \
— namespace ingress-basic \
— key xyz-ingress-tls.key \
— cert xyz-ingress-tls.crt
xyz-ingress-tls.key is the private key that can be created using the following command:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-out xyz-ingress-tls.crt \
-keyout xyz-ingress-tls.key \
-subj “/CN=xyz-web-nonprod.foo.com/O= xyznonprod “
xyz-ingress-tls.crt is a self-signed or trusted, signed certificate through a provider or your own certificate authority (CA). Some organizations allow self-signed certificates in the non-prod environment.
If Kubernetes is new to your team or org, and app is a simple app, it may be a good idea to start with an ingress controller such as ingress-nginx to enable Https. As you get comfortable with Kubernetes or your app gets more complex, say more than 6 PODS are running in your Kubernetes cluster, you may consider using service mesh such as Istio or Linkerd. Deployments of kubernetes objects using Helm charts can be also considered once you get familiar with Kubernetes.