Skip to main content

Command Palette

Search for a command to run...

Demystifying Kubernetes Services: Why Deployments Aren't Enough

Updated
6 min read
Demystifying Kubernetes Services: Why Deployments Aren't Enough
J
IT Professional with 4+ years of combined experience across Software Engineering, DevOps, Cloud, Technical Writing, and AI-assisted Development. Passionate about building things, simplifying complex technology, and continuously learning while sharing knowledge through hands-on experimentation and technical writing.

If you are deploying applications in Kubernetes, you quickly learn that spinning up a bare Pod is rarely done in production. Instead, we use Deployments to manage our application lifecycle.

But here’s the harsh reality: A Deployment alone isn't enough to make your application robust, reachable, or scalable. For that, you need a Kubernetes Service (SVC).

In this post, we’re going to look into the absolute fundamentals of Kubernetes Services. We will break down the "Why" and "How" behind Load Balancing, Service Discovery, and Networking.

🛑 The Nightmare Scenario: A Cluster with No Services

To understand why we need Services, let’s discard all abstraction and imagine a Kubernetes cluster that doesn't have them.

As a DevOps engineer, you write a YAML file and deploy an application using a Deployment. The Deployment talks to a ReplicaSet, which handles the actual scaling mechanics. Let's say you're requirement dictates 3 replicas to handle concurrent user traffic.

Why do we need multiple replicas?

Think about scale. If thousands of concurrent users try to access an application (like WhatsApp or Google) at the exact same fraction of a second, a single Pod will instantly buckle and crash under the load. We increase replicas based on the highest number of requests a single Pod can handle before it fails.

Suppose a single pod fails after serving 10 requests, it can handle 10 concurrent users. If the number of concurrent users rises by 100 and one pod can manage 10 requests, we need to increase the replicas by 10.

The Dynamic IP Catch

Containers are ephemeral by design. Let's say one of your three Pods (Pod 1 with IP 172.16.3.4) crashes due to an internal bug or network hiccup.

Because Kubernetes boasts built-in Auto-Healing, the ReplicaSet controller detects the failure and immediately spins up a brand-new Pod copy to restore the count to three.

Here is the catch: The new Pod will not inherit the old IP address. It gets a completely fresh internal IP, say 172.16.3.8.

If there are no Services in your cluster, you have to manually distribute these shifting Pod IP addresses to your QA testing teams or internal dependent microservices.

When Pod 1 dies and restarts, your testing team will immediately ping you saying: "Hey, your application is down!". You check your cluster dashboard, see 3 green Pods, and argue: "No, it's running perfectly fine!".

Neither of you is wrong. You implemented auto-healing successfully, but the testing team is still trying to access the old, dead IP address (172.16.3.4) while your live Pod is sitting on 172.16.3.8.

Real-world tech companies don't hand out individual, volatile IP addresses to different batches of users. They provide a single, unchanging gateway. In Kubernetes, that gateway is a Service.

⚡ Core Advantage 1: True Load Balancing

Instead of making users or internal teams target specific Pod IPs, you use a Service (SVC) as a layer on top of your Deployment.

When you set up a Service, Kubernetes assigns it a fixed, static name and internal IP address (e.g., payment.default.svc). Your testing teams or external clients will always interact with this single address.

When traffic reaches the Service, kube-proxy decides which Pod gets the request.

Historically, when kube-proxy uses iptables mode, the distribution is approximately random. When using IPVS mode, algorithms such as Round Robin, Least Connections, etc., can be used.

So, Kubernetes Service itself provides basic load distribution among Pods.

Behind the scenes, the Service acts as a traffic police, evenly distributing incoming concurrent requests across all of your underlying, healthy Pod instances.

🔍 Core Advantage 2: Dynamic Service Discovery

If Pod IPs change all the time, how does the Service itself keep track of them without breaking?

It does not track them by IP addresses. Instead, Kubernetes handles this dynamically using Labels and Selectors.

When you create a Service, you tell it to watch out for that exact label:

apiVersion: v1
kind: Service
metadata:
  name: web-app-service
spec:
  type: NodePort
  selector:
    app: payment # This must perfectly match the Pod template label!
  ports:
    - port: 80
      targetPort: 8000 # The port your container listens on
      nodePort: 30007  # Exposes the service on the host node port
  • Labels: Text-based key-value metadata tags assigned to your Pods inside the Deployment configuration (e.g., app: payment).

  • Selectors: A query configuration defined inside your Service, instructing it to: "Find and direct traffic to any Pod that carries the label app: payment."

When a Pod fails, the ReplicaSet uses the same original YAML template to create a new one. This means the new Pod has the same app: payment label.

The Service does not care that the IP address changed from .4 to .8. It dynamically discovers the newborn Pod instantly because it carries the matching label tag.

🌐 Core Advantage 3: Exposing Applications to the Outside World

By default, everything running inside a Kubernetes cluster is locked inside an internal, isolated network. You cannot expect a retail customer on the internet to VPN or SSH into your worker nodes just to use your app.

To determine who gets access, Kubernetes Services provide three distinct entry points:

Deep Dive: How They Route Traffic

  1. ClusterIP: This is the baseline setting. It gives you internal load balancing and service discovery but completely isolates the application from external eyes.

  2. NodePort: This opens a dedicated port (ranging from 30000–32767) directly on every single Worker Node machine. Anyone inside your local network can call Node_IP:Static_Port to drop straight into your Pod.

  3. LoadBalancer: When you deploy this to a cloud provider (like AWS EKS or GCP GKE), Kubernetes hooks into the cloud provider's API. It automatically provisions an enterprise external cloud load balancer (like an AWS Network Load Balancer) with a public IP address. Traffic flows from the internet user, hits the cloud provider balancer, passes into the Kubernetes service, and targets your healthy Pods seamlessly.

Minikube Tip: If you run a LoadBalancer type service locally on Minikube, it will remain in a <pending> state indefinitely. This happens because your local laptop lacks the native cloud APIs to spin up an enterprise load balancer. For local engineering, we bypass this exposure roadblock using Ingresses.

📝 Key Takeaways

To recap our deep dive, a Kubernetes Service provides the missing architectural pillars required for cloud-native applications:

  • Load Balancing: Seamlessly distributes high-volume concurrent traffic across multi-pod replicas.

  • Service Discovery: It uses separate Labels and Selectors to keep traffic routing unaffected by temporary Pod failures.

  • Application Exposure: Provides detailed network control to keep applications internal (ClusterIP), share them within an organization (NodePort), or make them accessible worldwide (LoadBalancer).

Happy Orchestrating! 🧊

More from this blog

D

Demystifying Tech with Jasai

102 posts

Demystifying Tech with Jasai is a blog dedicated to breaking down complex tech concepts into clear, beginner-friendly explanations. Covering DevOps, Docker, Git, AWS, CI/CD, Networking, and core programming fundamentals, it emphasizes strong foundations before advanced topics. Through step-by-step walkthroughs and real-world analogies, it simplifies the why behind the how — making technology approachable, structured, and built for long-term growth.