Every Pod has an IP address which other Pods in the cluster can reach, but that IP address only applies for the life of the Pod.
Services provide a consistent IP address linked to a DNS name, and you’ll always use Services for routing internal and external traffic into Pods.
Services and Pods are loosely-coupled: a Service finds target Pods using a label selector.
Service definitions have the usual metadata. The spec needs to include the network ports and the label selector:
apiVersion: v1
kind: Service
metadata:
name: whoami
spec:
selector:
app: whoami
ports:
- name: http
port: 80
targetPort: 80
The ports are where the Service listens, and the label selector can match zero to many Pods.
selector
- list of labels to find target Podsports
- list of ports to listen onname
- port name within Kubernetesport
- port the Service listens ontargetPort
- port on the Pod where traffic gets sentPods need to include matching labels to receive traffic from the Service.
Labels are specified in metadata:
apiVersion: v1
kind: Pod
metadata:
name: whoami
labels:
app: whoami
spec:
# ...
Labels are abitrary key-value pairs.
app
,component
andversion
are typically used for application Pods.
Start by creating some simple Pods from definitions which contain labels:
kubectl apply -f https://fasttrack-azure.github.io/Cloud-For-Partners/labs/aks/services/specs/pods/whoami.yaml
kubectl apply -f https://fasttrack-azure.github.io/Cloud-For-Partners/labs/aks/services/specs/pods/sleep.yaml
You can work with multiple objects and deploy multiple YAML manifests with Kubectl
📋 Check the status for all Pods, printing all the IP addresses and labels.
kubectl get pods -o wide --show-labels
The Pod name has no affect on networking, Pods can’t find each other by name:
kubectl exec sleep -- nslookup whoami
Kubernetes provides different types of Service for internal and external access to Pods.
ClusterIP is the default and it means the Service gets an IP address which is only accessible within the cluster - its for components to communicate internally.
📋 Deploy the Service from labs/services/specs/services/whoami-clusterip.yaml
and print its details.
kubectl apply -f https://fasttrack-azure.github.io/Cloud-For-Partners/labs/aks/services/specs/services/whoami-clusterip.yaml
Print the details:
kubectl get service whoami
kubectl describe svc whoami
The
get
anddescribe
commands are the same for all objects; Services have the aliassvc
The Service has its own IP address, and that is static for the life of the Service.
Kubernetes runs a DNS server inside the cluster and every Service gets an entry, linking the IP address to the Service name.
kubectl exec sleep -- nslookup whoami
This gets the IP address of the Service from its DNS name. The first line is the IP address of the Kuberentes DNS server itself.
Now the Pods can communicate using DNS names:
kubectl exec sleep -- curl -s http://whoami
📋 Recreate the whoami Pod and the replacement will have a new IP address - but service resolution with DNS still works.
Check the current IP address then delete the Pod:
kubectl get pods -o wide -l app=whoami
kubectl delete pods -l app=whoami
You can use label selectors in Kubectl too - labels are a powerful management tool
Create a replacement Pod and check its IP address:
kubectl apply -f https://fasttrack-azure.github.io/Cloud-For-Partners/labs/aks/services/specs/pods/whoami.yaml
kubectl apply -f https://fasttrack-azure.github.io/Cloud-For-Partners/labs/aks/services/specs/pods/sleep.yaml
kubectl get pods -o wide -l app=whoami
The Service IP address doesn’t changed, so if clients cache that IP they’ll still work. Now the Service routes traffic to the new Pod:
kubectl exec sleep -- nslookup whoami
kubectl exec sleep -- curl -s http://whoami
There are two types of Service which can be accessed outside of the cluster: LoadBalancer and NodePort.
They both listen for traffic coming into the cluster and route it to Pods, but they work in different ways. LoadBalancers are easier to work with, but not every Kubernetes cluster supports them.
In this course we’ll deploy both LoadBalancers and NodePorts for all our sample apps so you can follow along with your cluster.
LoadBalancer Services integrate with the platform they’re running on to get a real IP address. In a managed Kubernetes service in the cloud you’ll get a unique public IP address for every Service, integrated with a cloud load balancer to direct traffic to your nodes. In Docker Desktop the IP address will be localhost
; in k3s it will be a local network address.
NodePorts don’t need any external setup so they work in the same way on all Kubernetes clusters. Every node in the cluster listens on the specified port and forwards traffic to Pods. The external port number must be >= 30000 - a security feature so Kubernetes components don’t need to run with elevated privileges on the node.
Platform | LoadBalancer | NodePort |
---|---|---|
Docker Desktop | ✔ | ✔ |
K3s | ✔ | ✔ |
K3d | 🌓 | ✔ |
AKS, EKS, GKE etc. | ✔ | ✔ |
Kind | ❌ | ✔ |
Minikube | ❌ | ✔ |
Microk8s | ❌ | ✔ |
Bare-metal | ❌ | ✔ |
If you don’t have LoadBalancer support you can add it with MetalLB, but that’s not in scope for this course :)
There are two Service definitions to make the whoami app available outside the cluster:
You can deploy both:
kubectl apply -f https://fasttrack-azure.github.io/Cloud-For-Partners/labs/aks/services/specs/services/whoami-nodeport.yaml -f https://fasttrack-azure.github.io/Cloud-For-Partners/labs/aks/services/specs/services/whoami-loadbalancer.yaml
📋 Print the details for the services - both have the label app=whoami
.
kubectl get svc -l app=whoami
If your cluster doesn’t have LoadBalancer support, the
EXTERNAL-IP
field will stay at<pending>
forever
External Services also create a ClusterIP, so you can access them internally.
You always need to use the Service port for communication:
kubectl exec sleep -- curl -s http://whoami-lb:8080
kubectl exec sleep -- curl -s http://whoami-np:8010
The Services all have the same label selector, so they all direct traffic to the same Pod
Now you can call the whoami app from your local machine:
# either
curl http://localhost:8080
# or
curl http://localhost:30010
If your cluster isn’t running locally, use the node’s IP address for NodePort access or the EXTERNAL-IP address field for the LoadBalancer
Services are a networking abstraction - they’re like routers which listen for incoming traffic and direct it to Pods.
Target Pods are identified with a label selector, and there could be zero or more matches.
Create new Services and whoami Pods to test these scenarios:
What happens? How can you find the target Pods for a Service?
Every YAML spec for this lab adds a label kubernetes.courselabs.co=services
.
That makes it super easy to clean up, by deleting all those resources:
kubectl delete pod,svc -l kubernetes.courselabs.co=services