spec.type decides who can reach a Service. Each type includes everything the one before it does.
ClusterIP (default)
inside the cluster only
Pod ──▶ 10.96.x.x:80 ──▶ PodsA virtual IP from the service range. Used for service-to-service traffic.
NodePort
outside ──▶ <any node IP>:3xxxx ──▶ 10.96.x.x:80 ──▶ PodsOpens the same port on every node, in the range 30000-32767. Still has a cluster IP. Check which port was allocated:
kubectl get svc market-web -o jsonpath='{.spec.ports[0].nodePort}'From this sandbox's shell, the node is 10.0.0.10, so curl http://10.0.0.10:<nodePort> reaches the Service.
LoadBalancer
outside ──▶ cloud load balancer IP ──▶ node:3xxxx ──▶ 10.96.x.x:80 ──▶ PodsAdds a request to the cloud provider for an external IP. In this sandbox there is no cloud controller, so EXTERNAL-IP stays <pending>. The NodePort and ClusterIP parts still work.
ExternalName
name.ns.svc.cluster.local ──▶ CNAME ──▶ db.example.comNo selector, no proxying. DNS returns the target name. Used to give an outside host an in-cluster name.
Setting the type
Either flag it at creation:
kubectl expose deployment market-web --port=80 --type=NodePortor set it in a manifest:
apiVersion: v1
kind: Service
metadata:
name: market-web
spec:
type: NodePort
selector:
app: market-web
ports:
- port: 80
targetPort: 80port is the Service's port. targetPort is the container's port. They are often equal; when they differ, the Service translates.