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. Theports
section specifies that the service should listen on port 80 and route traffic to port 80 on the pods with theapp: 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 labelapp: 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
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