| |

LFCE 141 ๐Ÿง Kubernetes โ€” Ingress Basics

โฑ๏ธ Estimated read: 11 min | |

An Ingress is a Kubernetes resource that defines HTTP and HTTPS routing rules for services inside the cluster. It is not a load balancer and it does not expose anything by itself. The Ingress resource is a declaration of intent: requests for api.example.com/v1 should go to the api-v1 Service, and requests for api.example.com/v2 should go to the api-v2 Service. The component that reads that declaration and configures the actual routing is the Ingress Controller.

This chapter covers the Ingress resource, the rules that define host and path routing, the IngressClass that selects the controller, and the critical distinction between Ingress (the rule) and Ingress Controller (the implementation). It also covers the difference between an Ingress and a Service of type LoadBalancer, because the two are often confused.

Key point: An Ingress does nothing without an Ingress Controller. The resource is just a rule set. The controller is the running software that watches for Ingress resources, provisions the underlying load balancer, and routes the traffic. A cluster with Ingress resources but no Ingress Controller silently accepts the manifests and routes nothing.


Why Ingress exists alongside Services

The LoadBalancer cost problem. A Service of type LoadBalancer provisions one cloud load balancer per Service. Ten HTTP services mean ten load balancers and ten public IP addresses. An Ingress consolidates those ten services behind one load balancer and one IP address, using host and path rules to route each request to the correct Service . The cost reduction is the primary motivation, but the operational simplification is equally important: one IP to manage, one TLS certificate to rotate, one set of DNS records.

The layer-7 problem. A Service of type LoadBalancer operates at layer 4. It forwards TCP or UDP traffic to a Pod without inspecting the HTTP request. It cannot route based on the Host header or the URL path. An Ingress operates at layer 7. It reads the HTTP request, matches the host and path against the rules, and forwards the request to the appropriate Service . This is what makes name-based virtual hosting and path-based fanout possible.

The rule abstraction problem. The Ingress resource is a stable API for routing rules. The same Ingress manifest works with an NGINX Ingress Controller on a self-hosted cluster, with the GKE Ingress controller on Google Cloud, and with Application Gateway on Azure . The controller translates the rules into the cloud provider’s load balancer configuration. The application team writes the routing rules once; the platform team chooses the controller.


a. The Ingress resource and its rules

The Ingress resource is defined in the networking.k8s.io/v1 API group. The spec contains an optional tls block, an optional defaultBackend, and a rules list. Each rule has an optional host and a http.paths list. Each path has a path, a pathType, and a backend that references a Service and port .

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
spec:
  ingressClassName: nginx
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /v1
            pathType: Prefix
            backend:
              service:
                name: api-v1
                port:
                  number: 80
          - path: /v2
            pathType: Prefix
            backend:
              service:
                name: api-v2
                port:
                  number: 80

The host field is a fully qualified domain name. It can be an exact match (api.example.com) or a wildcard (*.example.com), but the wildcard must be the first DNS label and matches only one label . If host is omitted, the rule matches all hosts.

The pathType field determines how the path is matched. Exact requires an exact match and is case-sensitive. Prefix matches on path elements separated by /, so /v1 matches /v1/users but not /v1beta. ImplementationSpecific leaves the interpretation to the controller . When multiple paths match, the longest path wins.

The backend references a Service by name and port. The Service must exist in the same namespace as the Ingress. If the Service does not exist, the Ingress controller returns a 503 for requests routed to that backend.


b. The IngressClass and the controller

The ingressClassName field references an IngressClass resource, which in turn names the controller that should implement the Ingress. The IngressClass is a cluster-scoped resource with a spec.controller field that identifies the controller implementation.

apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: nginx
spec:
  controller: k8s.io/ingress-nginx

The ingressClassName field replaced the older kubernetes.io/ingress.class annotation. The annotation is deprecated but still supported by most controllers for backward compatibility . A cluster can have a default IngressClass marked with the ingressclass.kubernetes.io/is-default-class: "true" annotation. An Ingress without an ingressClassName uses the default class if one exists.

The distinction between the resource and the controller is the most common source of confusion. The Ingress resource is a manifest that describes routing rules. The IngressClass is a manifest that names the controller. The controller is a running Deployment in the cluster that watches for Ingress resources with a matching class, reads their rules, and configures the underlying proxy. Without the controller, the Ingress resource is inert.


c. Ingress versus Service of type LoadBalancer

A Service of type LoadBalancer exposes a single Service on a cloud load balancer. It operates at layer 4, does not inspect HTTP, and requires one load balancer per Service. An Ingress consolidates multiple HTTP Services behind one load balancer and routes by host and path.

The Azure documentation states the distinction clearly: for non-HTTP traffic, use a LoadBalancer Service with layer-4 load balancing; for HTTP-like traffic, use an Ingress controller with layer-7 load balancing to share a single public IP across multiple applications . A cluster can use both: a LoadBalancer Service for a database that accepts TCP connections on a specific port, and an Ingress for the web front-end that routes by hostname.


Complete Example Session

# ============================================
# PART 1: THE BACKEND SERVICES
# ============================================
apiVersion: v1
kind: Service
metadata:
  name: api-v1
spec:
  selector:
    app: api
    version: v1
  ports:
    - port: 80
      targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: api-v2
spec:
  selector:
    app: api
    version: v2
  ports:
    - port: 80
      targetPort: 8080
# ============================================
# PART 2: THE INGRESS RESOURCE
# ============================================
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
spec:
  ingressClassName: nginx
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /v1
            pathType: Prefix
            backend:
              service:
                name: api-v1
                port:
                  number: 80
          - path: /v2
            pathType: Prefix
            backend:
              service:
                name: api-v2
                port:
                  number: 80
# ============================================
# PART 3: THE INGRESSCLASS
# ============================================
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: nginx
spec:
  controller: k8s.io/ingress-nginx
# ============================================
# PART 4: APPLY THE MANIFESTS
# ============================================
kubectl apply -f services.yaml
kubectl apply -f ingressclass.yaml
kubectl apply -f ingress.yaml
# ============================================
# PART 5: VERIFY THE INGRESS
# ============================================
kubectl get ingress api-ingress

# NAME          CLASS   HOSTS             ADDRESS         PORTS
# api-ingress   nginx   api.example.com   203.0.113.10    80
# ============================================
# PART 6: DESCRIBE THE INGRESS
# ============================================
kubectl describe ingress api-ingress

# Rules:
#   Host             Path  Backends
#   api.example.com
#                    /v1   api-v1:80 (10.244.1.5:8080)
#                    /v2   api-v2:80 (10.244.2.3:8080)
# ============================================
# PART 7: TEST THE ROUTING
# ============================================
curl http://api.example.com/v1/users
# Routed to api-v1

curl http://api.example.com/v2/users
# Routed to api-v2
# ============================================
# PART 8: WILDCARD HOST
# ============================================
spec:
  rules:
    - host: "*.example.com"
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: wildcard-svc
                port:
                  number: 80
# ============================================
# PART 9: DEFAULT BACKEND
# ============================================
spec:
  defaultBackend:
    service:
      name: fallback
      port:
        number: 80
  rules:
    - host: api.example.com
      # ...
# ============================================
# PART 10: TLS
# ============================================
spec:
  tls:
    - hosts:
        - api.example.com
      secretName: api-tls
  rules:
    - host: api.example.com
      # ...

The ten parts covered the backend Services, the Ingress resource, the IngressClass, applying the manifests, verification, description, testing, wildcard hosts, the default backend, and TLS.


Quick Reference

Ingress fields

FieldPurpose
ingressClassNameReferences the IngressClass
rules[].hostHostname match (exact or wildcard)
rules[].http.paths[].pathURL path
rules[].http.paths[].pathTypeExact, Prefix, ImplementationSpecific
rules[].http.paths[].backendService name and port
defaultBackendFallback when no rule matches
tlsTLS hosts and Secret

Path types

TypeBehavior
ExactCase-sensitive exact match
PrefixElement-wise prefix match
ImplementationSpecificController-defined

Controller comparison

FeatureIngressLoadBalancer Service
Layer7 (HTTP/HTTPS)4 (TCP/UDP)
RoutingHost and pathPort only
Load balancersOne for many ServicesOne per Service
CostLowerHigher

IngressClass

FieldPurpose
spec.controllerIdentifies the controller implementation
Default annotationingressclass.kubernetes.io/is-default-class: "true"

Best Practices

โœ… Do This:

# Specify ingressClassName explicitly
spec:
  ingressClassName: nginx                                   # โœ…
# Use Prefix for path routing
pathType: Prefix                                            # โœ…
# Use a defaultBackend for unmatched requests
defaultBackend:
  service:
    name: fallback                                          # โœ…

โŒ Don’t Do This:

# Omit ingressClassName and rely on a default
# If no default class exists, the Ingress is inert        # โŒ
# Use Exact for a path that should match subpaths
pathType: Exact                                             # โŒ
# Assume Ingress works without a controller
# The manifest is accepted, but nothing is routed          # โŒ

Common Pitfalls

PitfallWhy It HappensFix
Ingress has no effectNo Ingress Controller installedInstall a controller and create the IngressClass
503 from the controllerBackend Service does not exist or has no endpointsCheck kubectl get endpoints
Path does not matchpathType is Exact but subpath is requestedUse Prefix
Wildcard host does not matchThe wildcard is not the first labelUse *.example.com, not foo.*.com
TLS certificate not usedThe Secret is missing or in the wrong namespaceCreate the TLS Secret in the same namespace

Real-World Examples

1. Host-based routing

rules:
  - host: api.example.com
    http:
      paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: api
              port:
                number: 80

2. Path-based routing

paths:
  - path: /v1
    pathType: Prefix
    backend:
      service:
        name: api-v1
  - path: /v2
    pathType: Prefix
    backend:
      service:
        name: api-v2

3. IngressClass

apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: nginx
spec:
  controller: k8s.io/ingress-nginx

4. Default backend

spec:
  defaultBackend:
    service:
      name: fallback

5. TLS

spec:
  tls:
    - hosts: [api.example.com]
      secretName: api-tls

6. Wildcard host

host: "*.example.com"

7. Imperative creation

kubectl create ingress simple --rule="foo.com/bar=svc1:8080"

8. Check the controller

kubectl get pods -n ingress-nginx

9. Check the Ingress

kubectl get ingress

10. Describe the Ingress

kubectl describe ingress api-ingress

Visual

Ingress and the controller

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  INGRESS RESOURCE                                            โ”‚
โ”‚    rules:                                                    โ”‚
โ”‚      host: api.example.com                                   โ”‚
โ”‚        /v1 โ†’ api-v1 Service                                  โ”‚
โ”‚        /v2 โ†’ api-v2 Service                                  โ”‚
โ”‚                                                              โ”‚
โ”‚  INGRESS CONTROLLER (running Pod)                            โ”‚
โ”‚    watches for Ingress resources                              โ”‚
โ”‚    reads the rules                                            โ”‚
โ”‚    configures the proxy                                       โ”‚
โ”‚                                                              โ”‚
โ”‚  Without the controller, the rules are inert.                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Host and path routing

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  api.example.com/v1/users                                    โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Ingress Controller                                          โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ”œโ”€โ”€ host match: api.example.com                       โ”‚
โ”‚       โ”œโ”€โ”€ path match: /v1                                   โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  api-v1 Service โ”€โ”€โ–บ api-v1 Pod                               โ”‚
โ”‚                                                              โ”‚
โ”‚  api.example.com/v2/users                                    โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  api-v2 Service โ”€โ”€โ–บ api-v2 Pod                               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Ingress vs LoadBalancer Service

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  LOADBALANCER SERVICE          INGRESS                       โ”‚
โ”‚                                                              โ”‚
โ”‚  One LB per Service            One LB for many Services     โ”‚
โ”‚  Layer 4                       Layer 7                      โ”‚
โ”‚  TCP/UDP                       HTTP/HTTPS                   โ”‚
โ”‚  No host/path routing          Host and path routing        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

IngressClass

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Ingress                                                     โ”‚
โ”‚    ingressClassName: nginx                                  โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  IngressClass (nginx)                                        โ”‚
โ”‚    spec.controller: k8s.io/ingress-nginx                     โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  NGINX Ingress Controller                                    โ”‚
โ”‚    watches Ingress resources with class "nginx"              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
API groupnetworking.k8s.io/v1
Routing layerLayer 7 (HTTP/HTTPS)
Required componentIngress Controller
Class selectioningressClassName or annotation
Host matchingExact or wildcard (*.example.com)
Path typesExact, Prefix, ImplementationSpecific
BackendService name and port
TLStls block with hosts and Secret
Default fallbackdefaultBackend

Key takeaways:

  • An Ingress is a rule set; an Ingress Controller is the implementation. The Ingress resource declares routing rules. The controller watches for Ingress resources, reads the rules, and configures the underlying proxy. Without a controller, the Ingress is inert .
  • Ingress operates at layer 7; a LoadBalancer Service operates at layer 4. Ingress can route by host and path because it inspects the HTTP request. A LoadBalancer Service forwards TCP or UDP without inspecting the request, so it cannot route by hostname or URL .
  • The ingressClassName field references an IngressClass, which names the controller. The class is a cluster-scoped resource. A default class can be marked with an annotation, and Ingress resources without a class use the default if one exists .
  • The pathType determines how paths are matched. Exact requires an exact match. Prefix matches on path elements, so /v1 matches /v1/users but not /v1beta. When multiple paths match, the longest path wins .
  • A wildcard host must be the first DNS label. *.example.com is valid and matches api.example.com but not foo.api.example.com. The wildcard cannot be used alone as * .
  • TLS is configured with a tls block and a Secret. The Secret must exist in the same namespace as the Ingress. The controller uses it to terminate TLS for the listed hosts.

Remember: An Ingress is the layer-7 routing rule, and the Ingress Controller is the software that makes the rule real. The resource declares host and path matches and points to backend Services. The class selects the controller. The controller provisions the load balancer and routes the traffic. Without the controller, the manifest is a comment. Use Ingress for HTTP services that need host-based or path-based routing behind a single IP address. Use a LoadBalancer Service for non-HTTP traffic that needs a dedicated layer-4 endpoint. And when an Ingress is not working, check the controller first: if it is not running, nothing else matters.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!