📖 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:
-
Frontend (ReactJS) → exposed via
LoadBalancer
-
Backend (Spring Boot or FastAPI) → exposed via
NodePort
-
Database (MySQL) → exposed via
ClusterIP
🧩 Application Architecture
+------------------+ +------------------+ +------------------+
| React Frontend | <---> | Backend (API) | <---> | MySQL DB |
| (LoadBalancer) | | (NodePort) | | (ClusterIP) |
+------------------+ +------------------+ +------------------+
↑
Public Internet
⚙️ 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
🧾 Service
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
type: ClusterIP
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
⚙️ 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"
🧾 Service
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
type: NodePort
selector:
app: backend
ports:
- port: 80
targetPort: 8080
nodePort: 30080
📌 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
🧾 Service
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
type: LoadBalancer
selector:
app: frontend
ports:
- port: 80
targetPort: 80
☁️ 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]
📌 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
🎯 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?