📍 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.