Skip to main content
Kubernetes beginner Lesson 5 of 8

Kubernetes Services — Hands-On

Hands-on understanding of how Services work: ClusterIP, labels/selectors, Ingress, and service discovery via DNS.

Connecting Pods with a Service

Here is a complete end-to-end example: a Deployment whose Pods are exposed by a Service.

# full-example.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web          # ← Service selects on this label
    spec:
      containers:
        - name: nginx
          image: nginx:1.25
          ports:
            - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web              # ← match Pods with label app=web
  ports:
    - port: 80
      targetPort: 80
  type: ClusterIP
kubectl apply -f full-example.yaml

# Confirm pods and service are up
kubectl get pods,svc

# Test internal connectivity
kubectl run curl-test --rm -it --image=curlimages/curl -- curl http://web-service

Service Discovery via DNS

Kubernetes automatically assigns DNS entries for every Service.

# Format: <service>.<namespace>.svc.cluster.local
# From inside any pod in the same namespace:
curl http://web-service            # short name works
curl http://web-service.default    # with namespace
curl http://web-service.default.svc.cluster.local  # fully qualified

# Cross-namespace call
curl http://payments.finance.svc.cluster.local
# Debug DNS resolution
kubectl run dns-debug --rm -it --image=busybox -- sh
# Inside:
nslookup web-service
nslookup web-service.default.svc.cluster.local

Exposing Externally with NodePort

# service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: web-nodeport
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 80
      nodePort: 31000     # accessible at <any-node-ip>:31000
  type: NodePort
kubectl apply -f service-nodeport.yaml

# minikube convenience URL
minikube service web-nodeport --url

Ingress — HTTP Routing to Multiple Services

Ingress lets you route traffic by hostname or URL path using a single external IP.

# Enable the ingress addon (minikube)
minikube addons enable ingress
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - host: myapp.local
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-service     # route /api → api-service
                port:
                  number: 80
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-service     # route / → web-service
                port:
                  number: 80
kubectl apply -f ingress.yaml

# Check ingress status (ADDRESS column shows external IP once assigned)
kubectl get ingress

# Test (add myapp.local to /etc/hosts pointing to minikube IP first)
minikube ip   # get the IP
echo "$(minikube ip) myapp.local" | sudo tee -a /etc/hosts
curl http://myapp.local/api
curl http://myapp.local/

Port Forwarding (Local Dev)

No need to expose a service externally just to test it locally.

# Forward local port 8080 → pod port 80 (good for one-off debugging)
kubectl port-forward pod/my-pod 8080:80

# Forward via service (load-balances across pods)
kubectl port-forward service/web-service 8080:80

# Now accessible at http://localhost:8080

Service Debugging Checklist

# 1. Are pods running and Ready?
kubectl get pods -l app=web

# 2. Do pod labels match the service selector?
kubectl describe service web-service | grep -A2 Selector
kubectl get pods --show-labels

# 3. Are endpoints populated?
kubectl get endpoints web-service
# Empty endpoints = selector mismatch or pods not Ready

# 4. Can another pod reach the service?
kubectl run probe --rm -it --image=curlimages/curl -- curl http://web-service

# 5. Check events for errors
kubectl describe service web-service

Learning Outcomes

You can:

  • Deploy a Service alongside a Deployment end-to-end
  • Use DNS names for internal service-to-service calls
  • Choose the right Service type for each access pattern
  • Configure Ingress for HTTP routing on a single external IP
  • Debug connectivity issues systematically

Frequently Asked Questions

What does ClusterIP mean?
ClusterIP exposes the Service internally inside the cluster on a virtual IP. It's the default Service type and the right choice for pod-to-pod communication.
What is Ingress and when should I use it instead of LoadBalancer?
Ingress routes HTTP/HTTPS traffic to multiple services based on host or path rules using a single external IP. LoadBalancer provisions one external IP per service. Use Ingress to avoid paying for multiple cloud LBs.