By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
You’re deploying a microservice in Kubernetes. Your app runs in Pods, but Pods are ephemeral—they die, respawn, and get new IPs. How do you expose your app to: - Other services inside the cluster? (e.g., a frontend talking to a backend) - External users? (e.g., a web app accessible via a browser) - A cloud load balancer? (e.g., AWS ALB, GCP LB)
This is where Kubernetes Services come in. They provide stable networking for Pods, abstracting away their dynamic IPs. The three most common Service types—ClusterIP, NodePort, and LoadBalancer—solve different problems:
Why this matters in production:- ClusterIP is the default—if you don’t specify a type, your service is only accessible internally. Forget this, and your frontend can’t talk to your backend.- NodePort is a quick way to expose a service for testing, but it’s not secure or scalable for production.- LoadBalancer is the go-to for cloud deployments, but it costs money (AWS ALB ~$16/month + data processing fees). Misconfigure it, and you’ll burn cash or expose your app to the internet unintentionally.
Real-world scenario:You inherit a Kubernetes cluster where a critical backend service is exposed via NodePort in production. This is a security risk (exposed on a high port) and not scalable (manual load balancing). You need to: 1. Migrate it to ClusterIP for internal traffic.2. Set up a LoadBalancer for external access.3. Ensure zero downtime during the switch.
This guide will show you how.
kubectl get endpoints
app: my-backend
kubectl describe svc <service-name>
Cluster
Local
service.spec.sessionAffinity: ClientIP
kubectl
# Create a Deployment with 3 Nginx Pods kubectl create deployment nginx --image=nginx --replicas=3 # Verify Pods are running kubectl get pods -o wide
Expected Output:
NAME READY STATUS RESTARTS AGE IP NODE nginx-7c6d8f6b5d-abc12 1/1 Running 0 10s 10.244.1.2 node-1 nginx-7c6d8f6b5d-def34 1/1 Running 0 10s 10.244.2.3 node-2 nginx-7c6d8f6b5d-ghi56 1/1 Running 0 10s 10.244.3.4 node-3
# clusterip-service.yaml apiVersion: v1 kind: Service metadata: name: nginx-clusterip spec: type: ClusterIP selector: app: nginx # Matches the Deployment's label ports: - protocol: TCP port: 80 # Service port targetPort: 80 # Pod port
Apply & Verify:
kubectl apply -f clusterip-service.yaml # Get the Service details kubectl get svc nginx-clusterip # Test internal access (from another Pod) kubectl run curl-test --image=curlimages/curl -it --rm -- sh curl http://nginx-clusterip:80 # Should return Nginx welcome page
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-clusterip ClusterIP 10.96.123.45 <none> 80/TCP 5s
Why this matters:- Internal microservices (e.g., frontend → backend) use ClusterIP.- No external access—secure by default.
# nodeport-service.yaml apiVersion: v1 kind: Service metadata: name: nginx-nodeport spec: type: NodePort selector: app: nginx ports: - protocol: TCP port: 80 # Service port targetPort: 80 # Pod port nodePort: 30080 # Optional: Manually set port (30000-32767)
kubectl apply -f nodeport-service.yaml # Get the Service details kubectl get svc nginx-nodeport # Access via Node IP + Port (replace <NODE_IP> with your Node's IP) curl http://<NODE_IP>:30080
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-nodeport NodePort 10.96.67.89 <none> 80:30080/TCP 5s
Why this matters:- Quick testing without a cloud load balancer.- Not for production—exposes high ports, no TLS, no scaling.
# loadbalancer-service.yaml apiVersion: v1 kind: Service metadata: name: nginx-loadbalancer spec: type: LoadBalancer selector: app: nginx ports: - protocol: TCP port: 80 # Service port targetPort: 80 # Pod port
kubectl apply -f loadbalancer-service.yaml # Get the Service details (wait ~1-2 mins for cloud LB to provision) kubectl get svc nginx-loadbalancer -w # Access via the LoadBalancer's external IP curl http://<EXTERNAL_IP>
Expected Output (AWS EKS):
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-loadbalancer LoadBalancer 10.96.123.45 a1234567890abcdef1234567890abcdef-123456789.us-west-2.elb.amazonaws.com 80:32456/TCP 2m
Why this matters:- Standard for production external access.- Cloud-provided load balancing (AWS ALB, GCP LB, etc.).- Costs money (~$16/month for AWS ALB).
kubectl delete svc nginx-clusterip nginx-nodeport nginx-loadbalancer kubectl delete deployment nginx
yaml # Example: AWS LoadBalancer with Security Group metadata: annotations: service.beta.kubernetes.io/aws-load-balancer-security-groups: "sg-12345678"
externalTrafficPolicy: Local
selector
app: my-service
app.kubernetes.io/name
app.kubernetes.io/version
kubectl run curl-test --image=curlimages/curl -it --rm -- sh
targetPort
externalTrafficPolicy
kubectl delete svc <service-name>
❌ NodePort/LoadBalancer (external access).
"You need to expose a service externally in AWS. What’s the simplest way?"
❌ NodePort (manual, not scalable).
"How do you preserve client IP in a LoadBalancer Service?"
❌ Default (Cluster) loses client IP.
"What’s the port range for NodePort?"
✅ 30000–32767 (default, configurable in kube-apiserver).
kube-apiserver
"Why would kubectl get endpoints show no IPs?"
kubectl describe svc
Challenge:You have a Deployment (my-app) with 2 Pods. Create a ClusterIP Service that routes traffic to port 8080 on the Pods. Then, test connectivity from a temporary curl Pod.
my-app
8080
curl
Solution:
# 1. Create the Service kubectl expose deployment my-app --port=80 --target-port=8080 --type=ClusterIP # 2. Test connectivity kubectl run curl-test --image=curlimages/curl -it --rm -- sh curl http://my-app:80
Why it works:- kubectl expose auto-creates a Service with the correct selector labels.- target-port=8080 maps the Service port (80) to the Pod port (8080).
kubectl expose
target-port=8080
80
kubectl expose deployment <name> --port=80 --target-port=8080
kubectl expose deployment nginx --port=80 --target-port=80
kubectl get svc
kubectl describe svc <name>
kubectl describe svc nginx
kubectl get endpoints nginx
nodePort: 30080
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
sessionAffinity: ClientIP
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.