Kubernetes Service Spec Structure
Kubernetes Service Spec Structure defines how services are created and managed, specifying type, selector, and port mappings within a cluster.
Kubernetes Service Spec Structure refers to the schema and field-level composition of the spec block within a Service manifest, defining exactly how selector matching, port mapping, session behavior, and external exposure are expressed as structured YAML fields rather than free-form configuration. Understanding this structure precisely is necessary to author Services correctly, since small structural mistakes, such as mismatched port names, produce Services that appear valid but silently fail to route traffic.
Top-Level Spec Fields
selector
The selector field is a label query matched against pod labels; every pod whose labels satisfy the selector becomes a candidate backend for the Service. A Service with an empty or absent selector is not matched against pods automatically and instead expects its Endpoints to be managed manually or by an external controller.
spec:
selector:
app: ledger-api
tier: backend
type
The type field determines the Service's exposure model and defaults to ClusterIP when omitted. Valid values are ClusterIP, NodePort, LoadBalancer, and ExternalName, each changing how the remaining spec fields are interpreted, most notably externalName, which is only meaningful when type is ExternalName.
spec:
type: ClusterIP
ports
The ports field is a list of port mapping entries, each of which may specify a name, the externally-facing port, the targetPort on the backing pod, and optionally a protocol (defaulting to TCP). When a Service defines more than one port, every entry must have a unique name, since the name is what higher-level resources such as Ingress use to reference a specific port unambiguously.
spec:
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
- name: grpc
port: 9090
targetPort: 9090
protocol: TCP
targetPort as Name or Number
targetPort may reference either a numeric container port or a named port declared in the pod's container spec, and using a named targetPort is generally more resilient, since it allows the actual container port number to change without requiring a corresponding Service update, as long as the pod's named port declaration is updated consistently.
containers:
- name: ledger-api
ports:
- name: api-port
containerPort: 8080
---
spec:
ports:
- port: 80
targetPort: api-port
Session and Traffic Behavior Fields
sessionAffinity
The sessionAffinity field controls whether repeated requests from the same client are routed to the same backing pod. Its default value, None, distributes each connection independently; setting it to ClientIP pins a client's connections to the same pod for the configured timeout window, which is used when a workload maintains connection-local state that would break if requests were spread across different pods.
spec:
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
externalTrafficPolicy
For NodePort and LoadBalancer Services, externalTrafficPolicy determines whether external traffic is routed to any node regardless of whether it hosts a backing pod (Cluster, the default, which preserves even load distribution but obscures the original client IP) or only to nodes that actually host a backing pod (Local, which preserves the client's source IP but can produce uneven load distribution).
spec:
externalTrafficPolicy: Local
Type-Specific Fields
clusterIP and clusterIPs
The clusterIP field can be left unset for automatic allocation, explicitly set to a specific address for a stable, pre-known virtual IP, or set to None to declare a headless Service. The plural clusterIPs field exists to support dual-stack clusters, holding both an IPv4 and IPv6 address simultaneously.
spec:
clusterIP: None
nodePort
Within each ports entry, an explicit nodePort value can be set for NodePort and LoadBalancer Services to pin a specific external port across all nodes; if omitted, Kubernetes allocates one automatically from the configured node port range.
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
nodePort: 30080
externalName
Exclusive to ExternalName Services, this field holds the DNS name that internal lookups of the Service name are aliased to, and no selector, ports, or clusterIP fields are meaningful in this mode.
spec:
type: ExternalName
externalName: partner-provider.example.com
Structural Validation Considerations
Port Name Uniqueness Across a Multi-Port Service
Because Ingress and other consumers reference Service ports by name when a Service exposes more than one port, omitting names or duplicating them across entries produces a Service that validates syntactically but cannot be referenced unambiguously by name-based consumers, only by relying on port number, which is more fragile to maintain over time.
Selector and Pod Template Label Alignment
The spec's selector field must be a subset of the labels present on the pod template it targets; extra labels on the pod beyond what the selector requires are harmless, but any selector key absent from the pod's labels results in that pod never being selected as a backend.