Exposing Services

Choose ClusterIP, NodePort, LoadBalancer, or Ingress depending on who needs to reach your app.

There are several ways to make a workload reachable, from internal-only to public.

TypeReachable fromTypical use
ClusterIPInside the cluster onlyApp-to-app traffic
NodePortAny node IP on a high portQuick external access
LoadBalancerExternal IP (ServiceLB on k3s)Exposing a single service
IngressHostname / path via TraefikMany HTTP services on port 80/443

For web apps, an Ingress is usually the cleanest choice. For a single non-HTTP service, a LoadBalancer or NodePort is simpler.

Example

Example · bash
# Quickly expose a Deployment as a NodePort service
kubectl expose deployment web \
  --type=NodePort --port=80 --target-port=8080

# See the assigned node port
kubectl get svc web

When to use it

  • A developer uses ClusterIP to keep a database service reachable only inside the cluster while exposing the frontend via an Ingress.
  • An ops team uses NodePort to give QA testers direct access to a staging service on a specific port without configuring DNS.
  • A production operator combines a LoadBalancer Service with Traefik Ingress to terminate TLS at the ingress layer while letting ServiceLB handle IP assignment.

More examples

Expose a Deployment as NodePort

Creates a NodePort Service that maps a random cluster port to the pod's port 3000, reachable on any node IP.

Example · bash
kubectl expose deployment my-app \
  --type=NodePort \
  --port=80 \
  --target-port=3000
kubectl get svc my-app

Create a ClusterIP service manifest

Defines a ClusterIP Service for a database so only pods within the cluster can reach port 5432.

Example · yaml
apiVersion: v1
kind: Service
metadata:
  name: backend
spec:
  type: ClusterIP
  selector:
    app: backend
  ports:
  - port: 5432
    targetPort: 5432

Test service connectivity in-cluster

Launches a throwaway pod to test that a ClusterIP service is reachable by DNS name from within the cluster.

Example · bash
kubectl run curl-test --image=curlimages/curl --rm -it --restart=Never -- \
  curl -s http://backend:5432
kubectl delete pod curl-test --ignore-not-found

Discussion

  • Be the first to comment on this lesson.