Kubernetes Services and Service Discovery

Kubernetes Service

A Service is a round-robin load balancer for all the pods, which match its name or selector. It constantly monitors the pods, in case a pod gets unhealthy, the service will start deploying the traffic to the other healthy pods.

Service Types

ClusterIP:

Your pods or your service will get a cluster IP so if you try to access your service so you will be only able to access the service using the cluster IP which is only available or accessible within the Kubernetes cluster.

Advantage: It provides service discovery.

Disadvantage: Application only accessible inside Kubernetes cluster.

Exposes the service on cluster-internal IP.

Here's an example manifest file for a Kubernetes Service that uses ClusterIP type:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  type: ClusterIP
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 8080

NodePort:

It will allow your application to be accessed inside your organization.

Anybody within our network technically might not have access to Kubernetes clusters but they have access to the worker Node IP address.

Whoever has access to the Node IP address only they can access the application if the service is created in Note-Port mode.

example manifest for a Service of type: NodePort

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app.kubernetes.io/name: MyApp
  ports:
      # By default and for convenience, the `targetPort` is set to the same value as the `port` field.
    - port: 80
      targetPort: 80
      # Optional field
      # By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
      nodePort: 30007

LoadBalancer:

If you create a Service as type LoadBalancer, the cloud control manager creates an external load balancer IP using the underlying cloud provider logic in the C-CM. Users can access services using the external IP.

Example manifest for a Service type LoadBalancer


apiVersion: v1
kind: Service
metadata:
  name: front-end
spec:
  type: LoadBalancer
  ports:
    - targetPort: 80
      port: 80
  selector:
    app: myapp
    type: front-end

Use the command to create service

kubectl create -f service.yml

Service Discovery

Service comes up with a process which is called labels and selectors. So whenever a pod is created/getting created DevOps engineer will apply a label. This label will be common to all pods.

The service doesn't bother about IP address it will watch for the pods with specific Labels.

This is a ReplicaSet YAML file Example see labels & selector for a better understanding.

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  # modify replicas according to your case
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_samples/gb-frontend:v3

Why label remain the same?

The replica set controller will deploy a new pod with the same yaml that it got.

So if the service is keeping track of pods using labels instead of IP addresses & the label is always the same the problem is solved.

This is a service Discovery mechanism.

Expose to the external world.

Whenever we create deployment the pod is created. This pod came up with a new IP address.

Whoever has access to the Kubernetes cluster? It can be minikube, KOPS, or EKS They can log in to the Kubernetes cluster & they can hit the application.

This is not a real-world scenario, we can't ask our customers to SSH my machine, log in to Kubernetes & access my application cause, for example, my users in Europe or Australia I can't tell they don't have access to my application directly cause they are not in my network. Firstly they have to use VPN and then come to my Network.

So, what service do additionally?

A Service can expose our application can allow the application to access outside the Kubernetes cluster.

How to expose Kubernetes workloads to the outside world using Services?

Create a Kubernetes LoadBalancer Service object: A Kubernetes Service object is a way to expose a deployment or a set of pods as a network service. You can create a Service object by defining its YAML configuration file.

apiVersion: v1
kind: Service
metadata:
  name: front-end
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 80
  selector:
    app: myapp

In this file:

  • apiVersion: v1 indicates that this is a version 1 Kubernetes API object.

  • kind: Service specifies that this is a service resource.

  • metadata provides metadata about the resource, including the name of the service (front-end).

  • spec specifies the desired state of the service. In this case, type: LoadBalancer tells Kubernetes to create a load balancer for the service. The ports section specifies that the service should listen on port 80 and route traffic to port 80 on the pods with the app: myapp label.

  • selector specifies how the service should identify which pods to load balance. In this example, the load balancer will route traffic to pods with the label app: myapp.

Once you've created this service definition file, you can use the kubectl apply the command to create the service in your Kubernetes cluster:

kubectl apply -f <filename>.yaml

This will create the load balancer and expose it to the external network. You can use the kubectl get services command to see the status of the load balancer and its external IP address.

Kubernetes DNS for Services and Pods

Kubernetes is a powerful platform that enables the creation of DNS records for both Services and Pods. This means that instead of relying on IP addresses, Services can be accessed using consistent DNS names, making it easier for running containers to locate Services.

Kubelet is responsible for configuring Pods' DNS, allowing them to lookup Services by name rather than IP. When defining Services within the cluster, DNS names are assigned to them automatically. Additionally, by default, a client Pod's DNS search list includes the Pod's namespace and the cluster's default domain. This makes it easier for Pods to locate Services within their namespace as well as in the cluster's default domain.

DNS Records

What objects get DNS records?

Services

Pods

Services Records

A Record:

IIt is the most basic type of a DNS record used to point a domain or subdomain to a certain IP address. The record consists of the domain name, the IP address to resolve it, and TTL in seconds. TTL stands for Time To Live, and is a sort of expiration date put on a DNS record. A TTL tells the DNS server how long it should keep a given record in its cache.

Kubernetes assigns different A record names for “normal” and “headless” services.

SRV records

SRV Records are created for named ports that are part of normal or headless services.

For each named port, the SRV record has the form port-name.port-protocol.my-svc.my-namespace.svc.cluster-domain.example.

For a regular Service, this resolves to the port number and the domain name: my-svc.my-namespace.svc.cluster-domain.example.

For a headless Service, this resolves to multiple answers, one for each Pod that is backing the Service, and contains the port number and the domain name of the Pod of the form hostname.my-svc.my-namespace.svc.cluster-domain.example. Pods

Pods

A Records

If DNS is enabled, pods are assigned a DNS A record in the form of pod-ip-address.my-namespace.pod.cluster.local.

For example, a pod with IP 172.12.3.4 in the namespace default with a DNS name of the cluster. local would have an entry of the form 172–12–3–4.default.pod.cluster.local

Any Pods exposed by a Service have the following DNS resolution available:

pod-ip-address.service-name.my-namespace.svc.cluster-domain.example

Pod’s Hostname and Subdomain Fields

The default hostname for a pod is defined by a pod’s metadata.name value.

However, users can change the default hostname by specifying a new value in the optional hostname field. Users can also define a custom subdomain name in a subdomain field.

For example, a pod with its hostname set to custom-host, and subdomain set to custom-subdomain, in namespace my-namespace, will have the fully qualified domain name (FQDN) custom-host.custom-subdomain.my-namespace.svc.cluster.local.

Pod's DNS Policy

DNS policies can be set on a per-Pod basis. These policies are specified in the dnsPolicy field of a Pod Spec.

Default: The Pod inherits the name resolution configuration from the node that the Pods run on.

"ClusterFirst": Any DNS query that does not match the configured cluster domain suffix, such as "www.kubernetes.io", is forwarded to an upstream nameserver by the DNS server.

"ClusterFirstWithHostNet": For Pods running with hostNetwork, you should explicitly set its DNS policy to "ClusterFirstWithHostNet". Otherwise, Pods running with host network and "ClusterFirst" will fallback to the behavior of the "Default" policy.

Note: This is not supported on Windows.

"None": It allows a Pod to ignore DNS settings from the Kubernetes environment. All DNS settings are supposed to be provided using the dnsConfig field in the Pod Spec.

Default is not the default DNS policy. If dnsPolicy is not explicitly specified, then "ClusterFirst" is used.

The example Pod with its DNS policy set to "ClusterFirstWithHostNet"

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - image: busybox:1.28
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
    name: busybox
  restartPolicy: Always
  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet

Pod's DNS Config

Pod's DNS Config allows users more control over the DNS settings for a Pod.

Properties a user can specify in the dnsConfig field:

nameservers: A list of IP addresses that will be used as DNS servers for the Pod.

searches: A list of DNS search domains for hostname lookup in the Pod. Duplicate domain names are removed. Kubernetes allows for at most 6 search domains.

options: An optional list of objects where each object may have a name property (required) and a value property (optional). The contents in this property will be merged with the options generated from the specified DNS policy. Duplicate entries are removed.

Example Pod with custom DNS settings:

apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: dns-example
spec:
  containers:
    - name: test
      image: nginx
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
      - 192.0.2.1 # this is an example
    searches:
      - ns1.svc.cluster-domain.example
      - my.dns.search.suffix
    options:
      - name: ndots
        value: "2"
      - name: edns0

When the Pod above is created, the container test gets the following contents in its /etc/resolv.conf file:

nameserver 192.0.2.1
search ns1.svc.cluster-domain.example my.dns.search.suffix
options ndots:2 edns0

For IPv6 setup, the search path and name server should be set up like this:

kubectl exec -it dns-example -- cat /etc/resolv.conf

The output is similar to this:

nameserver 2001:db8:30::a
search default.svc.cluster-domain.example svc.cluster-domain.example cluster-domain.example
options ndots:5

conclusion

Kubernetes DNS system assigns domain and sub-domain names to pods, ports, and services, which allows them to be discoverable by other components inside your Kubernetes cluster.

DNS-based service discovery is very powerful because you don’t need to hard-code network parameters like IPs and ports into your application. Once a set of pods is managed by a service, you can easily access them using the service’s DNS.

Connect me on

LinkedIn:

https://www.linkedin.com/in/aditya-tak/

Hashnod:

https://adityatak.hashnode.dev/

https://hashnode.com/@AdityaDevOps

#Kubernetes #Devops #Kubeweek #kubeweekchallenge

Shubham Londhe

Thank You! Stay Connected☁️👩‍💻

Resources:

https://www.youtube.com/watch?v=xY6Ic7Igzck&list=PLdpzxOOAlwvIKMhk8WhzN1pYoJ1YU8Csa&index=43

https://kubernetes.io/docs/concepts/services-networking/service/

https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/

https://medium.com/kubernetes-tutorials/kubernetes-dns-for-services-and-pods-664804211501