The Nginx Ingress Controller manages external access to services in a Kubernetes cluster, typically HTTP/HTTPS. It provides features like SSL termination, name-based virtual hosting, and path-based routing.
Installation
Clone Repository
Clone the official NGINX Ingress Controller repository: git clone https://github.com/nginxinc/kubernetes-ingress.git --branch v3.1.1
cd kubernetes-ingress/deployments/
Create Namespace and Service Account
kubectl apply -f common/ns-and-sa.yaml
Apply RBAC Resources
kubectl apply -f rbac/rbac.yaml
kubectl apply -f rbac/ap-rbac.yaml
kubectl apply -f rbac/apdos-rbac.yaml
Create Configuration Resources
kubectl apply -f common/nginx-config.yaml
kubectl apply -f common/ingress-class.yaml
Install Custom Resource Definitions
kubectl apply -f common/crds/k8s.nginx.org_virtualservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_virtualserverroutes.yaml
kubectl apply -f common/crds/k8s.nginx.org_transportservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_policies.yaml
kubectl apply -f common/crds/k8s.nginx.org_globalconfigurations.yaml
Deploy Ingress Controller
Deploy as DaemonSet to run on all nodes: kubectl apply -f daemon-set/nginx-ingress.yaml
Verify Installation
kubectl get ns
kubectl -n nginx-ingress get ds
kubectl -n nginx-ingress get pods
After installation, accessing any node IP via a browser will show a 404 Not Found error from NGINX. This confirms the controller is receiving requests and waiting for Ingress resources.
Deploy Sample Application
Create Application Manifest
apiVersion : v1
kind : Namespace
metadata :
name : petclinic
---
apiVersion : apps/v1
kind : Deployment
metadata :
name : petclinic
namespace : petclinic
spec :
replicas : 2
selector :
matchLabels :
app : petclinic
template :
metadata :
labels :
app : petclinic
spec :
containers :
- name : pet
image : lovelearnlinux/webserver:v1
ports :
- containerPort : 80
---
apiVersion : v1
kind : Service
metadata :
name : petclinic-svc
namespace : petclinic
spec :
ports :
- port : 80
targetPort : 80
protocol : TCP
name : http
selector :
app : petclinic
---
apiVersion : networking.k8s.io/v1
kind : Ingress
metadata :
name : petclinic-ingress
namespace : petclinic
annotations :
nginx.ingress.kubernetes.io/rewrite-target : /
spec :
ingressClassName : nginx
rules :
- host : petclinic.example.com
http :
paths :
- path : /
pathType : Prefix
backend :
service :
name : petclinic-svc
port :
number : 80
Apply the Manifest
kubectl apply -f petclinic.yaml
Testing the Ingress
Local DNS Configuration
Since we don’t have a real DNS setup, modify /etc/hosts on worker nodes:
# Add this line to /etc/hosts on each worker node
< worker-ip > petclinic.example.com
Test Access
# From the worker node
curl http://petclinic.example.com
You should see the application response.
Ingress Configuration
Path-Based Routing
apiVersion : networking.k8s.io/v1
kind : Ingress
metadata :
name : path-based-ingress
namespace : default
spec :
ingressClassName : nginx
rules :
- host : myapp.example.com
http :
paths :
- path : /api
pathType : Prefix
backend :
service :
name : api-service
port :
number : 8080
- path : /web
pathType : Prefix
backend :
service :
name : web-service
port :
number : 80
Host-Based Routing
apiVersion : networking.k8s.io/v1
kind : Ingress
metadata :
name : host-based-ingress
namespace : default
spec :
ingressClassName : nginx
rules :
- host : app1.example.com
http :
paths :
- path : /
pathType : Prefix
backend :
service :
name : app1-service
port :
number : 80
- host : app2.example.com
http :
paths :
- path : /
pathType : Prefix
backend :
service :
name : app2-service
port :
number : 80
SSL/TLS Configuration
Create TLS Secret
kubectl create secret tls my-tls-secret \
--cert=path/to/tls.crt \
--key=path/to/tls.key \
-n petclinic
Update Ingress with TLS
apiVersion : networking.k8s.io/v1
kind : Ingress
metadata :
name : petclinic-ingress
namespace : petclinic
spec :
ingressClassName : nginx
tls :
- hosts :
- petclinic.example.com
secretName : my-tls-secret
rules :
- host : petclinic.example.com
http :
paths :
- path : /
pathType : Prefix
backend :
service :
name : petclinic-svc
port :
number : 80
Common Annotations
URL Rewriting
SSL Redirect
CORS
Rate Limiting
Custom Headers
annotations :
nginx.ingress.kubernetes.io/rewrite-target : /
Advanced Features
Basic Authentication
Create htpasswd File
htpasswd -c auth username
Create Secret
kubectl create secret generic basic-auth --from-file=auth -n petclinic
Add Annotation
annotations :
nginx.ingress.kubernetes.io/auth-type : basic
nginx.ingress.kubernetes.io/auth-secret : basic-auth
nginx.ingress.kubernetes.io/auth-realm : 'Authentication Required'
Custom Error Pages
annotations :
nginx.ingress.kubernetes.io/custom-http-errors : "404,503"
nginx.ingress.kubernetes.io/default-backend : custom-error-pages
Canary Deployments
# Production Ingress
apiVersion : networking.k8s.io/v1
kind : Ingress
metadata :
name : production
annotations :
nginx.ingress.kubernetes.io/canary : "false"
spec :
ingressClassName : nginx
rules :
- host : myapp.example.com
http :
paths :
- backend :
service :
name : production-service
port :
number : 80
path : /
pathType : Prefix
---
# Canary Ingress (10% traffic)
apiVersion : networking.k8s.io/v1
kind : Ingress
metadata :
name : canary
annotations :
nginx.ingress.kubernetes.io/canary : "true"
nginx.ingress.kubernetes.io/canary-weight : "10"
spec :
ingressClassName : nginx
rules :
- host : myapp.example.com
http :
paths :
- backend :
service :
name : canary-service
port :
number : 80
path : /
pathType : Prefix
Monitoring and Troubleshooting
View Ingress Controller Logs
kubectl logs -n nginx-ingress < pod-nam e >
Check Ingress Status
kubectl get ingress -A
kubectl describe ingress < ingress-nam e > -n < namespac e >
Test Backend Connectivity
kubectl run test --image=curlimages/curl -it --rm -- sh
curl http:// < service-nam e > . < namespac e > .svc.cluster.local
Deployment Options
Runs an Ingress Controller pod on every node. Suitable for:
High availability
Direct node port access
On-premises clusters
kubectl apply -f daemon-set/nginx-ingress.yaml
Runs a specific number of replicas. Suitable for:
Cloud environments with load balancers
Resource-constrained clusters
Better control over pod placement
kubectl apply -f deployment/nginx-ingress.yaml
The DaemonSet approach ensures that every node can handle incoming traffic directly, while the Deployment approach works better with cloud load balancers.
Best Practices
Use IngressClass to support multiple ingress controllers
Always set resource limits for the ingress controller pods
Enable RBAC and use least privilege principles
Implement TLS for all public-facing applications
Monitor ingress controller metrics and logs
Use separate ingress resources per application/namespace
Test configuration changes in non-production first
Direct exposure of node ports in production is not recommended. Use a proper LoadBalancer service or cloud provider’s load balancer integration.