ClusterIP Service resources are the default Service resource type that exposes pods within the Kubernetes cluster. It is not possible to access ClusterIP Service resources outside the cluster; therefore, they are never used to expose your pods to the external world. ClusterIP Service resources generally expose backend apps such as data stores and databases—the business and data layers—in a three-tier architecture.
Tip
When choosing between Service resource types, as a general rule of thumb, always start with the ClusterIP Service resource and change it if needed. This will ensure that only the required Services are exposed externally.
To understand ClusterIP Service resources better, let’s create a redis Deployment resource first using the imperative method with the following command:
$ kubectl create deployment redis –image=redis
Let’s try exposing the redis deployment pods using a ClusterIP Service resource. To access the resources for this section, cd into the following:
$ cd ~/modern-devops/ch6/services/
Let’s look at the Service resource manifest, redis-clusterip.yaml, first:
apiVersion: v1
kind: Service
metadata:
labels:
app: redis
name: redis
spec:
ports:
port: 6379
protocol: TCP
targetPort: 6379
selector:
app: redis
The Service resource manifest starts with apiVersion and kind as any other resource. It has a metadata section that contains name and labels.
The spec section contains the following:
- ports: This section includes a list of ports that we want to expose via theService resource:
- port: The port we wish to expose.
- protocol: The protocol of the port we expose (TCP/UDP).
- targetPort: The target container port where the exposed port will forward the connection. This allows us to have a port mapping similar to Docker.
- selector: This section containslabels based on which pod group is selected.
Let’s apply the Service resource manifest using the following command and see what we get:
$ kubectl apply -f redis-clusterip.yaml
Let’s run kubectl get to list the Service resource and get the cluster IP:
$ kubectl get service redis
NAME
TYPE
CLUSTER-IP
EXTERNAL-IP PORT(S)
AGE
redis
ClusterIP
10.12.6.109
6379/TCP
16s
We see a redis Service resource running with a ClusterIP type. But as this pod is not exposed externally, the only way to access it is through a second pod running within the cluster.
Let’s create a busybox pod in interactive mode to inspect the Service resource and run some tests using the following command:
$ kubectl run busybox –rm –restart Never -it –image=busybox / #
And with this, we see a prompt. We have launched the busybox container and are currently within that. We will use the telnet application to check the connectivity between pods.
Let’s telnet the cluster IP and port to see whether it’s reachable using the following command:
- # telnet 10.96.118.99 6379 Connected to 10.96.118.99
The IP/port pair is reachable from there. Kubernetes also provides an internal DNS to promote service discovery and connect to the Service resource. We can do a reverse nslookup on the cluster IP to get the Service resource’s FQDN using the following command:
- # nslookup 10.96.118.99
Server:10.96.0.10
Address:10.96.0.10:53
99.118.96.10.arpa name = redis.default.svc.cluster.local
As we can see, the IP address is accessible from the FQDN—redis.default.svc.cluster. local. We can use the entire domain or parts of it based on our location. The FQDN is formed of these parts: <service_name>.<namespace>.svc.<cluster-domain>.local.
Kubernetes uses namespaces to segregate resources. You can visualize namespaces as multiple virtual clusters within the same physical Kubernetes cluster. You can use them if many users work in multiple teams or projects. We have been working in the default namespace till now and will continue doing so. If your source pod is located in the same namespace as the Service resource, you can use service_name to connect to your Service resource—something like the following example:
- # telnet redis 6379 Connected to redis
If you want to call a Service resource from a pod situated in a different namespace, you can use <service_name>.<namespace> instead—something like the following example:
- # telnet redis.default 6379 Connected to redis.default
Some service meshes, such as Istio, allow multi-cluster communication. In that situation, you can also use the cluster name for connecting to the Service resource, but as this is an advanced topic, it is beyond the scope of this discussion.
Tip
Always use the shortest domain name possible for endpoints, as it allows for more flexibility in moving your Kubernetes resources across your environments.
ClusterIP Services work very well for exposing internal pods, but what if we want to expose our
pods to the external world? Kubernetes offers various Service resource types for that; let’s look at the NodePort Service resource type first.