If you are deploying an application on Kubernetes, and you probably want to access the application with www.<myapplication>.com
Imagine, you build the application into a Docker image and deploy it on the Kubernetes cluster as a pod in Deployment. Also, your application need a MongoDB database
So, you also want to deploy a
mongodb database as a pod and create a service of type
mongodb-clusterip-service to make it accessible to the MongoDB database.
apiVersion: v1 kind: Pod metadata: name: mongodb-pod labels: app: mongodb spec: containers: - name: mongodb-container image: mongo imagePullPolicy: IfNotPresent ports: - containerPort: 27017 protocol: TCP
apiVersion: v1 kind: Service metadata: name: mongodb-clusterip-service spec: type: ClusterIP ports: - targetPort: 27017 port: 80 selector: app: mongodb
// Create MongoDB pod and ClusterIP Service $ kubectl create -f mongodb-pod.yaml pod/mongodb-pod created $ kubectl create -f mongodb-clusterip-service.yaml service/mongodb-clusterip-service created // Check the MongoDB pod and Service $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES mongodb-pod 1/1 Running 0 10s 172.17.0.3 minikube <none> <none> $ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE mongodb-clusterip-service ClusterIP 10.99.96.212 <none> 80/TCP 6s
Now, your Mongo DB database is working inside the Kubernetes cluster. The dataBase, you probably want to only access in the Kubernetes Cluster.
However, your web application should be accessible to the outside world. To make the application accessible to the outside world, you need to create another type of service for
web application which is
NodePort and make the application available with the port on the nodes in the Kubernetes Cluster.
apiVersion: v1 kind: Pod metadata: name: web-pod labels: app: web-pod spec: containers: - name: web-pod-container image: jayjodev/k8s-app-db:latest ports: - containerPort: 4000 protocol: TCP
apiVersion: v1 kind: Service metadata: name: web-nodeport-service spec: type: NodePort ports: - targetPort: 4000 port: 80 nodePort: 30001 selector: app: web-pod
// Create Web pod and NodePort Service $ kubectl create -f web-pod.yaml pod/web-pod created $ kubectl create -f web-nodeport-service.yaml service/web-nodeport-service created // Check the Web pod and Service $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-pod 1/1 Running 0 81s 172.17.0.4 minikube <none> <none> // kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE web-nodeport-service NodePort 10.110.165.250 <none> 80:30001/TCP 63s
Access the web application with NodePort Service.
$ minikube ip 192.168.64.5 $ curl http://192.168.64.5:30001 This is Node.js for Testing Kubernetes MongoDB and Redis Connection. Also, ConfigMap and Secrets can be tested.
Now, user can access your app with
This setup works and users are able to access the application. Whenever traffic increases, we increase the number of replicas of the pod to handle the additional traffic and the service takes care of splitting traffic between the pods.
However, If you have deployed a production grade application before you know that there are many more things involved in addition to simply splitting the traffic between the pods.
- we do not want the users to have to type in IP address every time, so DNS server to point the IP of the node.
- curl http://192.168.64.5:30001
- curl http://www.myapplication.com:30001
$ minikube ip 192.168.64.5 // Add node-ip to DNS server. $ cat /etc/hosts 192.168.64.5 www.myapplication.com $ curl http://192.168.64.5:30001 This is Node.js for Testing Kubernetes MongoDB and Redis Connection. Also, ConfigMap and Secrets can be tested. $ curl http://www.myapplication.com:30001 This is Node.js for Testing Kubernetes MongoDB and Redis Connection. Also, ConfigMap and Secrets can be tested.
Now, users can access the web application with URL www.myapplication.com:30001
2. Users also do not want to remember port numbers either. However, NodePort Service can only allocate high numbered ports that are greater than 30000. So, you bring in an additional layer between the DNS server and the cluster like a proxy server that proxies requests on port 80 to port 30001 on the node. You then point to the DNS server. Now, users can access the web application by simply type http://www.myapplication.com.
What if your Kubernetes Cluster on a public cloud environment like Google Cloud Platform?
If you set Loadbalancer service type, Kubernetes still do everything that it has to do for a NodePort, which is to provision a high port for the service, but in addition to that Kubernetes also sends a request to Google Cloud Platform to provision a network load balancer for the service on receiving the request Google Cloud Platform automatically deploy a load balancer configured to route traffic to the service ports on all the nodes and return its information to Kubernetes. The LoadBalancer has an external IP that can be provided to users to access the application.
Now, What if your company is growing and you need more service for your customers. For example, account service the user should log in to your application. your service should provide like
The developers developed the new account application as a completely different application as it has nothing to do with the existing one. However, in order to share the same cluster resources, you deploy the new application as a separate deployment within the same cluster. You can create a new Loadbalancer Service. The new load balancer has a new IP. You must pay for each of these load balancers and having many such load balancers can inversely affect the cloud build.
How do you direct traffic between each of these load balancers Based on the URL that users type in?
Now you need a new load balancer or proxy that can redirect traffic based on URLs to the diffenent services. Everytime you introduce a new service you have to reconfigure the load balancer and finally you also need to enable SSL for the applications, so users can access the application using https.
Where do you configure that?
It can be done at different levels either at the application level itself or at the load balancer or proxy server but you do not want the developers to implement it in their application as they would do it in different ways.
Thus, You want to be configured in one place with minimal maintenance. That is a lot of different configurations and all of this becomes difficult to manage when the application scales. It requires involving different individuals in different teams. You need to configure your firewall rules for each new service and it is expensive as well as for each service you cloud-native load balancer needs to be provision would not be nice.
What if Kubernetes can manage all of that within the Kubernetes cluster, and have all that configuration as just another Kubernetes definition file?
That is where Ingress comes in.
Ingress helps users access the application using a single externally accessible URL, that you can configure to route to different services within the cluster based on the URL Path. At the same time implement SSL security as well.
You can think ingress as a layer load balancer built-in to the Kubernetes Cluster that can be configured using native Kubernetes primitives.
With Ingress you still need to expose it to make it accessible outside the cluster. Going forward you are going to perform all the load balancing Auth, SSL and URL Based routing configurations on the Ingress controller.