[11/24] I is for Ingress: Managing External Access
This is Post #10 in the Kubernetes A-to-Z Series
Reading Order: Previous: ConfigMaps and Secrets | Next: Helm
Series Progress: 11/24 complete | Difficulty: Intermediate | Time: 25 min | Part 4/6: Advanced Concepts
Welcome to the tenth post in our Kubernetes A-to-Z Series! Now that you understand configuration management, let’s explore Ingress - the Kubernetes resource for managing external access to services. Ingress provides HTTP/HTTPS routing, load balancing, and TLS termination for your applications.
Why Ingress?
Without Ingress, exposing multiple services requires multiple LoadBalancers (expensive) or NodePorts (limited):
Without Ingress:
┌─────────────────────────────────────────────────┐
│ External Traffic │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ LB $$$ │ │ LB $$$ │ │ LB $$$ │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Service │ │ Service │ │ Service │ │
│ │ API │ │ Web │ │ Admin │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────┘
Multiple LoadBalancers = High Cost
With Ingress:
┌─────────────────────────────────────────────────┐
│ External Traffic │
│ ┌─────────────────────────────────────┐ │
│ │ Single LoadBalancer │ │
│ └──────────────┬──────────────────────┘ │
│ │ │
│ ┌──────────────▼──────────────────────┐ │
│ │ Ingress Controller │ │
│ │ /api → API /web → Web /admin → │ │
│ └──────────────┬──────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Service │ │ Service │ │ Service │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────┘
Single entry point = Cost effective
Ingress Benefits
- Cost Efficiency: Single LoadBalancer for multiple services
- Centralized Routing: Path and host-based routing rules
- TLS Termination: Manage SSL certificates in one place
- Advanced Features: Rate limiting, authentication, rewrites
Ingress Components
1. Ingress Controller
The controller implements the Ingress rules. Popular options:
- NGINX Ingress Controller (most common)
- Traefik
- HAProxy
- AWS ALB Ingress Controller
- GCE Ingress Controller
2. Ingress Resource
The configuration that defines routing rules.
Installing NGINX Ingress Controller
# Using Helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace
# Verify installation
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx
Basic Ingress Configuration
Simple Path-Based Routing
# basic-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: webapp-ingress
namespace: production
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: myapp.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
Host-Based Routing
# host-based-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-host-ingress
namespace: production
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 3000
Path Types
| Type | Description | Example Match |
|---|---|---|
| Exact | Exact URL match | /api matches only /api |
| Prefix | URL prefix match | /api matches /api, /api/users |
| ImplementationSpecific | Controller-dependent | Varies |
# path-types-example.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-types-ingress
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /api
pathType: Exact
backend:
service:
name: api-exact-service
port:
number: 8080
- path: /api/
pathType: Prefix
backend:
service:
name: api-prefix-service
port:
number: 8080
TLS/SSL Configuration
Basic TLS Setup
# tls-ingress.yaml
apiVersion: v1
kind: Secret
metadata:
name: webapp-tls
namespace: production
type: kubernetes.io/tls
data:
tls.crt: LS0tLS1CRUdJTi... # Base64 encoded certificate
tls.key: LS0tLS1CRUdJTi... # Base64 encoded private key
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
namespace: production
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- myapp.example.com
- api.example.com
secretName: webapp-tls
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
Automatic TLS with Cert-Manager
# cert-manager-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auto-tls-ingress
namespace: production
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- myapp.example.com
secretName: myapp-tls-auto
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
Advanced Annotations
NGINX Ingress Annotations
# advanced-annotations.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: advanced-ingress
namespace: production
annotations:
# SSL/TLS
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
# Timeouts
nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
# Body size
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
# Rate limiting
nginx.ingress.kubernetes.io/limit-rps: "100"
nginx.ingress.kubernetes.io/limit-connections: "10"
# CORS
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com"
# Rewrites
nginx.ingress.kubernetes.io/rewrite-target: /$2
# Sticky sessions
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "route"
spec:
ingressClassName: nginx
rules:
- host: myapp.example.com
http:
paths:
- path: /api(/|$)(.*)
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
URL Rewriting
# rewrite-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rewrite-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
# /api/users -> /users on backend
- path: /api(/|$)(.*)
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
Basic Authentication
# basic-auth-ingress.yaml
apiVersion: v1
kind: Secret
metadata:
name: basic-auth
namespace: production
type: Opaque
data:
# htpasswd -c auth admin
auth: YWRtaW46JGFwcjEkSDZ... # base64 encoded htpasswd
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auth-ingress
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"
spec:
ingressClassName: nginx
rules:
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 3000
Complete Production Example
# production-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: production-ingress
namespace: production
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- www.example.com
- api.example.com
- admin.example.com
secretName: production-tls
rules:
# Main website
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
# API
- host: api.example.com
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: api-v1-service
port:
number: 8080
- path: /v2
pathType: Prefix
backend:
service:
name: api-v2-service
port:
number: 8080
# Admin panel
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 3000
Default Backend
Handle unmatched requests:
# default-backend-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-with-default
spec:
ingressClassName: nginx
defaultBackend:
service:
name: default-service
port:
number: 80
rules:
- host: example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
Troubleshooting
# Check Ingress status
kubectl get ingress -A
kubectl describe ingress webapp-ingress -n production
# Check Ingress Controller logs
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx
# Check Ingress Controller service
kubectl get svc -n ingress-nginx
# Test DNS resolution
nslookup myapp.example.com
# Test connectivity
curl -v https://myapp.example.com
# Check TLS certificate
openssl s_client -connect myapp.example.com:443 -servername myapp.example.com
# Check backend service
kubectl get endpoints api-service -n production
Commands Reference
# Ingress Management
kubectl get ingress -A
kubectl describe ingress webapp-ingress -n production
kubectl delete ingress webapp-ingress -n production
# Ingress Controller
kubectl get pods -n ingress-nginx
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx
# TLS Secrets
kubectl create secret tls webapp-tls --cert=tls.crt --key=tls.key -n production
kubectl get secrets -n production | grep tls
# Testing
curl -H "Host: myapp.example.com" http://INGRESS_IP/
curl -k https://myapp.example.com/
Key Takeaways
- Ingress provides HTTP/HTTPS routing to services
- Ingress Controller implements the routing rules
- Path-based and host-based routing supported
- TLS termination centralizes certificate management
- Annotations enable advanced features (rate limiting, auth, rewrites)
- Cert-manager automates TLS certificate provisioning
Next Steps
Now that you understand Ingress, you’re ready to explore Helm in the next post. We’ll learn how to package, deploy, and manage Kubernetes applications using Helm charts.
Resources for Further Learning
Series Navigation:
- Previous: M is for ConfigMaps and Secrets
- Next: H is for Helm: Package Management
Complete Series: Kubernetes A-to-Z Series Overview