Table of contents
In this blog let us see how Service and Service Discovery in detail.
The two main important concepts we are going to see today are:
Expose k8s workloads using service
Discover pods and services in the clusters using DNS and other mechanisms
Service
A Kubernetes Service is a mechanism to expose applications both internally and externally.
In K8s a Service is a single outward-facing endpoint for exposing a network application that is running as one or more Pods in your cluster
A Service in Kubernetes is an object (the same way that a Pod or a ConfigMap is an object).
The service holds access policies and is responsible for enforcing these policies for incoming requests.
The service is assigned a virtual IP address, known as a clusterIP, which persists until it is explicitly destroyed.
You can create, view or modify Service definitions using the Kubernetes API. Usually, you use a tool such as kubectl
to make those API calls for you.
Types of Services
Kubernetes allows the creation of these types of services:
ClusterIP
NodePort
LoadBalance
External IP
ClusterIP (default Type of Service)
A Service is created by grouping similar types of pods( Example: web app, db groups) and IP address is assigned to it.
Service receives a name, cluster-internal IP address and a port, making its pods only accessible from within the cluster. This is called as Cluster IP.
In yaml, we need to mention only the target port(backend port) and port(service port) and both are 8
Nodeport
A NodePort service builds on top of the ClusterIP service, exposing the node to a port accessible from outside the cluster.
The nodePort field in the service manifest is optional and lets you specify a custom port between 30000-32767.
In yaml, while creating this kind of service three ports are important node port(has range), target port(default as port) and service port(mandatory)
yaml file for reaching applications within a
single pod on a single node
using a service.For
multiple pods in a single node same cluster
, there is no need for any configuration change in yaml because all have the same label and the service uses a random algorithm to reach podsFor
multiple pods in multiple nodes
in the same cluster, the service expands across all the nodes in the cluster and uses the same port number with the respective node ip.
LoadBalancer
A LoadBalancer service is based on the NodePort service and adds the ability to configure external load balancers in public and private clouds via native load balancers.
It exposes services running within the cluster by forwarding network traffic to cluster nodes.
ExternalName
An ExternalName service maps the service to a DNS name instead of a selector.
It returns a CNAME record matching the contents of the externalName field
Expose k8s workloads using service
Services match a set of Pods using labels and selectors, a grouping primitive that allows logical operation on objects in Kubernetes.
Creating a service for an application running in two pods
create a YAML file to create a new application deployment
apiVersion: apps/v1 kind: Deployment metadata: name: hello-world spec: selector: matchLabels: run: load-balancer-example replicas: 2 template: metadata: labels: run: load-balancer-example spec: containers: - name: hello-world image: gcr.io/google-samples/node-hello:1.0 ports: - containerPort: 8080 protocol: TCP
Run the application in cluster
kubectl apply -f
https://k8s.io/examples/service/access/hello-application.yaml
Create a deployment named: hello-world
ReplicaSet : 2
Pods: 2(application each)
Display information about the Deployment
kubectl get deployments hello-world
kubectl describe deployments hello-world
Display information about the rs
kubectl get replicasets kubectl describe replicasets
Expose the deployment using service
This creates service object that exposes deployment
kubectl expose deployment hello-world --type=NodePort --name=example-service
Note : Here we use Nodeport to expose the node to outside world in cluster
Display info about the service
kubectl describe services example-service
List pods that run Hello world application
kubectl get pods --selector="run=load-balancer-example" --output=wide
check the application
curl http://<clusterip>:<nodeport>
K8s Service discovery
To make a Pod reachable via external networks or other Kubernetes clusters without relying on any internal IPs, we need another layer of abstraction. Kubernetes offers that abstraction with a construct called a Service Deployment.
Service discovery is the actual process of figuring out how to connect to a service from pods.
For Cloud Native service discovery, k8s updates the EndpointSlices for a Service whenever the set of Pods in a Service changes.
For non-cloud native service discovery, Kubernetes supports 2 primary modes of finding a Service - environment variables and DNS.
Environment variables
When a Pod is run on a Node, the kubelet adds a set of environment variables for each active Service.
It adds {SVCNAME}_SERVICE_HOST
and {SVCNAME}_SERVICE_PORT
variables, where the Service name is upper-cased and dashes are converted to underscores.
For Example the Service redis-primary
which exposes TCP port 6379 has following environmental variable
REDIS_PRIMARY_SERVICE_HOST=10.0.0.11
REDIS_PRIMARY_SERVICE_PORT=6379
REDIS_PRIMARY_PORT=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP_PROTO=tcp
REDIS_PRIMARY_PORT_6379_TCP_PORT=6379
REDIS_PRIMARY_PORT_6379_TCP_ADDR=10.0.0.11
Note: In this method, you must create the Service before the client Pods come into existence. Otherwise, those client Pods won't have their environment variables populated.
DNS-Based Service Discovery
Kubernetes provides a built-in DNS service that allows you to discover Services and Pods using their DNS names. The DNS service is automatically created when you create a cluster and acts as pods.
Kube-Dns or CoreDNS integrate with Kubernetes via the Kubernetes plugin, or with etcd with the etcd plugin. All major cloud providers have plugins too: Microsoft Azure DNS, GCP Cloud DNS and AWS Route53.
How do Pods Communicate
K8s implements DNS in clusters. Let’s say one pod i.e. test wants to communicate with another pod, db. So, we can do that by adding the db pods ip in test pod's /etc/hosts file*.*
But the same cannot be done when more pods need to communicate with each other in a cluster
To eliminate this, a centralized DNS server was introduced. It stores the pod's name and IP. So the pods reach the DNS server and connect with other pods in the cluster. But it is possible only when pods reach the DNS server, for that we need to mention the DNS server namespace and IP address in each pod's /etc/resolve.conf.
Every time a new pod gets created, k8s will create an entry of the new pod in the DNS server and also will update the /etc/resolv.conf file of the new pod with IP address of the DNS server.
CoreDNS in K8s
As CoreDns is the latest version here we will see about it. A cluster-aware DNS server, such as CoreDNS, watches the Kubernetes API for new Services/pods and creates a set of DNS records for each one.
CoreDNS has been available in K8s since v1.9. It is a fast and flexible DNS server.
How CoreDNS server record entries
As a continuation from the above topic, in the below picture, you can see that in the CoreDNS server there are two types of entries
One for service - for service, it is mapped as name and IP address
One for pods - for pods the name is noted by its IP address by replacing '.' with '-' and the IP address
By default,CoreDNS's pod entries will be disabled. Once it is enabled, throughout your cluster then all Pods should automatically be able to resolve Services by their DNS name.
The format of the DNS record would be: service-name.namespace.svc.cluster.local
Now the client pod can access the URL of the application deployed in pods using any of the below DNS names mentioned in the picture.
How is the CoreDNS setup in Cluster
CoreDNS is configured as pods as a namespace in the cluster. They are deployed as two pods as part of the redundancy of a replica set within a deployment.
It requires a configuration file /etc/coredns/CoreFile and in this number of plugins are configured (The one that is in orange).
Here Kubernetes plugin integrates CoreDNS and K8s, here we set the top-level domain name of the cluster as cluster.local
.
Every record in the CoreDNS server falls under this domain.
As mentioned in the above topic pods insecure
is the option that is disabled by default. We can enable this to record pod entries
Next comes the proxy, once pods try to reach an application URL it checks the CoreFile's proxy attribute. It is then forwarded to the nameserver specified in the CoreDNS pod's resolve.conf file.
It now uses the resolve.conf
file to reach the DNS nameserver in K8s Node.
Note: This CoreFile is passed into Pod as a ConfigMap object. To edit this configuration we can use ConfigMap object
kubectl get configmap -n kube-system
Now we have the CodeDNS pods running using the CoreDNS plugin. It watches the K8s cluster whenever pods/ services are created and adds the entries to its database.
Let us think that we have multiple DNS servers, so what address do the pods use to reach the DNS server? Here comes the service that will be created by default when CoreDNS is installed. This Service is called kube-dns.
kubectl get service -n kube-system
This Service IP address is configured as nameserver IP in /etc/resolve.conf of pods. This configuration is done by K8s automatically when pods are created. Kubelet component is responsible for this process.
Below is the config file of kubelet is the IP address of the DNS server(service IP)
The pods are configured with the right nameserver. Now the pods can resolve other pods or services like below
If we check this with nslookup or host command it will return the FQDN of webservice
In the above picture, the DNS nameserver can resolve the services in any of these names.
However, it is not the case with pods and the FQDN name needs to be mentioned for it
Reference: https://medium.com/kubernetes-tutorials/kubernetes-dns-for-services-and-pods-664804211501
https://platform9.com/blog/kubernetes-service-discovery-principles-in-practice/
https://www.digitalocean.com/community/tutorials/an-introduction-to-the-kubernetes-dns-service
Summary
To understand these concepts, learning the basic DNS and routing concepts would be much helpful. Also, Service and Service Discovery are the crucial concepts of effective and efficient networking in K8s. They run the cloud native and native networking concept as a miniature within K8s. Still, it helps in forming and managing more complex infrastructure.
~~ Saraa
Thanks for reading my blog. Hope it gave some insights on DNS in K8s.
Suggestions are always welcomed.
Will see you in the next blog ........... :)