Cluster IP service is the default service type that gets created when you create a Kubernetes service.
Here’s what it looks like:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
demo ClusterIP 10.100.68.216 <none> 80/TCP 161m
The Cluster IP is a stable IP address that remains unchanged throughout the lifetime of the service.
Though this service may point to multiple pods that can come and go, but you can always access them through the service’s single and constant IP address.
We already saw it in action in another post where we created a Kubernetes service and accessed it using another pod.
But how can a client pod directly know the IP and port of a service? It’s not a great experience where you first create the service, then manually look up its IP address and pass the IP to the configuration options of the client pod.
This is where Kubernetes service discovery comes in really handy.
There are two ways you can access Cluster IP service in Kubernetes from another pod in the cluster:
- Pod Environment Variables
- Kubernetes DNS system
In this post, I will discuss both and show you how to use them.
1 – Pod Environment Variables
When you start a pod, Kubernetes initializes a bunch of environment variables. These variables point to each service that exists at that moment. You can use the variable to directly access the service without knowing the ClusterIP.
So, what’s the catch?
The catch is that if you create the service after creating the pods, the pod isn’t going to get those environment variables. In other words, you must:
- Create the ClusterIP service
- Then, create the pods supported by the service.
To check whether a pod has the environment variables, execute the below command.
$ kubectl exec basic-rc-86w4j env
Here, basic-rc-86w4j
is the name of the pod.
You should a big list of variables printed on the screen. The environment variables for the Kubernetes service will look like below:
DEMO_SERVICE_HOST=10.100.68.216
DEMO_PORT_80_TCP_PROTO=tcp
DEMO_SERVICE_PORT=80
DEMO_PORT_80_TCP_PORT=80
DEMO_PORT=tcp://10.100.68.216:80
DEMO_PORT_80_TCP=tcp://10.100.68.216:80
DEMO_PORT_80_TCP_ADDR=10.100.68.216
How can you use these environment variables?
That’s simple.
The environment variables are available to the process running within the pod. For example, in the case of Node.js, you can pull out any of these variables from the process.env
object. Then, it’s a matter of using it in your application as per the requirement.
Check the below example for reference where we access the variable DEMO_SERVICE_HOST
from process.env
object:
const express = require('express');
const app = express();
let requestCount = 0;
console.log(`Service Host: ${process.env.DEMO_SERVICE_HOST}`);
app.get('/', (req, res) => {
requestCount++;
if (requestCount > 2) {
res.status(500).send("The app is not well. Please restart!")
}
res.send("Hello World from our Kubernetes Pod Demo")
})
app.listen(3000, () => {
console.log("Listening to requests on Port 3000")
})
2 – DNS for Cluster IP Kubernetes Service
The first approach works well.
But looking up IP address and port is usually the job of a DNS system.
Kubernetes has its own DNS server that you can use to access the service without worrying about the IP address and port.
In your Kubernetes installation, there is a special namespace named kube-system
. Within that namespace, there is a special service kube-dns
. Behind the service are a couple of pods that run a DNS server known as Core DNS.
Here’s a quick command to check it out:
saurabhdashora@Saurabhs-MacBook-Air basic-pod-demo % kubectl --namespace=kube-system get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 256d
All other pods running in the cluster are automatically configured to use this DNS service. Each service gets a DNS entry in the internal DNS server. The client pods just need to known the name of the service and they can access it through its fully qualified domain name (aka FQDN)
Whenever a process running in a pod makes a DNS query, it comes to the Kubernetes DNS server.
For example, if I want to access the demo-service
, I can open a connection to the below FQDN:
demo.default.svc.cluster.local
Here,
demo
is the name of the service.default
stands for the namespace the service is defined insvc.cluster.local
is a configurable cluster domain suffix used in all cluster local service names.
In fact, connecting to the service is even simpler. You can omit the svc.cluster.local
suffix as well as the namespace when the two pods are in the same namespace. In other words, you can simply refer to the service as demo
.
See the below example:
$ kubectl exec basic-rc-86w4j -- curl http://demo
What makes this possible is the DNS resolver inside each pod’s container. You can check out how the resolver works by inspecting /etc/resolv.conf
file.
saurabhdashora@Saurabhs-MacBook-Air basic-pod-demo % kubectl exec basic-rc-86w4j -- cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
Conclusion
With this, we have looked at two ways to access a Cluster IP service in Kubernetes from another pod.
- Using Pod Environment Variables
- Using the in-built Kubernetes DNS server
This is the simplest use-case for accessing a service and also quite common way of quickly setting up connections between services running on different pods.
Hope you found it useful. In future posts, I’ll be covering other ways of connecting to Kubernetes services.
0 Comments