Open-Source Wikis

/

Kubernetes

/

Primitives

/

Service

kubernetes/kubernetes

Service

A stable network identity for a (changing) set of Pods. The Service object is the API; kube-proxy is the data plane. EndpointSlice is what connects the two.

Where it lives

Concern Path
Public type staging/src/k8s.io/api/core/v1/types.go (type Service struct {...})
Validation pkg/apis/core/validation/validation.go
REST registry pkg/registry/core/service/
Strategy pkg/registry/core/service/strategy.go
Storage (with VIP and node-port allocators) pkg/registry/core/service/storage/
ClusterIP allocator pkg/registry/core/service/ipallocator/
NodePort allocator pkg/registry/core/service/portallocator/
Endpoints registry pkg/registry/core/endpoint/
EndpointSlice registry pkg/registry/discovery/endpointslice/
EndpointSlice controller pkg/controller/endpointslice/
Mirror controller pkg/controller/endpointslicemirroring/
Proxy backends pkg/proxy/{iptables,nftables,ipvs,winkernel}/

Fields

A typical Service:

apiVersion: v1
kind: Service
metadata: { name: web, namespace: shop }
spec:
  type: ClusterIP # ClusterIP | NodePort | LoadBalancer | ExternalName
  ipFamilyPolicy: SingleStack # SingleStack | PreferDualStack | RequireDualStack
  ipFamilies: [IPv4]
  clusterIPs: [10.96.0.42] # allocated by the apiserver
  selector: { app: web }
  ports:
    - name: http
      port: 80 # service port
      targetPort: 8080 # pod port
      protocol: TCP
  internalTrafficPolicy: Cluster # Cluster | Local
  externalTrafficPolicy: Cluster # for NodePort/LB only
  sessionAffinity: None
status:
  loadBalancer: {} # populated by the cloud-controller-manager for type=LoadBalancer

ClusterIP allocation

The apiserver allocates a unique ClusterIP at create time. The allocator is:

  • Bitmap allocator (legacy) in pkg/registry/core/service/ipallocator/bitmap.go — single in-memory bitmap protected by leader-elected reconciliation.
  • Multi-CIDR allocator in pkg/registry/core/service/ipallocator/cidrallocator.go — backed by ServiceCIDR resources, allowing dynamic addition of new ranges.

The ServiceCIDR controller (pkg/controller/servicecidrs/) reconciles in-flight CIDRs with the allocator state.

NodePort allocation

pkg/registry/core/service/portallocator/ allocates a unique port in the configured range (default 30000-32767). The same allocator pattern as ClusterIP — bitmap with periodic reconciliation against the database of existing Services.

EndpointSlice computation

When a Service has a selector, the EndpointSlice controller (pkg/controller/endpointslice/) computes the Pods that match and emits EndpointSlice resources:

graph LR
    Service -->|selector| Pods
    Pods -->|filter Ready| Eligible[Eligible endpoints]
    Eligible -->|topology hints| Slice[EndpointSlice]
    Slice -->|published| API[kube-apiserver]
    API --> Proxy[kube-proxy on each node]

Slices are bounded at 100 endpoints by default. Large Services produce many slices; updates only rewrite the affected slice.

Topology-aware routing

Each EndpointSlice endpoint can carry Hints.ForZones. kube-proxy reads the hints and prefers same-zone endpoints when:

  • The hints population is "sufficient" (> 50% of endpoints have hints).
  • Cluster-wide endpoint distribution is "balanced enough" (heuristic in pkg/proxy/topology.go).

When the heuristic fails (e.g., one zone has zero endpoints), the proxy falls back to cluster-wide routing.

Service types

Type Behaviour Implementation
ClusterIP In-cluster VIP only kube-proxy only
NodePort ClusterIP + a port on every node kube-proxy programs the node port
LoadBalancer NodePort + an external LB Cloud-controller-manager creates the LB
ExternalName DNS CNAME Resolved by CoreDNS only

type=LoadBalancer is special: the cloud-controller-manager's service controller (staging/src/k8s.io/cloud-provider/controllers/service) creates the LB and writes the LB's external IP/hostname to status.loadBalancer.ingress.

Headless Services

spec.clusterIP: None makes a Service headless. There's no VIP and no kube-proxy programming. CoreDNS responds to <service>.<ns>.svc.<cluster-domain> with A records for every endpoint. StatefulSets use this for stable per-Pod DNS via a parent headless Service.

Validation highlights

  • Port names unique within a Service.
  • targetPort may be a number or a name (resolved to the container's named port).
  • clusterIPs and ipFamilies consistent in length and ordering.
  • externalTrafficPolicy=Local only valid for NodePort and LoadBalancer.
  • internalTrafficPolicy may not equal Local for NodePort/LoadBalancer.

Key source files

File Purpose
staging/src/k8s.io/api/core/v1/types.go Public Service type
pkg/registry/core/service/strategy.go Service REST strategy
pkg/registry/core/service/storage/storage.go Service storage with allocators
pkg/registry/core/service/ipallocator/cidrallocator.go Multi-CIDR ClusterIP allocator
pkg/registry/core/service/portallocator/ NodePort allocator
pkg/controller/endpointslice/endpointslice_controller.go Endpoint slicing
pkg/proxy/topology.go Topology-aware routing
staging/src/k8s.io/cloud-provider/controllers/service/controller.go Service LB controller

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Service – Kubernetes wiki | Factory