Di episode ini kita akan coba bahas Kubernetes Ingress, API object untuk mengelola external HTTP/HTTPS access ke service. Kita akan mempelajari Ingress controller, routing rule, TLS termination, dan best practice untuk expose application.

Catatan
Untuk kalian yang ingin membaca episode sebelumnya, bisa click thumbnail episode 18 di bawah ini
Di episode sebelumnya kita sudah belajar tentang Service untuk expose dan access application dalam dan luar cluster. Selanjutnya di episode 19 kali ini, kita akan coba bahas Ingress, yang menyediakan sophisticated HTTP/HTTPS routing ke Service.
Catatan: Disini saya akan menggunakan Kubernetes Cluster yang di install melalui K3s.
Sementara Service bisa expose application menggunakan LoadBalancer atau NodePort, Ingress menyediakan cara yang lebih powerful dan flexible untuk manage external access. Ingress bertindak sebagai smart HTTP router, enable feature seperti host-based routing, path-based routing, TLS termination, dan lebih - semua dengan single external IP.
Ingress adalah Kubernetes API object yang mengelola external HTTP dan HTTPS access ke Service di cluster. Dia menyediakan HTTP routing rule untuk direct traffic ke different Service berdasarkan hostname, path, dan criteria lain.
Bayangkan Ingress seperti reverse proxy atau API gateway - dia sit di edge cluster kalian, receive external HTTP/HTTPS traffic, dan route ke appropriate Service berdasarkan rule yang kalian define. Daripada membuat multiple LoadBalancer (satu per Service), kalian gunakan single Ingress dengan routing rule.
Karakteristik kunci Ingress:
Mari kita pahami perbedaan kunci nya:
| Aspek | Ingress | LoadBalancer Service |
|---|---|---|
| Layer | Layer 7 (HTTP/HTTPS) | Layer 4 (TCP/UDP) |
| Routing | Host dan path-based | Port-based saja |
| External IP | Satu IP untuk banyak Service | Satu IP per Service |
| TLS | Built-in TLS termination | Require external setup |
| Cost | Single load balancer | Multiple load balancer |
| Protocol | HTTP/HTTPS saja | Any TCP/UDP protocol |
Contoh scenario:
api.example.com ke API Service, web.example.com ke Web Service - satu IPIngress resource tidak bekerja sendiri - mereka require Ingress Controller untuk function.
Ingress Controller adalah specialized load balancer yang read Ingress resource dan implement routing rule. Dia adalah actual component yang handle traffic.
Popular Ingress Controller:
Important
Penting: Kalian harus install Ingress Controller sebelum Ingress resource akan work. Kubernetes tidak include satu by default.
Untuk K3s (comes dengan Traefik by default):
Important
Jika kalian menggunakan K3s maka default nya akan sudah ada Ingress Controller yang dijalankan menggunakan Traefik seperti ini:
➜ devnull@devnull ~ sudo kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.43.0.10 <none> 53/UDP,53/TCP,9153/TCP 121d
metrics-server ClusterIP 10.43.122.234 <none> 443/TCP 121d
traefik LoadBalancer 10.43.230.117 10.10.10.4 80:31009/TCP,443:30158/TCP 121d
➜ devnull@devnull ~ sudo kubectl get ingressclass
NAME CONTROLLER PARAMETERS AGE
traefik traefik.io/ingress-controller <none> 121d
➜ devnull@devnull ~ sudo kubectl describe ingressclass traefik
Name: traefik
Labels: app.kubernetes.io/instance=traefik-kube-system
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=traefik
helm.sh/chart=traefik-34.2.1_up34.2.0
Annotations: ingressclass.kubernetes.io/is-default-class: true
meta.helm.sh/release-name: traefik
meta.helm.sh/release-namespace: kube-system
Controller: traefik.io/ingress-controller
Events: <none># K3s include Traefik, tapi kalian bisa install NGINX
sudo kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yamlUntuk cluster lain:
sudo kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/baremetal/deploy.yamlVerify installation:
sudo kubectl get pods -n ingress-nginxMari kita buat simple Ingress untuk expose Service.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: app-hostname
image: ghcr.io/armandwipangestu/app-hostname:1.0.0
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80Apply:
sudo kubectl apply -f web-app.ymlapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
spec:
rules:
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80Apply:
sudo kubectl apply -f basic-ingress.ymlVerify:
sudo kubectl get ingressOutput:
NAME CLASS HOSTS ADDRESS PORTS AGE
web-ingress <none> web.example.com 203.0.113.10 80 30sSekarang traffic ke web.example.com route ke web-service.
Tip
Apabila kalian ingin akses web.example.com tersebut, kalian bisa tambahkan static record di /etc/hosts yang mengarah ke NodeIP nya, semisal
10.10.10.4 web.example.comKemudian coba akses dengan curl seperti ini
curl http://web.example.comAtau jika tidak ingin pakai /etc/hosts kalian bisa ubah header nya langsung dari curl seperti ini
curl -H "Host: web.example.com" http://10.10.10.4Maka akan mendapatkan response dari Deployment Pod nya seperti contoh berikut ini
Hello from pod: web-app-5f9556ff68-frrlbRoute different path ke different Service.
Ini route:
example.com/api/* → api-serviceexample.com/web/* → web-serviceexample.com/* → frontend-serviceRoute different hostname ke different Service.
Ini route:
api.example.com → api-serviceweb.example.com → web-serviceadmin.example.com → admin-serviceIngress support tiga path type:
Match berdasarkan URL path prefix:
pathType: Prefix
path: /apiMatch: /api, /api/users, /api/v1/users
Match exact path saja:
pathType: Exact
path: /apiMatch: /api saja
Tidak match: /api/, /api/users
Depend on Ingress Controller implementation:
pathType: ImplementationSpecific
path: /apiBehavior vary by controller.
Enable HTTPS dengan TLS certificate.
mkdir cert-self-signed
nvim cert-self-signed/openssl.cnfKemudian isikan file konfigurasi openssl.cnf seperti berikut ini
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[dn]
CN = example.com
[req_ext]
subjectAltName = @alt_names
[alt_names]
DNS.1 = example.com
DNS.2 = *.example.comSelanjutnya generate menggunakan command berikut
openssl req -x509 -nodes -days 10365 \
-newkey rsa:2048 \
-keyout cert-self-signed/tls.key \
-out cert-self-signed/tls.crt \
-config cert-self-signed/openssl.cnf \
-extensions req_extsudo kubectl create secret tls example-tls \
--cert=cert-self-signed/tls.crt \
--key=cert-self-signed/tls.keysudo kubectl apply -f tls-ingress.ymlTip
HTTPS Request jika ingin valid menggunakan cert harus menggunakan SNI atau Server Name Indication, karena jika mengubah HTTP header seperti request curl sebelumnya dengan cara
curl -H "Host: example.com" https://10.10.10.4 -k -vItu tidak akan berhasil dan akan fallback ke default cert K3s yaitu dari Traefik (jika menggunakan default Ingress Controller di K3s), karena HTTP Header tersebut terjadi setelah proses TLS Handshake selesai.
curl -k --resolve example.com:443:10.10.10.4 https://example.com -vCustomize Ingress behavior dengan annotation (controller-specific).
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: annotated-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
spec:
rules:
- host: example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080Common annotation:
rewrite-target: Rewrite URL pathssl-redirect: Redirect HTTP ke HTTPSproxy-body-size: Max request body sizerate-limit: Rate limitingwhitelist-source-range: IP whitelistingSpecify default Service untuk unmatched request.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-with-default
spec:
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: 8080Request yang tidak match rule apapun pergi ke default-service.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: microservices-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
tls:
- hosts:
- app.example.com
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /api/users(/|$)(.*)
pathType: Prefix
backend:
service:
name: user-service
port:
number: 8080
- path: /api/orders(/|$)(.*)
pathType: Prefix
backend:
service:
name: order-service
port:
number: 8080
- path: /api/products(/|$)(.*)
pathType: Prefix
backend:
service:
name: product-service
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 3000# Production Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: production-ingress
namespace: production
spec:
tls:
- hosts:
- api.example.com
secretName: prod-tls
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
---
# Staging Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: staging-ingress
namespace: staging
spec:
rules:
- host: staging-api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080apiVersion: 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:
rules:
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 80Buat auth secret:
htpasswd -c auth admin
sudo kubectl create secret generic basic-auth --from-file=authTip
Jika kalian menggunakan default K3s Ingress Controller dimana Traefik, kalian bisa buat Ingress Basic Auth menggunakan CRD atau Custom Resource Definition dengan seperti ini
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: basic-auth
spec:
basicAuth:
secret: basic-authSetelah itu kalian bisa akses admin.example.com menggunakan command curl seperti ini
curl -k --resolve admin.example.com:443:10.10.10.4 https://admin.example.com -u admin:admin -vsudo kubectl get ingresssudo kubectl describe ingress web-ingressOutput:
Name: web-ingress
Namespace: default
Address: 203.0.113.10
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
web.example.com
/ web-service:80 (10.42.0.10:80,10.42.0.11:80,10.42.0.12:80)
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 2m nginx-ingress-controller Scheduled for syncsudo kubectl get ingress web-ingress -o yamlProblem: Ingress dibuat tapi tidak working.
Solusi: Install Ingress Controller dulu:
sudo kubectl get pods -n ingress-nginxProblem: Ingress tidak bisa find Service.
Solusi: Verify Service exist:
sudo kubectl get service <service-name>Problem: Tidak bisa access via hostname.
Solusi: Configure DNS atau gunakan /etc/hosts:
203.0.113.10 example.comProblem: HTTPS tidak working.
Solusi: Verify secret exist:
sudo kubectl get secret example-tlsProblem: Wrong Service receive traffic.
Solusi: Order path dari most specific ke least specific:
paths:
- path: /api/v2 # More specific dulu
- path: /api # Less specific setelah
- path: / # Catch-all terakhirSelalu enable HTTPS:
spec:
tls:
- hosts:
- example.com
secretName: example-tlsSeparate Ingress per environment:
# production namespace
name: production-ingress
namespace: production
# staging namespace
name: staging-ingress
namespace: stagingPilih descriptive Ingress name:
# Bagus
name: api-ingress
name: web-app-ingress
name: admin-portal-ingress
# Hindari
name: ingress1
name: ing
name: testIngress route ke Service, ensure Pod punya limit:
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"Protect against abuse:
annotations:
nginx.ingress.kubernetes.io/limit-rps: "10"
nginx.ingress.kubernetes.io/limit-connections: "5"Automate certificate management:
# Install cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yamlCheck Ingress Controller log:
sudo kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginxsudo kubectl get pods -n ingress-nginx
sudo kubectl logs -n ingress-nginx <controller-pod>sudo kubectl port-forward service/<service-name> 8080:80
curl http://localhost:8080nslookup example.com
dig example.comsudo kubectl describe ingress <ingress-name>Pada episode 19 ini, kita telah membahas Ingress di Kubernetes secara mendalam. Kita sudah belajar apa itu Ingress, bagaimana dia berbeda dari Service, dan cara menggunakannya untuk sophisticated HTTP/HTTPS routing.
Key takeaway:
Ingress essential untuk expose HTTP/HTTPS application di Kubernetes. Dengan memahami Ingress, kalian bisa build sophisticated routing configuration, manage TLS certificate, dan efficiently expose multiple Service melalui single entry point.
Bagaimana, makin jelas kan tentang Ingress di Kubernetes? Jadi, pastikan tetap semangat belajar dan nantikan episode selanjutnya!
Catatan
Untuk kalian yang ingin melanjutkan ke episode selanjutnya, bisa click thumbnail episode 19.1 di bawah ini