Day 9of40daysofkubernetes : Comparing Kubernetes Services: ClusterIP, NodePort, LoadBalancer, ExternalName

In Kubernetes, services play a vital role in enabling communication between different components of an application. A Service in Kubernetes is an abstraction that defines a logical set of Pods and a policy by which to access them. Since Pods are ephemeral and have dynamic IPs, services provide a consistent way to expose these Pods to other Pods or external users.

Kubernetes offers several types of services to handle different network access scenarios, each serving distinct use cases. In this blog, we’ll break down four essential service types: ClusterIP, NodePort, LoadBalancer, and ExternalName.

1. ClusterIP: Internal Communication

Overview:

ClusterIP is the default service type in Kubernetes, designed for internal communication within the cluster. It automatically assigns an internal IP address to the service, making it accessible only from within the cluster.

Use Case:

This service is ideal for microservices that need to communicate internally within the Kubernetes cluster. For example, one service like a backend might need to access a database that is hosted inside the cluster using a ClusterIP service.

Key Characteristics:

  • Internal Only: Services are exposed to the cluster internally, not externally.

  • Automatic IP: Kubernetes automatically assigns an IP for internal use.

  • No External Access: Pods outside the cluster cannot access a ClusterIP service directly.

Example YAML:

apiVersion: v1
kind: Service
metadata:
  name: my-clusterip-service
spec:
  type: ClusterIP
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

2. NodePort: Expose Service on Each Node’s IP

Overview:

NodePort builds on top of ClusterIP but extends accessibility by opening a specific port on each node in the cluster. This service type allows external traffic to access the service via the node’s IP address and a designated port.

Use Case:

NodePort is used when you want to expose your service outside the cluster, but you don’t want or need a load balancer. It can be handy for development environments or simple setups where direct access to node IPs is feasible.

Key Characteristics:

  • Fixed Port Range: NodePort assigns a port from the default range (30000–32767) on each node.

  • Cluster-wide Access: Any node in the cluster can accept traffic on the assigned port.

  • Limited Traffic Distribution: Traffic is routed to any node but not load-balanced like a LoadBalancer service.

Example YAML:

apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
spec:
  type: NodePort
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 32000

3. LoadBalancer: Expose via External Load Balancer

Overview:

LoadBalancer service type is designed for production environments where you want to expose a service to the outside world through an external load balancer. It builds upon NodePort and ClusterIP, but with added support from cloud providers (e.g., AWS, GCP, Azure) to provision a load balancer automatically.

Use Case:

This service type is often used for publicly exposed applications, such as a web app or API endpoint, where traffic needs to be evenly distributed across multiple pods for redundancy and scalability.

Key Characteristics:

  • Cloud Provider Integration: Automatically provisions an external load balancer through cloud infrastructure.

  • Direct External Access: The service is accessible via the load balancer’s external IP.

  • Load Balancing: Traffic is evenly distributed across multiple nodes and pods.

  • Higher Cost: LoadBalancers typically incur extra costs depending on the cloud provider.

Example YAML:

apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer-service
spec:
  type: LoadBalancer
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

4. ExternalName: Map Service to External DNS Name

Overview:

ExternalName service type is a unique kind of service that does not involve IP-based routing like the other types. Instead, it maps a service to an external DNS name, effectively acting as an alias for external services.

Use Case:

This service is useful when you need to access external services by DNS name, such as external databases, APIs, or third-party services, from within the cluster without using ClusterIP or NodePort.

Key Characteristics:

  • No Pods or Endpoints: Doesn’t route traffic within the cluster but simply maps a DNS name to an external service.

  • DNS Resolution: Pods within the cluster use Kubernetes DNS to resolve the external name.

  • No Load Balancing: No load balancing or traffic management is involved.

Example YAML:

apiVersion: v1
kind: Service
metadata:
  name: external-service
spec:
  type: ExternalName
  externalName: api.external-service.com

Key Differences and Use Cases:

Service TypeAccess ScopeUse CaseProsCons
ClusterIPInternalInternal microservice communicationSimple, fast internal routingNo external access
NodePortExternalExpose services on each node’s IP and portSimple external accessNot suitable for large-scale external traffic
LoadBalancerExternal (via Load Balancer)Production-grade external access via cloud LBCloud provider handles load balancing and accessExtra cost, tied to cloud provider
ExternalNameExternal DNSAccess external services by DNS from within the clusterSimplifies access to external servicesLimited use case, no traffic management

Task

1. Create a Service of type ClusterIP

First, create a Service named myapp of type ClusterIP that exposes port 80 and maps to the target port 80.

apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  type: ClusterIP
  selector:
    app: myapp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

2. Create a Deployment with 1 replica of nginx:1.23.4-alpine

Now, create a Deployment named myapp with 1 replica using the nginx:1.23.4-alpine image and exposing the container port 80.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: nginx
          image: nginx:1.23.4-alpine
          ports:
            - containerPort: 80

After creating the deployment, expose the container port using the same label selector as in the service.

3. Scale the Deployment to 2 replicas

To scale the deployment to 2 replicas, run the following command:

kubectl scale deployment myapp --replicas=2

This increases the number of pods running your nginx container to 2.

4. Create a Temporary Pod Using busybox and Run a wget Command

To create a temporary pod with the busybox image and run a wget command against the service, use the following command:

kubectl run busybox --rm -it --image=busybox -- /bin/sh

Once inside the container shell, find the ClusterIP of the service:

kubectl get svc myapp

Now run the wget command:

wget -O- <ClusterIP>:80

This command should display the HTML content served by your nginx service.

5. Run a wget Command Against the Service Outside the Cluster

Currently, the ClusterIP type service is not accessible from outside the cluster. You can verify that by trying to access it from an external machine using the service IP, but the connection will fail since it is an internal-only service.

6. Change the Service Type to Allow External Access

To allow external access to the service, change the service type to NodePort:

kubectl patch svc myapp -p '{"spec": {"type": "NodePort"}}'

Alternatively, update the YAML and apply it:

apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  type: NodePort
  selector:
    app: myapp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 32000  # This can be in the range 30000-32767

7. Run wget Against the Service from Outside the Cluster

Once the service is exposed via NodePort, you can access the service by using the IP address of any node in your Kubernetes cluster along with the NodePort assigned to the service (32000 in this example):

wget -O- <NodeIP>:32000

This command should retrieve the HTML page from the nginx server running inside your cluster.

Conclusion

Each Kubernetes service type has its own strengths and weaknesses, making them suitable for different scenarios. Choosing the right service depends on your needs: for internal communication, go with ClusterIP; for simple external access, consider NodePort; for production-grade external access, LoadBalancer is a great choice; and if you need to access external services, ExternalName fits the bill.

Understanding these options is crucial in deploying scalable, accessible, and reliable Kubernetes applications effectively.

References

Video

Documentation

0
Subscribe to my newsletter

Read articles from Rahul Vadakkiniyil directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rahul Vadakkiniyil
Rahul Vadakkiniyil