Kubernetes Networking with Services
Overview
Kubernetes Service object is the way in Kubernetes to expose applications, both on the network and to the outside world. Exposing the app could be external
like from a web browser and internal
like accessing it from maybe another Pod or application on the same cluster that’s talking to it.
π₯ Services nail both these scenarios.
Let’s look at services
with an example below:
There’s a Pod (Green) hosting a web front end needing to talk to a few of backend Pods (Blue) down below. Well, we slip in a service
object in the middle. service
object is just a Kubernetes API object like a pod
or deployment
or anything else, meaning we define it in a YAML manifest, and we create it by throwing that manifest at the API server.
ClusterIP
Once a service
is created it provides a stable IP (a.k.a. ClusterIP) and DNS name, so, a single IP and DNS name that then load balancers requests it receives to the backend Pods.
Then if one of the (Blue) Pods die or gets replaced by another, it’s all good, because the service is watching, and it just updates the list that it holds are valid, healthy Pods. But importantly, it never changes the stable and reliable ClusterIP and DNS name for the service
. That never changes. In fact, part of the contract we have with Kubernetes is that once this service
is defined, that it’s IP and DNS will never, ever, ever, ever change. It is a just a highβlevel stable abstraction point for multiple Pods.
Load Balancing
Also it provides basic load balancing. The way that a Pod belongs to a service or makes it onto the list of Pods that a service will forward traffic to is via labels
. See below how the Pod manifest got a label called “web”. Well, just put the same label in the service manifest under the label selector, and the service is going to send traffic to that Pod.
Internal Access
We already said that a service
gets a ClusterIP, and as the name suggests, that is for inside the cluster. And we also said that the name of the service gets registered with the internal DNS service, and every container uses this DNS service when it is resolving names to IPs.
Four Pods inside the cluster(Green) wanting to talk to backend Pods(Blue), so long as they know the name of the service in front of the Pods, it fires that off to the internal DNS service, and it gets back the cluster IP
.
And then from there on, it just sends traffic to that cluster IP
, and the cluster takes care of getting it to individual Pods.
External Access
NodePort: A
service
also gets a network port. Well, that port can be mapped on every cluster node to point back to the cluster IP.So, in below example, the service has a port of 30001, and that’s mapped on every node in the cluster, meaning we can sit outside of the cluster and send requests literally to any node on that port, and Kubernetes makes sure that it’s routed to the
cluster IP
and eventually the Pods behind it.And we call this a
NodePort
. Again, it’s in the name! Every node gets the port mapped.LoadBalancer: For external access there’s a third type of
service
object: LoadBalancer type, and it seamlessly integrates with your cloud provider’s native load balancers to provide access from over the internet.And the π part, Kubernetes literally does it all, and I mean all right? You literally just define a YAML file that says type equals
LoadBalancer
, and Kubernetes does the rest.
There’s three major service types, and each one is useful for a different requirement. At the bottom is ClusterIP, and this is the default, right, so if you don’t explicitly set a type, that’s what you’ll get. Now, it is a stable IP within a cluster, so a ClusterIP only makes the service available from inside the cluster.
Next up, there’s the NodePort that we’re going with. This takes this ClusterIP, which is needed for routing within the cluster, and it adds a clusterβwide TCP or UDP port on top. In fact, it’s what we just saw when we assigned it a random port above 30000 and tied the service to that port on every node in the cluster.
Finally we have the LoadBalancer type, which works with Cloud providers loadbalancer and exposes a stable endpoint to the internet.
Create Services
Imperative
cloud_user@k8s-control:~$ kubectl expose pod hello-pod --name=hello-svc --target-port=8080 --type=NodePort
service/hello-svc exposed
cloud_user@k8s-control:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-svc NodePort 10.99.123.2 <none> 8080:31790/TCP 12s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 12d
Declarative
Further Read
The takeβhome point is that services
provide reliable networking for Pods.