Day 4 - Kubernetes Services and Service Discovery

Day 4 - Kubernetes Services and Service Discovery

📍 Introduction

Kubernetes is a powerful container orchestration system that helps manage containerized applications at scale. While Kubernetes makes it easy to run workloads in containers, exposing those workloads to the outside world requires additional configuration. In this blog, we will explore how to expose Kubernetes workloads to the outside world using services and we will also explore how to discover services and pods using DNS and other mechanisms.

🔹What are Services in Kubernetes?

A service in Kubernetes is a Kubernetes resource that exposes an application running in a set of pods as a network service. Services provide a stable IP address and DNS name that can be used to access the application, regardless of the underlying pod IP addresses or which node the pods are running on.

🔹Exposing a Service

To expose a service, you need to create a Kubernetes service resource. A service resource can be created using the kubectl expose command. For example:

kubectl expose deployment ui --type=LoadBalancer --port=80 --target-port=8080

we are exposing a deployment called ui on port 80. The --target-port flag specifies the port on which the container is listening.

  • --type flag specifies the type of service you want to create.

  • ClusterIP: Exposes the service on a cluster-internal IP address. This is the default service type.

  • NodePort: Exposes the service on a port on each node in the cluster.

  • LoadBalancer: Exposes the service externally using a cloud provider's load balancer.

🔹Accessing the Service

Once a service is created, it can be accessed using the IP address or DNS name of the service. If you created a LoadBalancer service, the service will be assigned an external IP address by your cloud provider.

To retrieve the IP address of a service, you can use the kubectl get services command.

🔹Discovering Services Using DNS

Kubernetes provides a built-in DNS service that allows you to discover services by name. By default, each service is assigned a DNS name in the format servicename.namespace.svc.cluster.local. For example, a service named my-service in the my-namespace namespace would have the DNS name my-service.my-namespace.svc.cluster.local.

To discover a service using DNS, simply use its DNS name in your application code or configuration. Kubernetes will automatically resolve the DNS name to the IP address of the service.

how to use these environment variables in a shell script:

#!/bin/bash

curl -s http://$WEB_SERVICE_HOST:$WEB_SERVICE_PORT

🔹Discovering Pods Using DNS

In addition to services, you can also discover pods using DNS. Each pod in Kubernetes is assigned a hostname in the format podname.podnamespace.pod.cluster.local. For example, a pod named my-pod in the my-namespace namespace would have the hostname my-pod.my-namespace.pod.cluster.local.

To discover a pod using DNS, simply use its hostname in your application code or configuration. Kubernetes will automatically resolve the hostname to the IP address of the pod.

🔹Discovering Services and Pods Using Environment Variables

Another way to discover services and pods is by using environment variables. Kubernetes automatically sets environment variables for each service and pod in the format SERVICENAME_PORT_PORTNUMBER_PROTOCOL and PODNAME_SERVICE_HOST and PODNAME_SERVICE_PORT_PORTNUMBER_PROTOCOL.

For example, if you have a service named my-service running on port 80, Kubernetes will automatically set the environment variable MY_SERVICE_PORT_80_TCP to the IP address and port number of the service.

Similarly, if you have a pod named my-pod is part of a service named my-service, Kubernetes will automatically set the environment variables MY_SERVICE_SERVICE_HOST and MY_SERVICE_SERVICE_PORT to the IP address and port number of the service.

To discover services and pods using environment variables, simply reference the appropriate environment variables in your application code or configuration.

Example of how to use Python to discover services and pods within a Kubernetes cluster:

import os
import socket

hostname = os.environ['HOSTNAME']
port = int(os.environ.get('PORT', '8080'))

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((hostname, port))
s.listen(1)

while True:
    conn, addr = s.accept()
    with conn:
        print('Connected by', addr)
        conn.sendall(b'Hello from ' + hostname.encode() + b':' + str(port).encode() + b'\n')

📍Conclusion

Exposing Kubernetes workloads to the outside world using services is a simple and powerful way to make containerized applications accessible to users. By using Kubernetes services, you can provide a stable IP address and DNS name for your application, regardless of the underlying pod IP addresses or which node the pods are running on. By using these mechanisms, you can easily discover and interact with services and pods without needing to know their IP addresses or ports.

Did you find this article valuable?

Support Ashutosh Mahajan's blog by becoming a sponsor. Any amount is appreciated!