A machine learning engineer's homepage

It is not just about machine learning engineering ...

View on GitHub

Understanding ingress.yaml in Kubernetes with an example

💬 “知人者智,自知者明。胜人者有力,自胜者强。(He who knows others is wise; he who knows himself is enlightened. He who conquers others is strong; he who conquers himself is truly powerful.)
— Laozi

Introduction: Why Learn the ingress.yaml?

In previous posts, you’ve deployed your Pods with deployment.yaml and made them accessible inside the Kubernetes cluster with service.yaml. But now you’re wondering, “How do I let the outside world—aka my users—reach this app?” Fear not, friend! The ingress.yaml is your ticket to exposing your application to the internet in a slick, controlled way. It’s like opening a fancy front door to your Kubernetes house, complete with a doorman checking IDs.

The ingress.yaml defines an Ingress resource, which manages external HTTP/HTTPS traffic to your Services, typically by routing requests based on hostnames or paths. Think of it as a smart traffic cop directing web requests to the right Service (like the my-app-service). Unlike NodePort or LoadBalancer Services, which can be clunky or costly, Ingress is lightweight, flexible, and works with an Ingress Controller (like NGINX, which routes traffic, unlike the NGINX in our Pod that serves static webpages) to handle the heavy lifting.

Common newbie traps include:

This post builds on our NGINX app example, showing you an ingress.yaml that exposes my-app-service externally via example.com. We’ll break it down with collapsible sections, keep the YAML indentation at 2 spaces (because YAML is picky), and make you feel like a Kubernetes networking pro by the end. Let’s dive in!


Example: Full ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-app-service
                port:
                  number: 80

Explanation of Each Section (Expand for details)

apiVersion: networking.k8s.io/v1
  • Specifies the API version for the Ingress resource.
  • `networking.k8s.io/v1` is the stable API for Ingress since Kubernetes 1.19, replacing older `extensions/v1beta1`.
  • Ensures compatibility with modern Kubernetes clusters.
kind: Ingress
  • Declares this YAML as an Ingress resource.
  • Ingress manages external HTTP/HTTPS traffic, routing it to Services based on rules like hostnames or paths.
  • Requires an Ingress Controller (e.g., NGINX, Traefik) to process these rules.
metadata
  • `name: my-app-ingress`: The unique name of the Ingress object within the namespace.
  • `annotations`: Optional key-value pairs for configuring the Ingress Controller.
  • `nginx.ingress.kubernetes.io/rewrite-target: /`: Tells the NGINX Ingress Controller to rewrite incoming URLs to `/`, useful for routing (e.g., stripping prefixes). Adjust based on your app’s needs.
spec.ingressClassName
  • `ingressClassName: nginx`: Specifies which Ingress Controller should handle this Ingress.
  • Matches the name of an `IngressClass` resource, ensuring the NGINX Ingress Controller (not another like Traefik) processes this.
  • Think of it as telling Kubernetes, “Hey, NGINX, this one’s for you!”
spec.rules
  • Defines routing rules for incoming HTTP traffic.
  • `host: example.com`: Routes requests for `example.com` to the specified Service.
  • If no `host` is set, the rule applies to all incoming requests (less secure, so use with caution).
  • Multiple rules can handle different domains (e.g., `api.example.com`, `app.example.com`).
spec.rules.http.paths
  • Specifies URL path-based routing for the given host.
  • `path: /`: Matches requests starting with `/` (e.g., `example.com/`, `example.com/home`).
  • `pathType: Prefix`: Indicates the path is a prefix match, so `/` catches all subpaths unless overridden by more specific rules.
  • Other `pathType` options include `Exact` (exact URL match) or `ImplementationSpecific` (controller-dependent).
  • `backend.service`: Routes matching requests to a Service.
  • `name: my-app-service`: Targets the Service from our previous post.
  • `port.number: 80`: Sends traffic to port 80 of `my-app-service`, matching its `port` field.

What This Ingress Actually Does

This ingress.yaml creates a Kubernetes Ingress resource named my-app-ingress that exposes the my-app-service (and thus our NGINX app) to the outside world via the domain example.com. It works with an NGINX Ingress Controller to route HTTP traffic from example.com/ (and all subpaths) to the my-app-service Service on port 80, which then load-balances requests across the NGINX Pods.

Here’s the play-by-play:

graph TD A[User Browser
example.com] -->|HTTP Request| LB[Load Balancer] LB -->|Distributes to| B[NGINX Ingress Controller
External IP] %% Kubernetes Cluster Subgraph subgraph K8sCluster[ ] B -->|Matches host: example.com| C[Ingress: my-app-ingress
path: /] C -->|Routes to| D[Service: my-app-service
port: 80] D -->|Load Balances| E[Pod 1
targetPort: 80] D -->|Load Balances| F[Pod 2
targetPort: 80] D -->|Load Balances| G[Pod 3
targetPort: 80] E -->|Serves| H[NGINX Webpage] F -->|Serves| H G -->|Serves| H end %% Styling nodes classDef nodeStyle fill:#69b5ce,stroke:#4287f5,stroke-width:2px,color:#090c0c; class A,LB,B,C,D,E,F,G,H nodeStyle; %% Styling edges linkStyle default stroke:#4287f5,stroke-width:2px,fill:none; %% Styling subgraph border classDef clusterStyle fill:none,stroke:#4287f5,stroke-width:4px,stroke-dasharray:5,5; class K8sCluster clusterStyle;

The ingressClassName: nginx ensures the NGINX Ingress Controller handles this resource, avoiding confusion if multiple controllers are running. The pathType: Prefix makes the rule flexible, catching all URLs under example.com/, so example.com/about works too. This setup is perfect for public-facing web apps, as it’s secure (HTTPS can be added with TLS settings), scalable (the Ingress Controller and Service handle load balancing), and cost-efficient (no need for a LoadBalancer Service per app).

Note: For this to work in production, you need:

This Ingress makes your NGINX app accessible to anyone with the right URL, providing a professional-grade HTTP routing without the headache of managing raw IPs or load balancers manually. It’s like giving your app a shiny billboard on the internet highway!


Ingress Command

Before deploying, ensure you have an NGINX Ingress Controller installed. For a quick setup (e.g., in a test cluster):

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml

Apply the ingress.yaml file to your cluster:

kubectl apply -f ingress.yaml

Verify and troubleshoot the Ingress:

# Check the Ingress resource
kubectl get ingress

# View detailed information about the Ingress
kubectl describe ingress my-app-ingress

# Get the Ingress Controller’s external IP (look for LoadBalancer IP)
kubectl get -n ingress-nginx service/ingress-nginx-controller

# Test access (replace <EXTERNAL-IP> with the Ingress Controller’s IP or your domain)
# Or you can just open the url in a browser
curl http://example.com/

# For local testing, use port-forward to access the Service behind the Ingress
kubectl port-forward service/my-app-service 8080:80
# Then access http://localhost:8080 in your browser

For official Ingress documentation, visit the Kubernetes Ingress page.