Lesson 07
Declaring services
~3 min read
Now, we have a deployment in our cluster exposing port 80. However there is no way for us to access it or know how to reach it. That is where services come in. A service in Kubernetes can be considered as the internal networking layer it is defined as:
a Service is a method for exposing a network application that is running as one or more Pods in your cluster.
Remember the pods that got created earlier when we applied the deployment? These pods come and go and we can not expect the exact same set of pods to be running forever. Each of these pods that get created are assigned an IP address. But wait, if I need to make requests to these pods and their IP addresses keep changing how can I know how to reach them?
This is the part where services really shine. Services provide an abstraction for how to access your application and they can route traffic across multiple pod replicas of your application. They provide a stable endpoint for pods to connect to, regardless of the lifecycle of individual pods.
Here is an example of a service resource:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app.kubernetes.io/name: my-nginx
ports:
- protocol: TCP
port: 80
targetPort: 80If you examine this service manifest you see that it also has a few interesting fields. It has the spec or specification which has two things; the selector which tells the service which pods it is going to be targeting. In our case we are going to be targeting all pods that have the label: app.kubernetes.io/name=my-nginx. The ports section is our way of telling Kubernetes that for the pods with the targeted label, we are going to be directing traffic to them through port 80 and sending it to the target port on each of the respective pods. If our pods were accepting traffic on a different port such as port 3000 we would specify that as the target port. All incoming traffic would still come through port number 80. Another thing we specify is the protocol, TCP is the default and we'll leave that as is.
The sandbox has the manifest stored as nginx-service.yaml. Let's apply it:
kubectl apply -f ./nginx-service.yaml
Verify that the service was created:
kubectl get servicesBy creating a service, Kubernetes automatically assigned a DNS A record to this service of the form <service>.<ns>.svc.<zone> where <service> is the name of the service, <ns> is the namespace the service is in, and <zone> is the configured cluster domain e.g. cluster.local. For our newly created service the DNS A record is: nginx-service.default.svc.cluster.local. Within the same namespace, you can simply use the service name (nginx-service) as a shorthand. Having a fully qualified domain name (FQDN) for our service allows other processes within the cluster to communicate with our service using this domain name.
Service routing: traffic distribution
Traffic flows from the Service to available Pods
Now, we have a deployment and a way to communicate with the pods in that deployment. So we have an application running inside of Kubernetes and a way to reach it, that is within the isolated cluster. The last remaining bit is to setup external access for our application.