NGINX Ingress Controller di Kubernetes: Setup, TLS, dan Routing
Cluster Kubernetes kamu jalan, pod sehat, service aktif. Tapi nggak ada cara buat traffic eksternal masuk ke dalamnya. Kamu bisa expose setiap service pakai NodePort, tapi itu artinya manage port terpisah, handle SSL termination di luar cluster, dan kehilangan path-based routing seluruhnya.
Ingress controller menyelesaikan masalah ini. Dia duduk di pinggir cluster, terima HTTP dan HTTPS, dan routing ke service yang tepat berdasarkan hostname atau path. NGINX jadi pilihan paling umum, dan ada alasan: cepat, dokumentasinya lengkap, dan sudah teruji di production selama bertahun-tahun.
Artikel ini menjelaskan cara install NGINX Ingress Controller pakai Helm, bikin Ingress resource pertama, dan setup TLS pakai cert-manager supaya service kamu otomatis dapat sertifikat HTTPS.
Prerequisites
- Cluster Kubernetes yang sudah jalan (1.25+) dengan
kubectlterkonfigurasi - Helm 3 terinstall (install docs)
- Domain name yang sudah pointing ke IP eksternal atau load balancer cluster kamu
cert-managerterinstall kalau mau TLS otomatis (dijelaskan di bawah)
Cek cluster bisa diakses:
kubectl cluster-info
kubectl get nodes
Langkah 1: Install NGINX Ingress Controller
Helm chart resmi ada di repository ingress-nginx. Tambahkan dan install:
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 --set controller.service.type=LoadBalancer
Pastikan pod-nya jalan:
kubectl -n ingress-nginx get pods
Output yang diharapkan:
NAME READY STATUS RESTARTS AGE
ingress-nginx-controller-6f4b8c7c9b-abc12 1/1 Running 0 30s
Ambil IP eksternal load balancer:
kubectl -n ingress-nginx get svc ingress-nginx-controller
Field EXTERNAL-IP menunjukkan tempat cluster kamu menerima traffic. Arahkan DNS record ke IP ini.
Langkah 2: Deploy Aplikasi Test
Sebelum konfigurasi routing, kamu perlu target. Deploy aplikasi sederhana:
kubectl create deployment hello --image=nginx:alpine --port=80
kubectl expose deployment hello --port=80 --type=ClusterIP
Ini bikin Service bernama hello yang cuma bisa diakses dari dalam cluster. Ingress controller akan mengubah itu.
Langkah 3: Buat Ingress Resource
Buat file hello-ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: hello.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello
port:
number: 80
Apply:
kubectl apply -f hello-ingress.yaml
Traffic ke hello.example.com sekarang sampai ke deployment hello. NGINX controller watch Ingress resources dan update nginx.conf secara otomatis.
Pastikan Ingress terbuat:
kubectl get ingress hello-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
hello-ingress nginx hello.example.com 34.120.x.x 80 10s
Langkah 4: Path-Based Routing
Setup real biasanya perlu routing beberapa path ke service berbeda. Deploy app kedua:
kubectl create deployment api --image=nginx:alpine --port=80
kubectl expose deployment api --port=80 --type=ClusterIP
Update Ingress untuk handle kedua path:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /web(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: hello
port:
number: 80
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api
port:
number: 80
Annotation rewrite-target: /$2 strip prefix sebelum forwarding. Request ke example.com/api/users sampai ke service api di path /users, bukan /api/users.
Apply config yang diupdate:
kubectl apply -f hello-ingress.yaml
Test pakai curl:
curl -H "Host: example.com" http://<EXTERNAL-IP>/web/
curl -H "Host: example.com" http://<EXTERNAL-IP>/api/status
Langkah 5: Install cert-manager buat TLS Otomatis
cert-manager watch Certificate resources dan komunikasi dengan Let's Encrypt buat issue dan renew sertifikat TLS secara otomatis.
Install cert-manager pakai Helm:
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set crds.enabled=true
Pastikan pod-nya jalan:
kubectl -n cert-manager get pods
Harusnya ada tiga pod: cert-manager, cert-manager-cainjector, dan cert-manager-webhook.
Langkah 6: Buat ClusterIssuer
ClusterIssuer bilang ke cert-manager pakai ACME server mana dan cara verifikasi kepemilikan domain. Buat cluster-issuer.yaml:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
ingress:
ingressClassName: nginx
Apply:
kubectl apply -f cluster-issuer.yaml
Cek status issuer:
kubectl get clusterissuer letsencrypt-prod -o wide
Field READY harus True dalam beberapa detik.
Langkah 7: Tambah TLS ke Ingress
Update Ingress resource dengan section TLS:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- example.com
secretName: example-com-tls
rules:
- host: example.com
http:
paths:
- path: /web(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: hello
port:
number: 80
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api
port:
number: 80
Apply:
kubectl apply -f hello-ingress.yaml
cert-manager akan detect annotation cert-manager.io/cluster-issuer, request sertifikat dari Let's Encrypt, dan simpan di Secret example-com-tls. Proses ini butuh 30 sampai 60 detik.
Monitor sertifikat:
kubectl get certificate
NAME READY SECRET AGE
example-com-tls True example-com-tls 45s
Begitu READY True, HTTPS sudah bisa dipakai. Coba:
curl -v https://example.com/web/
Masalah yang Sering Muncul
502 Bad Gateway. Ingress controller nggak bisa reach backend. Cek nama Service dan port sesuai dengan yang didefinisikan. Pakai kubectl describe ingress hello-ingress buat lihat backend yang terkonfigurasi. Pastikan juga Service-nya running: kubectl get svc hello.
Certificate stuck Pending. cert-manager nggak bisa selesaikan challenge HTTP-01. Pastikan port 80 terbuka di load balancer dan DNS pointing ke IP yang benar. Cek log cert-manager: kubectl -n cert-manager logs deploy/cert-manager.
Rewrite bikin app error. Annotation rewrite-target mengubah path sebelum forwarding. Kalau app kamu butuh path asli, hapus annotation. Kalau butuh keduanya, pakai annotation nginx.ingress.kubernetes.io/configuration-snippet buat set custom headers.
Ingress class nggak ditemukan. Kalau kubectl get ingress nunjukin nggak ada class, tambah --set controller.ingressClassResource.name=nginx ke Helm install command, atau pastikan kamu set ingressClassName: nginx di spec Ingress.
Langkah Selanjutnya
- rate-limit annotations (
nginx.ingress.kubernetes.io/limit-rps) buat proteksi backend dari traffic spike - canary deployments pakai
nginx.ingress.kubernetes.io/canary-weightbuat gradual rollout - ModSecurity WAF dengan enable annotation
modsecurity-snippet - Konfigurasi NGINX Ingress Controller di repository docs resmi