Skip to main content

Kubernetes Networking:

 Kubernetes Networking: Services (ClusterIP, NodePort, LoadBalancer) and Ingress

📅 Published: Feb 2026
⏱️ Estimated Reading Time: 18 minutes
🏷️ Tags: Kubernetes, K8s Networking, Services, Ingress, Load Balancing


Introduction: The Networking Challenge

In Kubernetes, Pods are ephemeral. They come and go. They restart. They scale up and down. Each time a Pod restarts, it gets a new IP address. This creates a fundamental problem: How do you reliably communicate with a set of Pods that are constantly changing?

Kubernetes solves this problem with Services. A Service provides a stable network endpoint (IP address and DNS name) that never changes, even as Pods come and go. It also load-balances traffic across healthy Pods.

Additionally, Services and Ingress work together to expose your applications to users outside the cluster, providing everything from simple port forwarding to sophisticated HTTP routing and TLS termination.

This guide explains how Services work, the different types you can use, and how Ingress provides advanced HTTP routing.


Part 1: The Pod Communication Problem

Pod IPs Are Ephemeral

Every Pod gets its own IP address. But these IP addresses are not stable:

  • When a Pod restarts, it gets a new IP

  • When a Deployment scales up, new Pods get new IPs

  • When a Pod moves to a different node, it gets a new IP

text
Before restart:
┌─────────────┐
│ Pod A       │
│ IP: 10.0.1.5│
└─────────────┘

After restart:
┌─────────────┐
│ Pod A       │
│ IP: 10.0.2.8│ ← completely different!
└─────────────┘

The Solution: Services

A Service sits in front of a set of Pods and provides:

  • Stable IP address: Never changes

  • Stable DNS name: Consistent for the life of the Service

  • Load balancing: Distributes traffic across healthy Pods

  • Health checking: Only sends traffic to ready Pods

text
Before Service:
Client → Pod IP (unstable)

After Service:
Client → Service IP (stable) → Pod A, Pod B, Pod C

Part 2: Services

What is a Service?

A Service is an abstraction that defines a logical set of Pods and a policy to access them. It enables loose coupling between dependent Pods.

Think of a Service as a stable "front desk" for your Pods. You tell clients to call the front desk. The front desk knows which Pods are available and directs traffic accordingly.

Service YAML Structure

yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: myapp           # Which Pods to target
  ports:
  - port: 80             # Port this Service listens on
    targetPort: 8080     # Port Pods are listening on
    protocol: TCP
  type: ClusterIP        # Service type

How Services Work

  1. Selector: The Service uses labels to find which Pods to target

  2. Endpoints: The Service maintains a list of Pod IPs matching the selector

  3. kube-proxy: On each node, kube-proxy creates network rules to forward traffic

  4. Load balancing: Traffic is distributed across healthy endpoints

text
┌─────────────────────────────────────────────────────────────┐
│                      Service                                 │
│                  selector: app=myapp                        │
│                    ClusterIP: 10.96.0.1                     │
│                                                             │
│   ┌─────────┐           ┌─────────┐      ┌─────────┐       │
│   │ Pod A   │           │ Pod B   │      │ Pod C   │       │
│   │ app=myapp│           │ app=myapp│      │ app=myapp│       │
│   │ 10.0.1.5│           │ 10.1.2.3│      │ 10.2.3.4│       │
│   └─────────┘           └─────────┘      └─────────┘       │
└─────────────────────────────────────────────────────────────┘

Part 3: Service Types

Kubernetes offers four types of Services, each serving a different use case.

Service Type Comparison

TypeCluster AccessExternal AccessUse Case
ClusterIPYesNoInternal services, backend APIs
NodePortYesYes (static port on each node)Basic external access, testing
LoadBalancerYesYes (cloud LB)Production external access
ExternalNameN/AVia DNS aliasAccessing external services

Type 1: ClusterIP (Default)

ClusterIP is the default Service type. It creates an internal IP address accessible only within the cluster.

Use when: You need communication between Pods, but external access is not required.

yaml
apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  type: ClusterIP              # Default, can be omitted
  selector:
    app: backend
  ports:
  - port: 8080
    targetPort: 8080
text
      ┌─────────────────────────────┐
      │      Kubernetes Cluster      │
      │                              │
      │  ┌─────────┐  ┌─────────┐   │
      │  │ Pod A   │  │ Pod B   │   │
      │  └────┬────┘  └────┬────┘   │
      │       │            │        │
      │       ▼            ▼        │
      │  ┌─────────────────────┐    │
      │  │   Service (ClusterIP)│    │
      │  │     10.96.0.1        │    │
      │  └──────────┬──────────┘    │
      │             │               │
      │             ▼               │
      │  ┌─────────────────────┐    │
      │  │      Frontend Pod    │    │
      │  └─────────────────────┘    │
      │                              │
      └──────────────────────────────┘
               No external access

Type 2: NodePort

NodePort builds on ClusterIP and adds external access. It opens a static port (30000-32767) on every node. Traffic to NodeIP:NodePort is forwarded to the Service.

Use when: You need simple external access, testing, or don't have a cloud load balancer.

yaml
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: NodePort
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30080          # Optional (Kubernetes assigns if omitted)
text
                    External User
                         │
                         │ http://any-node:30080
                         ▼
        ┌────────────────────────────────────────────┐
        │            Kubernetes Cluster               │
        │                                             │
        │  ┌─────────────┐  ┌─────────────┐          │
        │  │   Node 1    │  │   Node 2    │          │
        │  │             │  │             │          │
        │  │ ┌─────────┐ │  │ ┌─────────┐ │          │
        │  │ │ Pod A   │ │  │ │ Pod B   │ │          │
        │  │ └─────────┘ │  │ └─────────┘ │          │
        │  │             │  │             │          │
        │  │ NodePort    │  │ NodePort    │          │
        │  │ 30080       │  │ 30080       │          │
        │  └─────────────┘  └─────────────┘          │
        │           │              │                 │
        │           └──────┬───────┘                 │
        │                  ▼                         │
        │          ┌─────────────┐                   │
        │          │   Service   │                   │
        │          └─────────────┘                   │
        └────────────────────────────────────────────┘

Important: The nodePort range (30000-32767) is configurable and can be changed in the API server.


Type 3: LoadBalancer

LoadBalancer builds on NodePort and adds a cloud provider load balancer (AWS ELB, Azure LB, GCP LB). This is the standard way to expose services to the internet in production.

Use when: You need production-grade external access with a single IP address.

yaml
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
text
                    External User
                         │
                         │ http://load-balancer-ip
                         ▼
              ┌─────────────────────┐
              │   Cloud Load Balancer│
              │    (AWS ELB / GCP LB)│
              └──────────┬──────────┘
                         │
                         ▼
        ┌────────────────────────────────────────────┐
        │            Kubernetes Cluster               │
        │                                             │
        │  ┌─────────────┐  ┌─────────────┐          │
        │  │   Node 1    │  │   Node 2    │          │
        │  │  NodePort   │  │  NodePort   │          │
        │  │   30080     │  │   30080     │          │
        │  └──────┬──────┘  └──────┬──────┘          │
        │         │                │                 │
        │         └───────┬────────┘                 │
        │                 ▼                          │
        │         ┌─────────────┐                    │
        │         │   Service   │                    │
        │         └─────────────┘                    │
        │                 │                          │
        │         ┌───────┴────────┐                 │
        │         ▼                ▼                 │
        │  ┌───────────┐    ┌───────────┐            │
        │  │ Pod A     │    │ Pod B     │            │
        │  └───────────┘    └───────────┘            │
        └────────────────────────────────────────────┘

External IP allocation:

bash
# Get the external IP (may take a moment)
kubectl get service web-service
NAME          TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)
web-service   LoadBalancer   10.96.0.1      203.0.113.50      80:30080/TCP

# Now access your app at http://203.0.113.50

Type 4: ExternalName

ExternalName maps a Service to a DNS name outside the cluster. It does not have a selector or endpoints.

Use when: You want internal Pods to access external services using a consistent name.

yaml
apiVersion: v1
kind: Service
metadata:
  name: external-database
spec:
  type: ExternalName
  externalName: database.example.com

Now Pods can connect to external-database.default.svc.cluster.local and be routed to database.example.com.


Part 4: Ingress

What is Ingress?

While Services handle simple routing, Ingress provides sophisticated HTTP/HTTPS routing based on hostnames and URL paths. It acts as a "smart router" for external traffic entering your cluster.

Think of Ingress as the traffic controller at the entrance to your cluster. It looks at each request and decides: "This request for api.example.com/v1 should go to the API service. This request for example.com should go to the web service."

Ingress vs Service

AspectServiceIngress
ProtocolTCP/UDPHTTP/HTTPS only
RoutingIP:PortHostname + path
SSL/TLSManualNative support
Single IPOne per LoadBalancerMany services one IP
CostHigher (multiple LBs)Lower (one LB)
text
Before Ingress (multiple LoadBalancers):
┌─────────────────────────────────────────────────────────────┐
│              ┌─────────────┐  ┌─────────────┐               │
│              │ AWS ELB     │  │ AWS ELB     │               │
│              │ (Cost $)    │  │ (Cost $)    │               │
│              └──────┬──────┘  └──────┬──────┘               │
│                     │                │                       │
│              ┌──────▼──────┐  ┌──────▼──────┐               │
│              │ api-service │  │ web-service │               │
│              └─────────────┘  └─────────────┘               │
└─────────────────────────────────────────────────────────────┘

After Ingress (one LoadBalancer):
┌─────────────────────────────────────────────────────────────┐
│                       ┌─────────────┐                       │
│                       │ AWS ELB     │                       │
│                       │ (Cost $)    │                       │
│                       └──────┬──────┘                       │
│                              │                               │
│                       ┌──────▼──────┐                       │
│                       │   Ingress   │                       │
│                       └──┬───────┬──┘                       │
│                          │       │                          │
│                   ┌──────▼──┐ ┌──▼──────┐                   │
│                   │ api-    │ │ web-    │                   │
│                   │ service │ │ service │                   │
│                   └─────────┘ └─────────┘                   │
└─────────────────────────────────────────────────────────────┘

Ingress YAML Example

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - example.com
    secretName: example-tls
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080

How Traffic Flows with Ingress

text
External User
     │
     │ https://example.com/api/users
     ▼
┌─────────────────────────────────────────────────────────────┐
│                    Cloud Load Balancer                       │
│                         (AWS ELB)                            │
└─────────────────────────────┬───────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                      Ingress Controller                      │
│                     (Nginx / AWS ALB)                        │
│                                                             │
│   Checks: host = example.com, path = /api → api-service    │
│           host = example.com, path = / → web-service        │
└──────────────┬──────────────────────────────┬───────────────┘
               │                              │
               ▼                              ▼
    ┌──────────────────┐            ┌──────────────────┐
    │   api-service    │            │   web-service    │
    │   (ClusterIP)    │            │   (ClusterIP)    │
    └────────┬─────────┘            └────────┬─────────┘
             │                               │
             ▼                               ▼
    ┌──────────────────┐            ┌──────────────────┐
    │   api-pod-1      │            │   web-pod-1      │
    │   api-pod-2      │            │   web-pod-2      │
    └──────────────────┘            └──────────────────┘

Ingress Controllers

Ingress is just a specification. You need an Ingress Controller to implement it. Popular options:

ControllerBest ForFeatures
NGINX IngressGeneral purposeMost common, flexible
AWS ALB IngressAWS environmentsNative AWS integration
GCE IngressGoogle CloudNative GCP integration
TraefikMicroservicesDynamic configuration
HAProxy IngressPerformanceHigh throughput, low latency
ContourEnvoy-basedModern, high performance

Installing NGINX Ingress Controller

bash
# Install using Helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx

# Or using kubectl
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.0/deploy/static/provider/cloud/deploy.yaml

Part 5: Service Discovery

DNS in Kubernetes

Kubernetes has a built-in DNS service (CoreDNS). Every Service gets a DNS name automatically.

DNS naming pattern:

text
<service-name>.<namespace>.svc.cluster.local

Examples:

text
web-service.default.svc.cluster.local
api-service.production.svc.cluster.local
database.staging.svc.cluster.local

Pod-to-Service Communication

Pods can communicate with Services using the Service name:

bash
# From any Pod in the default namespace
curl http://web-service

# From any Pod in any namespace
curl http://web-service.default.svc.cluster.local

Headless Services

For stateful applications that need direct Pod access, create a headless Service (set clusterIP: None):

yaml
apiVersion: v1
kind: Service
metadata:
  name: stateful-service
spec:
  clusterIP: None
  selector:
    app: stateful-app
  ports:
  - port: 8080

Headless Services return Pod IPs instead of a single Service IP. Useful for StatefulSets.


Part 6: Network Policies

What are Network Policies?

Network Policies control traffic flow between Pods and external endpoints. They act as a firewall for your Pods.

By default, all Pods can communicate with all other Pods. Network Policies let you restrict this.

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-policy
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080

This policy only allows frontend Pods to access backend Pods on port 8080. All other traffic is denied.


Real-World Scenarios

Scenario 1: Three-Tier Web Application

A web application has three tiers: web, API, and database. Traffic flow: internet → web → API → database.

yaml
# Web Service (external access)
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 3000
---
# API Service (internal only)
apiVersion: v1
kind: Service
metadata:
  name: api-service
spec:
  type: ClusterIP
  selector:
    app: api
  ports:
  - port: 8080
    targetPort: 8080
---
# Database Service (internal only)
apiVersion: v1
kind: Service
metadata:
  name: database-service
spec:
  type: ClusterIP
  selector:
    app: database
  ports:
  - port: 5432
    targetPort: 5432

Scenario 2: Multiple Applications with Ingress

A team runs three applications on one cluster: example.com (main site), api.example.com (API), shop.example.com (store).

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-app-ingress
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - example.com
    - api.example.com
    - shop.example.com
    secretName: wildcard-tls
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080
  - host: shop.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: shop-service
            port:
              number: 3000

Scenario 3: Internal API with Strict Access

An internal API should only be accessible from the frontend namespace.

yaml
# Ingress (internal, not exposed to internet)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: internal-api-ingress
  annotations:
    nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/8"
spec:
  ingressClassName: nginx
  rules:
  - host: api.internal.company.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080

# Network Policy to restrict access
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-network-policy
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: frontend
    - ipBlock:
        cidr: 10.0.0.0/8
    ports:
    - protocol: TCP
      port: 8080

Summary

ComponentPurposeWhen to Use
Service (ClusterIP)Internal load balancingPod-to-Pod communication
Service (NodePort)Basic external accessTesting, no cloud LB
Service (LoadBalancer)Production external accessCloud environments
Service (ExternalName)External service aliasAccessing external services
IngressHTTP/HTTPS routingMulti-service web applications
NetworkPolicyTraffic restrictionSecurity, compliance

Decision Flow

text
Do you need external access?
├─ No → ClusterIP Service
└─ Yes
   ├─ Is it HTTP/HTTPS traffic?
   │  ├─ Yes → Ingress + ClusterIP Service
   │  └─ No → NodePort or LoadBalancer Service
   └─ Are you in the cloud?
      ├─ Yes → LoadBalancer Service
      └─ No → NodePort Service

Practice Questions

  1. Why do Kubernetes Pods need Services for stable communication?

  2. What is the difference between ClusterIP, NodePort, and LoadBalancer Service types?

  3. When would you use Ingress instead of a LoadBalancer Service?

  4. How do Pods discover the IP address of a Service?

  5. What is the purpose of Network Policies?


Learn More

Practice Kubernetes networking with hands-on exercises in our interactive labs:
https://devops.trainwithsky.com/

Comments

Popular posts from this blog

📊 Monitoring & Logging in Kubernetes – Tools like Prometheus, Grafana, and Fluentd

  Monitoring & Logging in Kubernetes – Tools like Prometheus, Grafana, and Fluentd Monitoring and logging are essential for maintaining a healthy and well-performing Kubernetes cluster. In this guide, we’ll cover why monitoring is important, key monitoring tools like Prometheus and Grafana, and logging tools like Fluentd to help you gain visibility into your cluster’s performance and logs. Shape Your Future with AI & Infinite Knowledge...!! Want to Generate Text-to-Voice, Images & Videos? http://www.ai.skyinfinitetech.com Read In-Depth Tech & Self-Improvement Blogs http://www.skyinfinitetech.com Watch Life-Changing Videos on YouTube https://www.youtube.com/@SkyInfinite-Learning Transform Your Skills, Business & Productivity – Join Us Today! 🚀 Introduction In today’s fast-paced cloud-native environment, Kubernetes has emerged as the de-facto container orchestration platform. But deploying and managing applications in Kubernetes is just half the ba...

How to Use SKY TTS: The Complete, Step-by-Step Guide for 2025

 What is SKY TTS? SKY TTS  is a free, next-generation  AI audio creation platform  that brings together high-quality  Text-to-Speech ,  Speech-to-Text , and a full suite of professional  audio editing tools  in one seamless experience. Our vision is simple — to make advanced audio technology  free, accessible, and effortless  for everyone. From creators and educators to podcasters, developers, and businesses, SKY TTS helps users produce  studio-grade voice content  without expensive software or technical skills. With support for  70+ languages, natural voices, audio enhancement, waveform generation, and batch automation , SKY TTS has become a trusted all-in-one toolkit for modern digital audio workflows. Why Choose SKY TTS? Instant Conversion:  Enjoy rapid text-to-speech generation, even with large documents. Advanced Voice Settings:   Adjust speed, pitch, and style for a personalized listening experience. Multi-...

Introduction to Terraform – The Future of Infrastructure as Code

  Introduction to Terraform – The Future of Infrastructure as Code In today’s fast-paced DevOps world, managing infrastructure manually is outdated . This is where Terraform comes in—a powerful Infrastructure as Code (IaC) tool that allows you to define, provision, and manage cloud infrastructure efficiently . Whether you're working with AWS, Azure, Google Cloud, or on-premises servers , Terraform provides a declarative, automation-first approach to infrastructure deployment. Shape Your Future with AI & Infinite Knowledge...!! Read In-Depth Tech & Self-Improvement Blogs http://www.skyinfinitetech.com Watch Life-Changing Videos on YouTube https://www.youtube.com/@SkyInfinite-Learning Transform Your Skills, Business & Productivity – Join Us Today! In today’s digital-first world, agility and automation are no longer optional—they’re essential. Companies across the globe are rapidly shifting their operations to the cloud to keep up with the pace of innovatio...