Kubernetes From Zero to Hero – Part 6: Exposing Your Applications with Kubernetes Services


Quick Recap – Where We Are
In the last blog, we:
Understood how Deployments manage ReplicaSets and Pods
Learned to scale applications manually
Performed rolling updates without downtime
Saw how Kubernetes ensures self-healing by replacing failed Pods
But all this happens within the cluster. What if we want the outside world (users, clients, APIs) to access our app?
That’s where Kubernetes Services come in.
Why Do We Need a Service?
Let’s say you deployed 3 replicas of an Nginx Pod.
These pods:
Get dynamic IPs that change on restart
Are managed by a ReplicaSet
Cannot be accessed reliably unless we know their IPs (which we don’t)
Problem:
No static endpoint to reach your app.
Solution:
Create a Service, which provides:
A stable IP
A DNS name
Load balancing across Pods
Types of Kubernetes Services
Type | Use Case | Accessible From |
ClusterIP | Default, internal-only communication | Inside cluster only |
NodePort | Expose on a port on each Node | External via <NodeIP>:<Port> |
LoadBalancer | Uses cloud provider’s external LB | Internet (if cloud-based) |
ExternalName | Maps to external DNS | Inside cluster |
When to Use What?
Situation | Use Type |
Pod-to-pod communication | ClusterIP |
Local testing from browser or Postman | NodePort |
Production deployment on cloud | LoadBalancer |
Talk to external DB/service via DNS | ExternalName |
Example: Exposing Nginx via NodePort
nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080
Apply it:
kubectl apply -f nginx-service.yaml
Check service:
kubectl get svc
Access the App (Minikube)
If you’re using Minikube:
minikube service nginx-service
It will open the URL in your browser.
If not using Minikube, open:
http://<NodeIP>:30080
You can get Node IP by:
kubectl get nodes -o wide
ClusterIP Example (Internal Only)
Used by backends or services that should not be exposed publicly.
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
type: ClusterIP
selector:
app: backend
ports:
- port: 8080
targetPort: 8080
DNS in Kubernetes
Kubernetes assigns DNS records for services automatically.
If you have a service called backend-service in namespace dev, it can be accessed by:
http://backend-service.dev.svc.cluster.local
This works inside the cluster only.
Bonus: Headless Service
Want service without load balancing, just for DNS?
Use:
clusterIP: None
Used in stateful apps like Kafka, Elasticsearch, etc.
Summary
Concept | Role in App Exposure |
Service | Stable network identity for Pods |
ClusterIP | Internal-only service |
NodePort | Exposes app via each node’s IP and port |
LoadBalancer | Creates external cloud-based endpoint |
DNS | Built-in DNS for service discovery |
What’s Next?
In the next post, we’ll explore:
What is Ingress and why it’s better than NodePort/LoadBalancer
How to install Ingress controllers
Route traffic to multiple apps using clean URLs
It’s time to bring the NGINX Ingress Controller into the mix and build a proper gateway for your cluster.
Subscribe to my newsletter
Read articles from Manas Upadhyay directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Manas Upadhyay
Manas Upadhyay
I am an experienced AWS Cloud and DevOps Architect with a strong background in designing, deploying, and managing cloud infrastructure using modern automation tools and cloud-native technologies.