Black Friday · 27 Nov 2026

Up to 90% off selected certifications.

One time only offer for a very precious career goal. Limited coupons, waitlist first.

Free lesson · CKAD Prep Program · Module 6: Services and networking

Expose Apps with the Right Service Type

The developer's service question is always who calls this. Internal callers get ClusterIP, previews get NodePort, the world gets LoadBalancer or Ingress, and outside dependencies get ExternalName.

10 min reading

Objectives

  • Serve internal traffic on ClusterIP and prove the endpoints
  • Preview a release externally with NodePort without cloud machinery
  • Request external entry with LoadBalancer where the platform supports it
  • Reach outside names cleanly with ExternalName instead of hardcoded IPs

Why this matters

Wrong service types waste the most debuggable hours in app delivery: NodePorts committed to git, LoadBalancers that never provision on bare metal, hardcoded external IPs that rot. Choosing by caller keeps manifests portable across dev, staging and production, which is exactly what reviewers check.

Concepts

ClusterIP serves cluster callers on a stable virtual IP: the default and the right answer for service-to-service traffic. NodePort adds a node-wide port for human previews and lab access: convenient, unencrypted, unauthenticated, never the production front door. LoadBalancer asks the cloud for an external entry and populates it asynchronously: code for Pending as not-yet, not broken. ExternalName returns a CNAME for outside dependencies: config changes instead of manifest edits when the vendor moves.

Ports deserve precision: port is the Service's ear, targetPort is the container's ear, and naming targetPorts lets Deployments evolve container ports without touching Services. Endpoints prove every choice: no addresses means the selector is wrong regardless of type.

Worked example

API for cluster callers, preview for humans, vendor reached by name:

kubectl expose deployment api --port=80 --name=api
kubectl get endpoints api              # ready addresses: internal path proven
kubectl expose deployment api --port=80 --type=NodePort --name=api-preview
# preview at http://<node>:<nodeport>/ for humans only
apiVersion: v1
kind: Service
metadata: { name: vendor }
spec:
  type: ExternalName
  externalName: api.vendor.example
  ports: [{ port: 443 }]
# app calls https://vendor:443, vendor moves by editing one field

Each caller gets its proper door, and the app's code never names an infrastructure address except through these Services.

Exam notes

Fresh Services need fresh endpoints: check before declaring victory, every time. NodePort commits to manifests pin random high ports into git history: acceptable in tasks, flagged in reviews. And ExternalName ignores selectors entirely: endpoints stay empty by design, which is correct.

Quick check

A 4-question self-check. Your answers stay on your device, are never stored or sent. Only a passing score (for example 3 of 4) is saved, and only to unlock lesson progress: at least 3 correct is required before a lesson counts as complete. It never counts toward any certification assessment.

Lesson feedback

No published feedback yet.

Log in and complete the lesson to leave feedback.

Exercise

Expose a fictional 2-replica app for three callers (cluster service, human preview, outside vendor API) with the right type each. Show the endpoints proof for the internal one and state what breaks if the vendor changes address under each alternative design.

Pass criteria

All three types correct per caller; endpoints proof shown; vendor-change analysis favors ExternalName over hardcoded IPs with the one-field reason.

Sources

Log in to track progressFree account: stores only your lesson progress and quiz results.