Kubernetes
services expose apps running as a set of Kubernetes
pods using a single DNS name. In addition, Kubernetes
services provide load balancing between the pods. Of course, I’ll demo how to manage services using kubectl
. Keep reading to find out more.
Introduction
In Kubernetes Deployments Demo we used kubectl port-forward
to expose app running as the deployment of several pods. Then, we discovered that deployment pods are not load-balanced and only a single pod serves the traffic.
In addition we saw in Kubernetes Pods Demo that pods live only once. Hence, pod ip is ephemeral. Then, of course, we can’t rely on it while connecting to an app running inside a pod. Seems like we need something that will act as a gateway to a set of pods. Pods may come and go, be scaled up or down. Still the app is accessible by its clients. Ideally, app clients don’t need to track app pods and their ips. They want to consume app endpoints using DNS resolvable name. That’s exactly what Kubernetes
service provides in addition to load balancing between the pods.
Kubernetes Services Concepts
So we already know that Kubernetes
service is a gateway to a set of pods. Of course, it has its own virtual ip address. However, unlike pods, services are not ephemeral. Also, we mentioned that services provide load balancing to their pods. But, how are pods associated with a service? Right. Using a label selector, similarly to Kubernetes deployments.
There are several Kubernetes
service types:
Kubernetes
Service Types
ClusterIP
The service is reachable only inside Kubernetes
cluster.
NodePort
The service is reachable by port on each Kubernetes
cluster node via service name and a port.
LoadBalancer
The service is reachable externally. Cloud provider’s load balancer usually proxies to LoadBalancer
service.
ExternalName
The service acts as a proxy for some external service.
Kubernetes Services Demo
It’s time for a Kubernetes
services short demo. Before that, let’s go over demo prerequisites.
Demo Prerequisites
minikube
kubectl
Kubernetes Deployments fast rewind
We’ll base the demo on Kubernetes Deployments Demo we saw previously.
First, let’s create minikube
multi-node cluster using:
minikube start --nodes 3 -p multinode-demo
Now, let’s create nginx
deployment using below command:
$ kubectl create deploy nginx --image=nginx:1.13.2
deployment.apps/nginx created
Make sure nginx
app is running in our minikube
Kubernetes cluster:
$ kubectl get all -l app=nginx
NAME READY STATUS RESTARTS AGE
pod/nginx-6d67674bb5-xd52w 1/1 Running 0 61s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 1/1 1 1 61s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-6d67674bb5 1 1 1 61s
Now, we would like to expose the deployment using Kubernetes
service. We can of course declare nginx
service using yaml. Though, this seems too daunting. So, what can we do? The answer is in the question 🙂 We can create Kubernetes
service out of deployment using kubectl expose
. Let’s see it in action:
$ kubectl expose deployment/nginx --port 8090 --target-port 80
service/nginx exposed
And of course, now we have Kubernetes
service running:
$ kubectl get all -l app=nginx
NAME READY STATUS RESTARTS AGE
pod/nginx-6d67674bb5-xd52w 1/1 Running 0 8m11s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx ClusterIP 10.110.111.105 <none> 8090/TCP 85s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 1/1 1 1 8m11s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-6d67674bb5 1 1 1 8m11s
Will you see nginx
welcome screen if you navigate to http://localhost:8090/
? No because, the service is exposed only internally. It’s running on virtual ip 10.111.105
. What can we do to expose the services externally? Right, use port-forwarding
:
$ kubectl port-forward service/nginx 8090:8090
Now, navigate to http://localhost:8090/
and you’ll see nginx
welcome screen. Let’s stop port-forwarding
for now (CTRL+C).
Declare Kubernetes services using yaml
Is there a way to see yaml of nginx
Kubernetes
service we created in the previous section? Of course. We can see yaml
of any Kubernetes
resource using kubectl get
.
$ kubectl --kubeconfig ~/.kube/config get service/nginx -o yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2021-12-11T13:40:38Z"
labels:
app: nginx
name: nginx
namespace: default
resourceVersion: "7004"
uid: 2882c5de-d3c8-402d-823a-104b582d0318
spec:
clusterIP: 10.110.111.105
clusterIPs:
- 10.110.111.105
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- port: 8090
protocol: TCP
targetPort: 80
selector:
app: nginx
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
There’s a lot of runtime information we’ll not cover here. Above service yaml can be shortened to below one if you intend to store it in git
, for instance.
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 8090
targetPort: 80
I’ll just point out selector
which should match the label app: nginx
. It’s the same selector we specified in the deployment spec
.
Of course, we could declare nginx
Kubernetes
service using yaml. Yet, I find kubectl expose
and kubectl get
trick a preferred way for generating service yaml.
Let’s now demo Kubernetes
services concepts like pods load balancing and access by DNS name.
Kubernetes Services Concepts in Action
As we mentioned above, Kubernetes
services clients can access them by service name. In addition, services provide load balancing for pods. Let’s see both concepts in action.
For this purpose, let’s create serve_hostname
deployment. Its pods return pod name when they are accessed at port 80.
$ kubectl create deployment hostnames --image=k8s.gcr.io/serve_hostname --replicas=3
deployment.apps/hostnames created
Next, let’s expose the pods via Kubernetes service.
$ kubectl expose deployment hostnames --port 9090 --target-port 9376
service/hostnames exposed
Now, let’s run busybox
pod in the same namepace where we ran hostnames
pods.
kubectl run --restart=Never busybox --image=gcr.io/google-containers/busybox -- sleep 7200
As you can see, busybox
is going to sleep for 2 hours:
$ kubectl exec pod/busybox -- ps
PID USER COMMAND
1 root sleep 7200
41 root ps
Now, let’s access
service a few times by service name from hostnames
busybox
pod using wget
and print the result to stdout
.
# demonstrate DNS resolution using wget in verbose mode
$ kubectl exec pod/busybox -- wget hostnames:8070 -O -
Connecting to hostnames:8070 (10.103.105.38:8070)
- 100% |*******************************| 26 0:00:00 ETA
hostnames-f86f9ccc9-t4w8h
# demonstrate load balancing using wget in quiet mode
$kubectl exec pod/busybox -- wget hostnames:8070 -qO -
hostnames-f86f9ccc9-t4w8h
$ kubectl exec pod/busybox -- wget hostnames:8070 -qO -
hostnames-f86f9ccc9-nd4tj
$ kubectl exec pod/busybox -- wget hostnames:8070 -qO -
hostnames-f86f9ccc9-876nq
As you can see, DNS resolution works because hostnames
service name is resolved to the virtual ip of the service. Next, load balancing works because different pods serve web requests directed at hostnames
service. Nice! See more details about debugging Kubernetes
services at Debug Services.
Note that, Kubernetes
service default type is ClusterIP
. That’s why load balancing applies only to internal service requests. In our case internal app wget
in busybox
pod accesses hostnames
service. You may wonder what about external load balancing. For example, in case a user or another app tries to access Kubernetes
service from outside the cluster. That’s a good question. We’ll see how to provide external access to services along with load-balancing in future posts. Then, we’ll cover Ingress
and see examples in the cloud of LoadBalancer
services.
Let’s clean all demo resources using kubectl delete [resource_name]
. Note, that while deleting a deployment deletes its pods, the service stays. You have to delete it using kubectl delete svc name
.
Finally, let’s stop our minikube
cluster.
minikube stop -p multinode-demo
Summary
That’s it about Kubernetes
services. Stay tuned for more Kubernetes
related posts. And, as always, feel free to share and comment.
Bonus:
- Become a Certified Kubernetes Administrator (CKA)!
- Become a Certified Kubernetes Application Developer (CKAD)!
- BUNDLE KUBERNETES FUNDAMENTALS & CKA CERTIFICATION (COURSE & CERTIFICATION) FOR THE BEST DEAL! $499 ONLY!
Recommended Kubernetes courses on Pluralsight:
- Configuring and Managing Kubernetes Networking, Services, and Ingress
- Managing the Kubernetes API Server and Pods
Sign up using this link to get exclusive discounts like 50% off your first month or 15% off an annual subscription)
Recommended Kubernetes books on Amazon: