DEV Community

DevCorner2
DevCorner2

Posted on

πŸš€ Using ClusterIP, NodePort, and LoadBalancer in a Real-World Kubernetes Application

πŸ“– Overview

Kubernetes provides multiple ways to expose your applications running inside Pods. The most commonly used Service types are:

  • ClusterIP – internal communication
  • NodePort – external access via node IP and port
  • LoadBalancer – production-grade public access via cloud load balancer

In this blog, we’ll build a real-world E-commerce Web App with:

  1. Frontend (ReactJS) β†’ exposed via LoadBalancer
  2. Backend (Spring Boot or FastAPI) β†’ exposed via NodePort
  3. Database (MySQL) β†’ exposed via ClusterIP

🧩 Application Architecture

+------------------+       +------------------+       +------------------+
|  React Frontend  | <---> |  Backend (API)   | <---> |     MySQL DB     |
| (LoadBalancer)   |       |  (NodePort)      |       |  (ClusterIP)     |
+------------------+       +------------------+       +------------------+
       ↑
  Public Internet
Enter fullscreen mode Exit fullscreen mode

βš™οΈ 1. MySQL Service (ClusterIP)

πŸ”Ή Why ClusterIP?

We don’t want the database to be accessible from outside. It should be reachable only by internal Pods like the backend.

🧾 Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:5.7
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: password
          ports:
            - containerPort: 3306
Enter fullscreen mode Exit fullscreen mode

🧾 Service

apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  type: ClusterIP
  selector:
    app: mysql
  ports:
    - port: 3306
      targetPort: 3306
Enter fullscreen mode Exit fullscreen mode

βš™οΈ 2. Backend API Service (NodePort)

πŸ”Ή Why NodePort?

For non-production use or internal teams, we may want to access the backend using the node's external IP and a fixed port.

🧾 Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - name: backend
          image: mycompany/backend:latest
          ports:
            - containerPort: 8080
          env:
            - name: DB_HOST
              value: "mysql"
Enter fullscreen mode Exit fullscreen mode

🧾 Service

apiVersion: v1
kind: Service
metadata:
  name: backend
spec:
  type: NodePort
  selector:
    app: backend
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30080
Enter fullscreen mode Exit fullscreen mode

πŸ“Œ Access via http://<NodeIP>:30080


βš™οΈ 3. Frontend Service (LoadBalancer)

πŸ”Ή Why LoadBalancer?

This service needs to be accessed publicly by customers, so we use LoadBalancer to provision a cloud load balancer.

🧾 Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
        - name: frontend
          image: mycompany/frontend:latest
          ports:
            - containerPort: 80
Enter fullscreen mode Exit fullscreen mode

🧾 Service

apiVersion: v1
kind: Service
metadata:
  name: frontend
spec:
  type: LoadBalancer
  selector:
    app: frontend
  ports:
    - port: 80
      targetPort: 80
Enter fullscreen mode Exit fullscreen mode

☁️ Cloud providers like AWS, GCP, and Azure will assign a public IP to this service.


πŸ”„ Application Flow

+---------------------------+
|    Public Internet        |
+------------+-------------+
             ↓
     [LoadBalancer Service]
             ↓
       [Frontend Pod]
             ↓
     [NodePort to Backend]
             ↓
     [ClusterIP to MySQL]
Enter fullscreen mode Exit fullscreen mode

πŸ“Œ Summary Table

Component Service Type Exposed To Access Method
MySQL ClusterIP Internal Pods DNS: mysql:3306
Backend NodePort Devs / Node IP http://<NodeIP>:30080
Frontend LoadBalancer Public Internet http://<external-ip>

βœ… Best Practices

  • Use ClusterIP for internal-only services (e.g., DBs, caches).
  • Use NodePort sparinglyβ€”only for development, testing, or where cloud load balancer isn't an option.
  • Use LoadBalancer in production for services needing public access.
  • Use Ingress Controllers and domain routing when dealing with multiple LoadBalancer services.
  • Add liveness and readiness probes for all deployments.
  • Parameterize all ports, replicas, and resource limits using Helm charts for reusability.

πŸ“¦ Bonus: Ingress Alternative

If you want to expose multiple services under one domain, consider using an Ingress Controller instead of multiple LoadBalancers.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ecommerce-ingress
spec:
  rules:
    - host: frontend.mysite.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend
                port:
                  number: 80
Enter fullscreen mode Exit fullscreen mode

🎯 Conclusion

Understanding and using the right Kubernetes Service type is key to building scalable, secure, and manageable cloud-native apps.

Need Use This Service
Internal access only ClusterIP
Basic external access NodePort
Cloud-managed public access LoadBalancer

Most tech companies β€” especially those building secure, scalable, cloud-native applications β€” follow this common architecture pattern when using Kubernetes:


βœ… Industry-Standard Approach (Used by Most Tech Companies)

πŸ” Backend = ClusterIP

  • Not exposed to the public
  • Only accessible internally by the frontend
  • Protects business logic and APIs from direct attack
  • Communication via internal DNS (e.g., http://backend:8080)

🌐 Frontend = LoadBalancer or Ingress

  • Exposed to the public Internet
  • Acts as the only entry point to the system
  • Sends requests to backend over internal network

πŸ—„οΈ Database = ClusterIP

  • Always kept internal
  • Accessed only by backend

🧠 Why This Architecture Is Preferred

Benefit Description
Security Minimizes attack surface; only the frontend is public
Control & Monitoring Easier to monitor and throttle access through a single public endpoint
Scalability You can scale frontend/backend independently
Compliance Meets security standards (SOC 2, ISO 27001, etc.) by isolating sensitive services

🏒 Real-World Examples

Company Approach Used
Netflix Frontend via edge gateway + service mesh; backends internal
Airbnb Load balancer to frontend + ClusterIP for internal APIs
Stripe Ingress controller at edge + everything else via ClusterIP
Shopify Uses Envoy/Gloo mesh at the edge, then internal ClusterIP
Amazon (AWS) ALB/NLB at edge β†’ internal services over private VPCs

🧾 Optional: Using an Ingress Controller

Most companies also place an Ingress controller (like NGINX, Traefik, or Istio Gateway) in front of the frontend to manage:

  • SSL termination
  • URL path routing
  • Rate limiting
  • Authentication

πŸ” Pro Tip: Zero Trust Model

Larger orgs go a step further with:

  • mTLS between services
  • Network Policies to restrict pod communication
  • Service Mesh (like Istio or Linkerd) for traffic control, observability, and security

βœ… TL;DR: What Most Tech Companies Use

Component Service Type Publicly Exposed? Typical Practice
Frontend LoadBalancer / Ingress βœ… Yes Public entry point
Backend ClusterIP ❌ No Internal-only, accessed by frontend
Database ClusterIP ❌ No Internal-only, accessed by backend

Would you like a production-grade setup with Helm, Ingress, TLS, and best practices bundled into one YAML or chart?

Top comments (0)