<h2>Background</h2><p>Services are Kubernetes resources that enable network access to Pods. In this blog, we will explain the concepts of Kubernetes Services and its different types. We will also explain Kubernetes Ingress, which is not a service but is another way of routing traffic to our services and our cluster</p><p><br></p><h2>About Kubernetes Services</h2><p>According to <a href="https://www.cortex.io/post/understanding-kubernetes-services-ingress-networking#:~:text=Unlike%20NodePort%20or%20LoadBalancer%2C%20Ingress,running%20inside%20a%20Kubernetes%20cluster." target="_blank">the reference</a>,</p><blockquote><p>a Kubernetes cluster consists of a set of node machines, running containerized applications inside objects named Pods. The pods are grouped based on the type of service they provide into various groups. Pods must be able to accept connections in some way, from our cluster or from ourside of our cluster.<br>In the case of external access, we know that pods inside the cluster are present inside an internal pod network and cannot be accessed by the node's IP address. A user should be able to communicate with the application using the IP address of the node.<br>In the case of internal communication, we know that each pod in the system is assigned with its own unique IP knows as Pod IP. But these IPs are not static, as we know the pods can go down any time and new pods are created all the time in a cluster. So we cannot rely on these IPs for internal communication.<br>So we need something that is consistent so that things outside or inside the cluster might be able to access it persistently. A Service is a Kubernetes object that acts as an endpoint for enabling the communication between various components within and outside the application. In other words, a service is a stable address for pods. The three important Service types in Kubernetes are:<br>1. ClusterIP<br>2. NodePort<br>3. LoadBalancer</p></blockquote><p><br></p><h3>1. ClusterIP</h3><p>ClusterIP is one of Kubernetes service type which comes with default deployment, and which is used to group pods together and provide a single interface to access them <b>within a cluster</b>.</p><pre># service.yaml apiVersion: v1 kind: Service metadata: name: front-end-service spec: type: ClusterIP selector: app: myapp type: front-end ports: - targetPort: 80 port: 80 </pre><p>Cluster IP is default, so this yaml file is nice to have, but for the purpose of comparing with upcoming NodePort and LoadBalancer. The <b>target port</b> is the port where the front-end service is exposed outside of cluster which in this case is 80 and the <b>port</b> is where the ClusterIP service is exposed which is also 80. The name of the service can be used by other pods to access the pod with the service</p><p><br></p><h3>2. NodePort</h3><p>NodePort is a Kubernetes service type that listens on a port on the node and forward requests on that port to a pod on the node, meaning that this is used for <b>communication with outside of the cluster</b></p><pre># service.yaml apiVersion: v1 kind: Service metadata: name: myapp-service spec: type: NodePort selector: app: myapp type: front-end ports: - targetPort: 80 port: 80 nodePort: 32593 </pre><p><b>targetPort</b> is the port on the pod where the actual web server is running, which is 80 in the case. The NodePort service forwards the requests to the target port. If no ports are provided in the spec, it will default to 80</p><p><b>port</b> is the port exposed to the NodePort service itself. It is mondatory</p><p><b>nodePort</b> is the port on the node which is used to access the web server externally. These ports can only be in a valid range from 30000 to32767. This is not a mondatory, and it will be automatically assigned if it's not specified in the file</p><p><br></p><h3>3. LoadBalancer</h3><p>With NodePort, problem is that multiple instances of the web app deployed across multiple nodes in the cluster would be too much for user to handle. To access this web app each, user needs to provide both a node IP and the node port.</p><p>LoadBalancer is a service type and once it's created cloud providers will create a load balancer in the backend and generate a public IP address. This is <b>a standard way to directly expose a service to the Internet</b></p><pre># service.yaml apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: myapp type: LoadBalancer ports: - nodePort: 31000 port: 80 targetPort: 9376 </pre><p>Yes, this is very similar to NodePort. <b>In we only have to have a single service port we can use NodePort. In the meantime, if we need to create multiple instances of the same service, we have to use the LoadBalancer</b></p><p><br></p><h2>Ingress Networking</h2><p>In case of node having multiple services (applications), LoadBalancer needs to be created one by one which is computational expensive. <b>An Ingress can be used when we have multiple services on our cluster and we want the user request routed to the service based on their path.<br></b></p><blockquote>Unlike NodePort or LoadBalancer, Ingress is not actually a type of service. Instead, it is an entry point that sits in front of multiple services in the cluster. It can be defined as a collection of routing rules that govern how external users access services running inside a Kubernetes cluster.<br>Ingress is most useful if you want to expose multiple services under the same IP address, and these services all use the same L7 protocol (typically HTTP).</blockquote><p></p><p><b>Ingress can be considered as the best way to expose multiple services under the same IP</b>. For example, in case of having 2 service in a same cluster and using Ingress, we can access Service A by `app.datak.biz/app1` while access Service B by `app.datak.biz/app2`.</p><p><br></p><h3>Test Ingress Deployment at Minikube/Jupyterhub</h3><p>Referencing <a href="https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/#before-you-begin" target="_blank">Kubernetes original doc</a> and <a href="https://zero-to-jupyterhub.readthedocs.io/en/latest/administrator/advanced.html" target="_blank">jupyterhub official doc</a>. We will use ingress-nginx.</p><p>1. Assuming <a href="https://lab.datak.biz/blog/detail/65/" target="_blank">you've deployed jupyterhub in Minikube by jupyterhub helm chart</a>. Enable the ingress controller in minikube<br></p><pre><p># shell minikube addons enable ingress</p></pre><p>2. Verify that the NGINX Ingress controller is running</p><pre># shell kubectl get pods -n ingress-nginx</pre><p>You will see following results</p><pre># shell NAME READY STATUS RESTARTS AGE ingress-nginx-admission-create-svgtt 0/1 Completed 0 30h ingress-nginx-admission-patch-4gv8q 0/1 Completed 1 30h ingress-nginx-controller-5d88495688-42kq4 1/1 Running 0 30h </pre><p>3. at your `config.yaml`, add following block</p><pre># config.yaml ingress: enabled: true hosts: - jhub.datak.analytics.com </pre><p>4. Update jupyterhub helm</p><pre># shell helm upgrade <RELEASE_NAME> jupyterhub/jupyterhub -f config.yaml </pre><p>Check if ingress is correctly running</p><p><pre># shell kubectl get ingress</pre><p>you will get following result</p><pre># shell NAME CLASS HOSTS ADDRESS PORTS AGE jupyterhub <none> jhub.datak.analytics.com 192.168.64.2 80 29h </pre><p>4. Open host file and add following line of code</p><pre># shell sudo vim /etc/hosts</pre><pre># /etc/hosts file # add 192.168.64.2 jhub.datak.analytics.com</pre><p>5. you can use both terminal or browser to check if it's working!</p><pre># shell curl jhub.datak.analytics.com</pre><p><br></p><h3>Ingress for Neo4j helm?</h3><p>So far it does not work.</p><br></p><p>Reference: <a href="https://www.cortex.io/post/understanding-kubernetes-services-ingress-networking#:~:text=Unlike%20NodePort%20or%20LoadBalancer%2C%20Ingress,running%20inside%20a%20Kubernetes%20cluster." target="_blank">Understanding Kubernetes services & ingress networking</a></p>
<< Back to Blog Posts
Back to Home