Back to Blog
Lesson 18 of the Kubernetes: Kubernetes Concepts & Your First Pod course
KubernetesAugust 5, 20263 min read

Creating a ClusterIP Service: Stable Internal Networking

Master the ClusterIP Service in Kubernetes. Learn to write Service manifests, use label selectors to target Pods, and ensure reliable internal connectivity.

KubernetesClusterIPServiceNetworkingDevOpsInfrastructure
Close-up of server racks in a data center highlighting modern technology infrastructure.

Previously in this course, we explored The Role of Services: Kubernetes Networking Explained, where we established why Pod IPs are ephemeral and unreliable for long-term communication. In this lesson, we move from theory to practice by implementing a ClusterIP Service—the standard way to expose your applications for internal cluster communication.

Why ClusterIP?

A ClusterIP service is the default Service type in Kubernetes. It allocates a stable, internal IP address that remains constant, even as the underlying Pods are destroyed and recreated. Because this IP is only reachable from within the cluster, it is the primary choice for backend services, internal APIs, and database connections.

Anatomy of a Service Manifest

To create a Service, we use a declarative YAML manifest. The core of this manifest is the selector field, which acts as the "glue" between the Service and your Pods by matching the labels we defined in earlier lessons.

Here is the structure of a standard ClusterIP Service:

YAML
apiVersion: v1
kind: Service
metadata:
  name: my-backend-service
spec:
  type: ClusterIP      # Explicitly setting the type
  selector:
    app: my-web-app    # This must match your Pod's labels
  ports:
    - protocol: TCP
      port: 80         # The port the Service listens on
      targetPort: 8080 # The port your container is running on

Worked Example: Connecting a Frontend to a Backend

Let's assume you have a Pod running an application labeled app: my-web-app that serves traffic on port 8080.

  1. Create the Manifest: Save the code above as service.yaml.
  2. Apply the Manifest: Run kubectl apply -f service.yaml.
  3. Verify: Use kubectl get svc my-backend-service to see the assigned CLUSTER-IP.

Once created, any other Pod in the same namespace can now reach your application by hitting http://my-backend-service:80 rather than tracking individual, changing Pod IPs.

Hands-on Exercise

  1. Ensure you have a running Pod with the label tier: backend.
  2. Write a Service manifest named backend-svc.yaml that targets the tier: backend selector.
  3. Apply the manifest and confirm it is active using kubectl get svc.
  4. (Optional) If you have a second "client" Pod, try running curl http://backend-svc from inside that container to verify connectivity.

Common Pitfalls

  • Label Mismatch: If your Service is not routing traffic, the first thing to check is the selector. If your Pod label is app: frontend but your Service selector is app: backend, the Service will be "orphaned" and will not route to any endpoints.
  • Port Confusion: Beginners often mix up port (the entry point for the Service) and targetPort (the actual port inside the container). Remember: port is for the cluster to find you, targetPort is for your code to listen on.
  • Namespace Isolation: Remember that a Service only routes to Pods within the same namespace. If your Service is in default and your Pod is in production, they cannot communicate via this Service.

FAQ

Q: Can I access a ClusterIP service from my laptop? A: Not directly. ClusterIP is strictly internal. To access it from your machine for debugging, use kubectl port-forward as discussed in our lesson on Kubernetes Port Forwarding.

Q: Do I need to update the Service if I add more Pods? A: No. Kubernetes automatically manages the list of "endpoints" for the Service based on the label selector. As you scale your Pods up or down, the Service keeps track of them automatically.

Recap

We have successfully implemented stable internal networking using the ClusterIP Service. By leveraging label selectors, we decouple our networking layer from the volatile nature of individual Pod lifecycles, ensuring our services remain discoverable across the cluster.

Up next: We will learn how to expose our applications to the outside world using the NodePort Service type.

Similar Posts