Kubernetes Services and Ingress: Types and Routing

Master Kubernetes service types and Ingress controllers to expose your applications inside and outside the cluster with proper load balancing and routing.

published: reading time: 29 min read author: GeekWorkBench updated: October 2, 2026
Quick Summary

Kubernetes Services give changing Pods stable network endpoints, and controllers expose those endpoints to external clients. This guide compares ClusterIP, NodePort, LoadBalancer, headless Services, and HTTP routing, including endpoint discovery, traffic paths, and common production failures. Use its decision tables and checks to choose an exposure model and trace issues from the client to the Pod.

Kubernetes Services and Ingress: Types and Routing

Pods in Kubernetes are ephemeral. They get IP addresses assigned when they start and those addresses change when pods reschedule. If you want your application to be reachable, you need something stable. Kubernetes Services provide that stability by creating a persistent endpoint for a set of pods.

This post covers the four service types, when to use each one, and how Ingress controllers extend routing beyond simple port forwarding.

If you need to understand the basics of Kubernetes first, check the Kubernetes fundamentals post. For advanced networking patterns, see the Advanced Kubernetes post.

Introduction

Pod IPs change when pods reschedule. If your app depends on a fixed address, it breaks constantly. Kubernetes Services give you a stable virtual IP that load-balances across matching pods, which is what makes microservices actually work in practice.

External traffic is a separate problem. Kubernetes gives you four service types and Ingress resources for different exposure patterns. Picking the wrong one costs money (over-provisioned load balancers) or creates weird URLs that users cannot reach. Getting it right means understanding how traffic actually flows from the outside world to your container.

This post covers the four service types, when to use each, and how Ingress controllers add HTTP routing on top. You will see how a request travels from a user to your pod, the trade-offs between each approach, and how to fix the most common networking problems you will hit in production.

Service Types Comparison

Kubernetes offers four service types:

Decision Matrix: Choosing the Right Service Type

Access Scenario Service Type Example
Internal microservice-to-microservice ClusterIP API to database
Expose single node for debugging NodePort Dev environment access
Production HTTP/HTTPS traffic Ingress Web app frontend
TCP/UDP without Ingress complexity LoadBalancer Custom protocol, legacy apps
Cross-cluster service discovery ExternalName Integrate external service

Skip NodePort for production HTTP services. The port range (30000-32767) is awkward, and node IPs change in dynamic clusters.

Skip LoadBalancer per microservice. One load balancer per team or product boundary is usually enough. Provisioning a cloud LB for every pod gets expensive fast.

ClusterIP is internal only. If you need external access, ClusterIP is not your answer.

Traffic Flow Architecture

Here is how a request moves from an external user down to a pod:

flowchart TD
    User([External user]) --> DNS[DNS]
    DNS --> EdgeLB[External endpoint or load balancer]
    EdgeLB --> Ingress[Gateway or Ingress controller]
    Ingress --> ClusterIP[ClusterIP Service]
    ClusterIP --> Pods[Ready backend Pods]
    User --> NodePortURL[Node IP and NodePort]
    NodePortURL --> NodePortService[NodePort Service]
    NodePortService --> Pods
    User --> ProviderLB[Provider load balancer]
    ProviderLB --> LBService[LoadBalancer Service]
    LBService --> Pods

These are alternative exposure paths. An HTTP route commonly reaches a Gateway or Ingress controller, then a ClusterIP Service; a provider load balancer may be one way to expose that controller.

NodePort and a LoadBalancer Service expose a Service through different mechanisms. Their exact data paths depend on the cluster’s service proxy and cloud integration.


Service Types Overview

Type Access Scope Use Case
ClusterIP Internal only Microservices within the cluster
NodePort Exposes on each node IP Development, simple external access
LoadBalancer External via cloud LB Production external access
ExternalName Maps to external DNS Integrating external services

ClusterIP is the default. You get an internal cluster IP that pods can use to communicate with each other. The other types expose services outside the cluster.

ClusterIP for Internal Access

ClusterIP is the most common service type. It creates an internal IP that load-balances traffic across all matching pods. Other pods in the cluster use the service name to reach your application.

apiVersion: v1
kind: Service
metadata:
  name: api-backend
  namespace: production
spec:
  type: ClusterIP
  selector:
    app: api-backend
    version: v2
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 8080
    - name: grpc
      protocol: TCP
      port: 50051
      targetPort: 50051

The targetPort can be a number or a name that matches the container port. Using names makes it easier to update ports without changing the service.

Within the cluster, pods access the service using its fully qualified name:

http://api-backend.production.svc.cluster.local

Or just the service name if they are in the same namespace:

http://api-backend

DNS is automatic. Kubernetes maintains a DNS entry for every service.

Headless Services for StatefulSets

Set clusterIP: None to create a headless service. Instead of load balancing, DNS returns the pod IPs directly. This is useful for StatefulSets where clients need to discover individual pod addresses.

apiVersion: v1
kind: Service
metadata:
  name: postgres-cluster
  namespace: database
spec:
  clusterIP: None
  selector:
    app: postgres
  ports:
    - port: 5432

With a headless service, DNS queries return A records for each pod: postgres-cluster-0.postgres-cluster.database.svc.cluster.local, and so on.

NodePort for Development

NodePort opens a port on every node in the cluster. Traffic arriving at http://<node-ip>:<node-port> gets routed to the service. The port range defaults to 30000-32767.

apiVersion: v1
kind: Service
metadata:
  name: web-frontend-nodeport
spec:
  type: NodePort
  selector:
    app: web-frontend
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080

Setting nodePort is optional. Kubernetes assigns one from the default range if you omit it.

NodePort is useful for development and for implementations that need node-level targets. It opens a high port on nodes and does not provide host- or path-based HTTP routing by itself; external load balancing and firewall behavior depend on the surrounding infrastructure.

LoadBalancer with Cloud Controllers

On a cluster with a compatible load balancer implementation, type: LoadBalancer requests an external load balancer for the Service. Target type, health checks, supported protocols, and TLS termination depend on the controller and provider.

apiVersion: v1
kind: Service
metadata:
  name: web-frontend-lb
  namespace: production
spec:
  type: LoadBalancer
  selector:
    app: web-frontend
  ports:
    - port: 80
      targetPort: 80
    - port: 443
      targetPort: 443

For example, the AWS Load Balancer Controller can select an NLB with spec.loadBalancerClass: service.k8s.aws/nlb or controller-specific annotations, and target mode determines whether it registers nodes or Pod IPs. Health checks and source-IP behavior depend on that mode and its target-group settings. Do not copy provider annotations between controllers; check the AWS Load Balancer Controller annotation reference.

With the AWS Load Balancer Controller, an NLB TLS listener can use a certificate ARN and an explicit TLS port, for example:

annotations:
  service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:us-east-1:123456789:certificate/abc123"
  service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"

Ingress Controllers and Rules

Ingress is not a Service type. It is a Kubernetes API for HTTP/HTTPS routing rules, and an Ingress controller implements them. The Ingress API remains stable but is frozen; Kubernetes recommends Gateway API for new designs. The community ingress-nginx controller retired in March 2026, so the NGINX annotations below are legacy examples for understanding existing configurations, not a recommendation for new deployments. Controller annotations are implementation-specific.

See the Kubernetes Ingress documentation and Gateway API documentation when choosing a current controller and API. The Kubernetes ingress-nginx retirement notice explains the March 2026 end of community maintenance.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
  namespace: production
spec:
  ingressClassName: nginx
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /users
            pathType: Prefix
            backend:
              service:
                name: users-api
                port:
                  number: 80
          - path: /products
            pathType: Prefix
            backend:
              service:
                name: products-api
                port:
                  number: 80
    - host: admin.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: admin-console
                port:
                  number: 80
  tls:
    - hosts:
        - api.example.com
        - admin.example.com
      secretName: example-com-tls

The ingressClassName field specifies which controller handles the Ingress. Check that the selected controller is supported and that its behavior matches the API features your routes use.

Path rewriting

Backend services rarely expose the same path structure as your Ingress routes. A frontend at example.com/users might proxy to an API that expects /users at its root. Without path rewriting, requests to /api/v1/users arrive at the backend as /api/v1/users, and the backend returns 404 because it only knows about /users.

For an existing community ingress-nginx deployment, path rewriting uses controller-specific annotations. New deployments should use a supported controller or Gateway API implementation.

annotations:
  nginx.ingress.kubernetes.io/use-regex: "true"
  nginx.ingress.kubernetes.io/rewrite-target: /$2

The $2 holds the second captured group from a regex path. Pair it with use-regex: "true" and pathType: ImplementationSpecific:

annotations:
  nginx.ingress.kubernetes.io/use-regex: "true"
  nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /api/v1(/|$)(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: users-api
                port:
                  number: 80

Requests to /api/v1/users hit the backend as /users. Requests to /api/v1/products/42 hit the backend as /products/42. The regex (.*) passes everything after /api/v1/ as-is, preserving query strings and nested paths.

This pattern shows up constantly when migrating from a monolith. You can route /api/v2/* to the new service and /legacy/* to the old one, rewriting paths to match whatever contract each backend expects.

Rate limiting with legacy ingress-nginx annotations

Rate limiting is controller-specific. In existing community ingress-nginx deployments, limit-rps limits requests per second and limit-connections limits concurrent connections per client IP, per controller replica. The project retired in March 2026, so do not start a new deployment on these annotations.

annotations:
  nginx.ingress.kubernetes.io/limit-rps: "10"
  nginx.ingress.kubernetes.io/limit-connections: "5"

These limits are calculated per controller replica, so adding replicas increases the effective per-client allowance. Exceeding a request or connection limit returns 503 by default; the controller’s limit-req-status-code setting can change the response code. Do not assume the response includes Retry-After. A 503 can also indicate an upstream failure, so correlate it with controller metrics and logs.

The limit-burst-multiplier annotation changes the burst size as a multiplier of the configured request rate; the default multiplier is 5. It is not a fixed number of extra requests, so calculate the effective burst from the RPS setting and test the chosen policy under expected traffic.

The client address comes from the controller’s trusted proxy configuration. Clients behind the same NAT may share one limit. Scope these annotations to the appropriate Ingress resource; for identity-based limits, use a supported gateway or rate-limiting service that authenticates the identity.

Security Considerations

Services enable connectivity, but you should restrict which pods can communicate with which. Kubernetes Network Policies (covered in a separate post) let you enforce microsegmentation between pods.

For HTTP/HTTPS exposure, use a supported Gateway API implementation or an existing Ingress controller with TLS where it fits your platform. Both depend on a controller for routing and certificate handling; NodePort alone does not provide those features.

Avoid creating a separate LoadBalancer for every HTTP Service without checking cost, isolation, and provider capabilities. A shared Gateway or Ingress controller may consolidate entry points, while separate load balancers can be appropriate for protocol support, isolation, or ownership boundaries.

Observability Checklist

Check the service path from the cluster edge to the selected pods, not just whether the Service object exists:

  • Confirm the Service selector matches the intended pods and its EndpointSlices contain ready endpoints.
  • Watch request rate, latency, and error rate at the Ingress or load balancer and at the backend.
  • Alert on sustained 5xx responses, connection failures, and backends with no ready endpoints.
  • Track load balancer provisioning events and cloud quota or health-check failures.
  • Check DNS resolution and service discovery after pod rescheduling or rollout.

Security and Compliance Notes

Expose only the services that need external access. Use standard ports and TLS at the ingress boundary, then apply NetworkPolicy or another supported control to limit pod-to-pod paths. Keep administrative endpoints private and avoid relying on an obscure NodePort as an access control.

For regulated workloads, record which services handle sensitive data, where TLS terminates, and which identities can reach each backend. Review load balancer and ingress rules alongside Kubernetes policies; a cluster-level policy does not automatically cover traffic filtered before it reaches a pod. Map these settings to the applicable audit requirements and retain evidence of periodic review. The configuration supports compliance work but does not certify the environment by itself.

Trade-off Analysis

ClusterIP vs Headless Services

The difference between ClusterIP and headless comes down to who manages pod discovery. With ClusterIP, Kubernetes gives you a stable virtual IP and load-balances traffic across all matching pods. Your client hits one address and Kubernetes handles the rest. With headless (clusterIP: None), there is no virtual IP. DNS returns individual pod A records instead, and your client is responsible for tracking which pods exist and picking one.

Aspect ClusterIP Headless (ClusterIP: None)
Endpoint selection Service proxy chooses ready endpoints (implementation-specific) Clients resolve and select pod addresses
DNS resolution Single service IP Multiple A records (one per pod)
Use case Stateless microservices StatefulSets, leader election
Client complexity Low High

For stateless services, ClusterIP is almost always the right choice. Your client does not need to know which pod is which. For StatefulSets, headless is necessary because pods have stable identities — a PostgreSQL replica needs to know it is connecting to postgres-cluster-1, not just any available pod. The client also needs to track which pod is primary for writes versus read-only replicas.

With ClusterIP, clients reconnect to the Service IP and the cluster’s service proxy selects an eligible endpoint. With headless, clients must handle DNS changes and choose among pod addresses; application-level leader election remains the workload’s responsibility. Use headless discovery when clients need per-pod identity.

Service Type Selection Trade-offs

Each service type maps to a specific access pattern. Pick the wrong one and you either limit your traffic or pay for something you do not need.

Exposure model Pros Cons or considerations
ClusterIP Internal Service address Not externally routable by default
NodePort Works without a cloud load balancer High port on nodes; external routing is separate
LoadBalancer Requests provider-managed external access Cost and behavior vary by implementation
Ingress HTTP host/path routing Requires a supported controller; API is frozen
Gateway API Extensible, role-oriented routing API Requires Gateway API CRDs and an implementation

ClusterIP is the usual choice for internal traffic: API to database, frontend to backend, worker to queue. Its virtual IP is routable within the cluster by default; use network controls for isolation.

NodePort exposes a high port on each node and is often used as a target behind another load balancer. It does not provide HTTP host/path routing by itself; whether it fits production depends on the external routing and firewall design.

Use a LoadBalancer Service when the provider integration or protocol needs a dedicated external listener. For HTTP/HTTPS, an Ingress or Gateway implementation can share routing infrastructure, but account for its availability and capacity as a shared dependency.

Ingress controllers route HTTP/HTTPS by host and path. Gateway API is the recommended direction for new Kubernetes routing designs; the choice of implementation determines TLS handling, sharing, and operations.

Ingress vs LoadBalancer per Service

Sharing an HTTP entry point can reduce load balancer count, but compare cost and quota with the operational impact of a shared controller.

Criteria Ingress Controller One LoadBalancer per Service
Cost Shared infrastructure costs Separate infrastructure costs
SSL management Centralized Per-service or per-LB
HTTP/HTTPS routing Path-based, host-based Port-based only
Operational overhead Controller deployment Cloud quota management

Provider quotas and prices vary by account, region, load balancer type, and traffic. Check current limits and pricing for your environment rather than planning around fixed examples. A shared controller can reduce frontend resources, but it also becomes a shared failure and capacity boundary.

SSL management is simpler with Ingress too. You store one certificate per hostname and the controller terminates TLS for every backend service behind it. With per-service LBs, you either terminate SSL at the LB (each one needs its own certificate) or at the backend (each service handles its own certs, more operational work).

Dedicated load balancers can make sense for non-HTTP protocols, static addressing, or isolation requirements. Kubernetes Service type alone does not guarantee a particular layer or feature set; check the controller’s supported protocols and routing model.

For new HTTP/HTTPS designs, evaluate a supported Gateway API implementation as well as existing Ingress options. Compare resource cost, controller support, failure isolation, and migration needs.

Production Failure Scenarios

ClusterIP Service Not Reachable After Pod Restart

When a pod restarts, its IP changes. If your application hardcodes pod IPs instead of using the ClusterIP service name, communication breaks.

Symptoms: Pod-to-pod communication fails after restarts, Connection refused errors.

Diagnosis:

kubectl get pod -o wide  # Check pod IPs
kubectl get endpointslices -n <namespace> -l kubernetes.io/service-name=<service-name>
kubectl describe pod <pod-name>  # Check status

Mitigation: Always use the ClusterIP service DNS name for pod-to-pod communication, never pod IPs.

NodePort Service Port Conflicts

When two services request the same nodePort value, Kubernetes rejects the second one with nodePort port is already allocated. This sneaks into clusters through hardcoded ports in Helm charts or kustomization overlays that nobody validated against existing allocations. In GitOps workflows, the conflict only shows up at apply time, not at render time, so code review misses it.

To diagnose an active conflict, filter services by nodePort in the 30000-32767 range:

kubectl get svc -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.type}{"\t"}{.spec.ports[*].nodePort}{"\n"}{end}' | grep -v '<none>'

The output lists every service with an assigned nodePort. When provisioning a new service, pick a free port or omit nodePort entirely and let Kubernetes assign one. Conflicts only happen when two manifests hardcode the same value.

Prevention across teams requires a shared allocation record. Some teams keep a ConfigMap with reserved ports and owners. Others skip NodePort entirely and use LoadBalancer or Ingress, which removes manual port management from the picture. If you run NodePort in a multi-tenant cluster, treat nodePort allocations like ephemeral port ranges: assign them centrally and never hardcode them in definitions that migrate between environments.

LoadBalancer Service Stays Pending

On cloud providers, LoadBalancer provisioning can fail due to quota limits, missing IAM permissions, or unsupported service configurations.

Symptoms: the Service’s EXTERNAL-IP remains <pending> or events show provisioning errors.

Diagnosis:

kubectl describe service <name> -n <namespace>
# Check events for error messages
kubectl get events --sort-by='.lastTimestamp' -n <namespace>

Mitigation: Check events, controller logs, permissions, quotas, and the provider-specific Service configuration. Confirm which controller owns the Service before changing annotations.

Common Pitfalls / Anti-Patterns

Exposing Services Directly Without Ingress

Do not create a separate external load balancer for every HTTP Service without checking current cost and quota. A shared Gateway or Ingress can reduce frontend resources, but it also concentrates capacity and failure risk. Keep separate entry points where protocol support, isolation, addressability, or ownership requires them, and verify current provider pricing and limits.

Using NodePort in Production

NodePort allocates a port from a fixed range (30000-32767) on every node in the cluster. When a pod receives traffic, kube-proxy routes it from that high port to the target pod. This sounds convenient for dev environments, but the model breaks down in production for several reasons.

The port range itself is the first problem. Standard HTTP is 80 or 443. Users hitting https://example.com:31234 see a port that looks like a VPN or proxy. Corporate firewalls routinely block non-standard ports, dropping traffic silently before it reaches your cluster. In regulated industries with strict outbound policies, high ports may be blocked entirely.

Node IP stability is the second problem. In managed Kubernetes (EKS, GKE, AKS), nodes live in an auto-scaling group. When scale-in events occur, terminated nodes return their IPs to the VPC pool and new nodes pick up different ones. Your NodePort service still exposes port 30080 on the new IPs, but any DNS records or firewall rules pointing to old node IPs go stale. You either maintain a dynamic discovery layer or accept intermittent outages during node churn.

Security is the third concern. Opening a port on every node means your service is reachable from anywhere in the cluster network. If nodes share a subnet with other workloads, a compromised pod can hit the NodePort directly, bypassing your Ingress controller’s authentication layer entirely. ClusterIP and Ingress shrink this attack surface by only exposing services through explicitly routed paths.

For local development, NodePort is fine. For anything beyond a quick demo, use Ingress with a proper HTTP/HTTPS stack or a LoadBalancer for TCP services. The routing clarity, SSL termination, and firewall-friendliness of standard ports justifies the extra setup time.

Skipping Health Checks on Headless Services

StatefulSets give pods stable identities: postgres-0 is always the primary, postgres-1 and postgres-2 are replicas. Clients querying the headless service DNS get all pod IPs and must pick one. Without health checks, clients can try to write to a pod that is still replaying WAL segments, causing failed queries, split-brain, or worse depending on the database.

Use a readinessProbe that reflects whether the pod can serve its intended role. Without one, Kubernetes can consider a container ready once it is running, even if database recovery is unfinished. A simple SELECT 1 only confirms that PostgreSQL accepts a query; it does not establish that a replica is caught up or that a pod is the write leader. Headless Service DNS normally follows endpoint readiness unless publishNotReadyAddresses changes that behavior.

spec:
  containers:
    - name: postgres
      readinessProbe:
        exec:
          command:
            - sh
            - -c
            - "psql -h localhost -U postgres -c 'SELECT 1' -q"
        initialDelaySeconds: 10
        periodSeconds: 5
        failureThreshold: 3

failureThreshold: 3 requires three consecutive probe failures before the probe reports failure; the probe period and timeout determine the delay. Tune readiness to the database recovery process and avoid overly aggressive checks that make endpoints flap.

Liveness probes serve a different purpose: they restart a container when it is stuck, not when it is merely unready. Do not use max_connections or statement_timeout as restart or failover controls; database high availability and recovery need their own mechanisms.

Quick Recap Checklist

  • Confirm the Service type fits the access pattern, and trace traffic from the client through the load balancer or Ingress to the backend pods.
  • Check the Service selector and EndpointSlices to confirm they list the intended, ready pod endpoints.
  • Verify that an Ingress controller is running for HTTP/HTTPS routing; use a Service to expose the backend it routes to.
  • Check pod readiness probes and health-check results so unready pods do not receive traffic.
  • Review NetworkPolicy rules in both directions to confirm the client, Ingress controller, and backend are allowed to communicate.

Interview Questions

1. What is the difference between ClusterIP, NodePort, and LoadBalancer service types in Kubernetes?

Expected answer points:

  • ClusterIP provides internal-only access within the cluster — only other pods can reach it
  • NodePort exposes the service on a high port (30000-32767) on every node's IP — useful for dev but not production HTTP
  • LoadBalancer provisions an external cloud load balancer (AWS ELB, GCP LB, Azure LB) for production external access
  • Ingress is not a service type but a routing layer for HTTP/HTTPS with host and path-based rules
2. How does kube-proxy route traffic to pods behind a ClusterIP service?

Expected answer points:

  • The cluster's service proxy watches Services and their EndpointSlices; some network implementations provide a replacement for kube-proxy.
  • The proxy implements the virtual Service IP using its supported dataplane, such as iptables, nftables, IPVS, or an integrated eBPF implementation.
  • Endpoint selection and connection behavior depend on that implementation; do not assume round-robin or random selection.
  • When ready endpoints change, the control plane updates EndpointSlices and the dataplane converges.
3. What is a headless service and when would you use it?

Expected answer points:

  • A headless service is created by setting `clusterIP: None`
  • No ClusterIP is assigned — DNS returns individual pod A records instead
  • Clients can discover pod IPs directly for StatefulSet workloads where each pod needs a stable identity
  • Useful for leader election, master-slave database setups, and scenarios requiring direct pod-to-pod communication
4. What is the purpose of the `targetPort` field in a Service definition?

Expected answer points:

  • targetPort specifies the port on the pod that receives traffic
  • It can be a number or a named port matching the container's port definition
  • Using named ports makes updates easier — changing the container port does not require changing the service
  • If omitted, targetPort defaults to the `port` value
5. Why should you avoid using NodePort for production HTTP services?

Expected answer points:

  • NodePort uses a non-standard port range (30000-32767) that is not typical for end users
  • Node IPs are dynamic in managed clusters — using them requires additional discovery or stable host entries
  • No HTTP host/path routing or centralized TLS termination by NodePort itself
  • External load balancing and traffic policy must be configured separately
6. How does an Ingress controller differ from a LoadBalancer service?

Expected answer points:

  • Ingress is a Kubernetes resource; an Ingress controller is the implementation that acts on it
  • Ingress provides HTTP/HTTPS host and path rules; the Ingress API is frozen, and Kubernetes recommends Gateway API for new designs
  • A Service of type LoadBalancer requests an external load balancer; supported protocols and features depend on its provider/controller
  • A shared Gateway or Ingress controller can route to multiple Services, trading fewer frontends for a shared capacity and failure boundary
7. What annotations are commonly used with AWS LoadBalancer services?

Expected answer points:

  • Annotations are controller-specific. With AWS Load Balancer Controller, `service.beta.kubernetes.io/aws-load-balancer-type: "external"` is used in annotation-based controller selection; supported setups may instead select it with `spec.loadBalancerClass`.
  • `service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"` registers Pod IPs as NLB targets when the cluster networking supports it; `instance` targets nodes.
  • `service.beta.kubernetes.io/aws-load-balancer-ssl-cert` and `...aws-load-balancer-ssl-ports` configure certificate-backed TLS listeners when supported by that controller.
  • Confirm current annotation names and defaults in the documentation for the installed controller and version.
8. What happens to client connections when a backend pod behind a ClusterIP service terminates?

Expected answer points:

  • The EndpointSlice controller removes or marks the endpoint unready, and the service proxy updates its dataplane.
  • In-flight requests may fail or reset; graceful termination and connection draining affect the result.
  • New connections are sent to remaining ready endpoints after the dataplane converges.
  • Clients should handle transient failures safely, with bounded retries for operations that are safe to repeat.
9. How does `sessionAffinity` work in a Kubernetes Service?

Expected answer points:

  • `None` is the default; backend selection is handled by the cluster's service proxy.
  • `ClientIP` asks the proxy to keep connections from the same client IP on the same endpoint for the configured timeout.
  • This can help protocols that need connection affinity, but clients behind a shared NAT may map to the same affinity key.
  • Affinity is not application session state and cannot guarantee an endpoint remains available.
10. What are the limitations of Kubernetes Services for east-west traffic management?

Expected answer points:

  • Services do not provide fine-grained traffic control (canary releases, traffic splitting)
  • No built-in circuit breaking, retry policies, or rate limiting at the service mesh level
  • NetworkPolicies provide L3/L4 isolation but not L7 traffic management
  • Service mesh solutions (Istio, Linkerd) extend Services with L7 control, mTLS, and observability
11. How do you troubleshoot a ClusterIP service that is not routing traffic to pods?

Expected answer points:

  • List current EndpointSlices: `kubectl get endpointslices -n -l kubernetes.io/service-name=` and check ready addresses.
  • Check pod selector labels match: `kubectl describe service ` shows selector
  • Verify pods are running and ready: `kubectl get pods -l app=`
  • Check the service proxy or CNI dataplane logs and rules for programming issues
  • Test connectivity from another pod using the service DNS name
12. What is the difference between `LoadBalancer` and `ClusterIP` service type regarding external traffic?

Expected answer points:

  • ClusterIP is routable within the cluster network by default.
  • LoadBalancer asks a compatible provider/controller to provision external access to the Service.
  • External address, target mode, protocols, and cost depend on the implementation.
  • Use ingress or Gateway routing for HTTP paths when its supported features and operational model fit.
13. Can a single Ingress resource handle multiple hostnames? How?

Expected answer points:

  • Yes — an Ingress spec can contain multiple `rules` entries, each with a different `host`
  • Each host can have its own set of paths routing to different backend services
  • A single TLS block can cover multiple hosts via multiple entries in the `hosts` list
  • Wildcard hosts (e.g., `*.example.com`) match one DNS label below `example.com`; they do not match the apex or multiple nested labels
14. How does pathType: Prefix differ from pathType: Exact in Ingress?

Expected answer points:

  • Exact match: URL path must match the path string exactly (e.g., `/users` matches only `/users`)
  • Prefix match: URL path must have the prefix at the start (e.g., `/users` matches `/users`, `/users/123`, `/users/foo/bar`)
  • `pathType` is required in the stable Ingress API. `Prefix` is explicit and matches path elements, not arbitrary string prefixes.
  • Exact is useful when you need strict path boundaries and no unintended prefix matching
15. How can you check whether a Service has ready backends?

Expected answer points:

  • List EndpointSlices in the Service namespace using the `kubernetes.io/service-name` label.
  • Inspect endpoint addresses and their readiness conditions rather than relying only on pod phase.
  • Check that the Service selector matches the intended pod labels and that readiness probes pass.
  • The legacy Endpoints API is deprecated; use EndpointSlices for current tooling.
16. What does `externalTrafficPolicy: Local` do on a LoadBalancer service and what are its trade-offs?

Expected answer points:

  • `Local` limits Service forwarding to node-local endpoints and avoids source NAT by the Kubernetes Service proxy on that path.
  • The external load balancer must health-check or target nodes that have ready local endpoints; integration behavior varies.
  • Uneven pod placement can create uneven traffic or leave nodes without usable local endpoints.
  • Verify client-IP behavior end to end with the chosen load balancer and target mode before relying on it for logs or policy.
17. How do you configure health checks for a Kubernetes Service?

Expected answer points:

  • Pod `readinessProbe` controls whether the Pod is considered ready for Service endpoints; a failed readiness probe does not restart the container.
  • `livenessProbe` can trigger a container restart after repeated failures; it should detect a stuck process, not ordinary load.
  • Provider load balancer health checks are configured separately through the relevant controller or provider integration.
  • Probe types include `exec`, `httpGet`, and `tcpSocket`; choose checks that test the condition needed for traffic.
18. What are EndpointSlices and how do they improve on the original Endpoints object?

Expected answer points:

  • EndpointSlices represent Service endpoints in separate resources so updates can scale without one large Endpoints object.
  • The control plane creates up to 100 endpoints per slice by default; this limit is configurable up to 1000.
  • Endpoint data can include fields such as hostname, node name, zone, and routing hints where populated.
  • The legacy Endpoints API was deprecated in Kubernetes v1.33; service proxies consume EndpointSlices as their endpoint source.
19. What is the purpose of `service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"` annotation?

Expected answer points:

  • The annotation specifies that the NLB should route directly to pod IPs (IP target) rather than node IPs (instance target)
  • IP target mode routes directly to Pod IPs and avoids an extra node hop.
  • Client source-IP preservation is not guaranteed by IP target mode; AWS NLB IP targets disable it by default unless configured through target-group attributes.
  • Confirm address-family, CNI, health-check, and target-group requirements in the installed AWS Load Balancer Controller documentation.
  • This mode requires the AWS VPC CNI plugin and works with pods that have ENIs attached in the VPC subnet
20. How does Kubernetes DNS (CoreDNS) handle service discovery and what record types does it create?

Expected answer points:

  • CoreDNS creates A records for ClusterIP services: `..svc.cluster.local` resolves to the ClusterIP
  • For headless services (`clusterIP: None`), DNS returns addresses for eligible Pod endpoints; readiness and `publishNotReadyAddresses` affect which endpoints are published
  • SRV records are created for named ports: `...svc.cluster.local`
  • ExternalName services create CNAME records pointing to the external FQDN specified

Further Reading

Conclusion

Kubernetes Services provide stable endpoints for applications as Pods change. ClusterIP supports in-cluster access, while NodePort and LoadBalancer expose traffic through different network paths whose details depend on the cluster and provider. Ingress remains a stable but frozen API; Kubernetes recommends Gateway API for new HTTP/HTTPS routing designs.

Start with ClusterIP for internal traffic. For external HTTP/HTTPS access, select a supported Gateway API implementation or maintain an existing Ingress controller based on its lifecycle and capabilities. Choose LoadBalancer when its provider-specific behavior, protocol support, or isolation fits the service.

Understanding these networking primitives helps you design services that are reachable, scalable, and secure. For deeper Kubernetes networking concepts like Network Policies, see the Advanced Kubernetes post.

Category

Related Posts

Kubernetes Network Policies: Practical Pod Security

Implement microsegmentation in Kubernetes using Network Policies to control traffic flow between pods and enforce zero-trust networking.

#kubernetes #network-policies #security

Cloud Security: IAM, Network Isolation, and Encryption

Implement defense-in-depth security for cloud infrastructure—identity and access management, network isolation, encryption, and security monitoring.

#cloud #security #iam

Container Security: Image Scanning and Vulnerability Management

Implement comprehensive container security: from scanning images for vulnerabilities to runtime security monitoring and secrets protection.

#container-security #docker #kubernetes