Ingress #
Ketika kita merancang eksposur aplikasi web atau API ke luar kluster, kita diperkenalkan pada Service bertipe LoadBalancer. Tipe tersebut sangat andal untuk mengekspos satu layanan eksternal. Namun, seiring dengan pertumbuhan sistem kita menjadi arsitektur layanan mikro (microservices), kita akan mendapati diri kita memiliki puluhan layanan backend yang berbeda (misalnya layanan user, payment, dashboard, katalog, dst).
Jika kita membuat satu Service bertipe LoadBalancer untuk setiap layanan tersebut, kita akan dipaksa membayar biaya bulanan yang sangat mahal untuk puluhan Load Balancer fisik yang disediakan oleh cloud provider. Selain itu, mengelola puluhan alamat IP publik atau nama DNS publik eksternal yang berbeda-beda akan menjadi mimpi buruk operasional bagi tim SysOps.
Untuk menyelesaikan masalah efisiensi biaya dan fleksibilitas routing layer 7 ini, Kubernetes menyediakan objek khusus yang bernama Ingress. Ingress bertindak sebagai satu pintu gerbang masuk terpadu (single entry point) yang menerima seluruh lalu lintas data HTTP/HTTPS dari luar kluster, kemudian menyebarkannya ke layanan-layanan internal yang tepat berdasarkan aturan kueri nama domain host (host-based routing) atau jalur URL path (path-based routing).
Artikel ini akan mengulas secara mendalam komponen Ingress, cara kerja Ingress Controller, penulisan aturan manifes, instalasi TLS, optimasi anotasi produksi, serta evolusi menuju Gateway API.
Komponen Ingress: Resource vs Controller #
Salah satu konsep penting yang wajib kita pahami saat pertama kali menggunakan Ingress adalah pemisahan antara konfigurasi dan implementasi. Ingress di Kubernetes terbagi menjadi dua komponen yang terpisah:
flowchart TD
System["KUBERNETES INGRESS SYSTEM"]
System --> Resource["Ingress Resource (Berkas manifes YAML yang mendefinisikan aturan routing)"]
System --> Controller["Ingress Controller (Aplikasi reverse proxy aktif yang memproses lalu lintas data)"]
1. Ingress Resource #
Ini adalah manifes YAML standar Kubernetes yang kita buat untuk mendefinisikan rute lalu lintas. Di dalam manifes ini, kita menuliskan aturan seperti: “Jika ada lalu lintas masuk dengan domain api.example.com menuju URL path /payments, belokkan lalu lintas tersebut ke Service payment-service di Port 80”. Objek ini hanyalah data konfigurasi statis di dalam database etcd; objek ini tidak melakukan pemrosesan data apa pun sendiri.
2. Ingress Controller #
Ingress Controller adalah aplikasi reverse proxy dan load balancer aktif yang berjalan sebagai Pod di dalam kluster kita. Kubernetes tidak menyertakan Ingress Controller secara default saat kluster diinisialisasi. Kita wajib menginstalnya sendiri secara manual (misalnya menginstal NGINX Ingress Controller, Traefik, Kong, atau HAProxy).
Ingress Controller bertugas memantau (watch) Kubernetes API Server untuk setiap objek Ingress Resource yang kita buat. Begitu mendeteksi adanya konfigurasi baru atau perubahan rute, Ingress Controller akan memperbarui file konfigurasi reverse proxy internalnya secara dinamis dan melakukan reload (misalnya menulis ulang blok nginx.conf secara runtime) tanpa memutus koneksi aktif pengguna.
Alur Penanganan Ingress Request #
Mari kita perhatikan bagaimana paket data dari luar kluster mengalir melintasi komponen Ingress melalui diagram berikut:
flowchart TD
Client["Client luar (api.company.com/payments)"] --> LB["Cloud Load Balancer (NLB/ALB)"]
LB --> IngressCtrl["Ingress Controller Pod (NGINX/Envoy)"]
IngressCtrl -. Evaluasi rules .-> Svc["payment-service (ClusterIP)"]
Svc --> Pod1["Pod payment-0"]
Svc --> Pod2["Pod payment-1"]
Ketika client luar mengirimkan kueri HTTPS ke api.company.com/payments:
- Koneksi mendarat di satu-satunya Cloud Load Balancer fisik eksternal kita.
- Load Balancer meneruskan koneksi ke Pod Ingress Controller yang aktif di kluster.
- Ingress Controller menganalisis header HTTP kueri tersebut (menemukan host
api.company.comdan path/payments). - Ingress Controller mengevaluasi kecocokan aturan, lalu melompati ClusterIP Service internal dan mengirimkan lalu lintas tersebut langsung (direct bypass) ke salah satu alamat IP Pod backend
paymentyang sehat yang terdaftar di tabel Endpoints.
Struktur Manifes Ingress Produksi #
Mari kita pelajari contoh manifes Ingress standar produksi yang menggabungkan host-based routing, path-based routing, dan TLS termination:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: enterprise-ingress
namespace: production
annotations:
kubernetes.io/ingress.class: "nginx" # Menentukan tipe controller (legacy method)
nginx.ingress.kubernetes.io/ssl-redirect: "true" # Mengarahkan HTTP ke HTTPS otomatis
spec:
ingressClassName: nginx # Pilihan standar modern untuk menunjuk Ingress Controller
tls:
- hosts:
- api.mycompany.com
- app.mycompany.com
secretName: wildcard-tls-secret # Secret berisi sertifikat SSL/TLS
rules:
# 1. Host-based routing (api.mycompany.com)
- host: api.mycompany.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: gateway-api-service
port:
number: 8080
# 2. Path-based routing (app.mycompany.com)
- host: app.mycompany.com
http:
paths:
- path: /api/users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
- path: /api/billing
pathType: Exact
backend:
service:
name: billing-service
port:
number: 80
Penyelaman Parameter pathType
#
Kubernetes menyediakan tiga opsi pencocokan jalur URL path yang wajib kita tentukan secara tepat:
Exact: Kueri URL dari client harus cocok persis dengan karakter path yang ditulis. Sebagai contoh,/api/billinghanya akan cocok dengan/api/billing. Kueri seperti/api/billing/detailsatau/api/billing/akan menghasilkan error 404 (Not Found).Prefix: Kueri URL dinilai cocok jika memiliki awalan path yang sesuai. Sebagai contoh,/api/usersakan mencocokkan/api/users,/api/users/,/api/users/123, dan/api/users/profile. Opsi ini adalah yang paling umum kita gunakan untuk API routing.ImplementationSpecific: Algoritma pencocokan diserahkan sepenuhnya kepada implementasi internal Ingress Controller yang kita gunakan. Perilakunya dapat berbeda-beda antar penyedia controller.
TLS Termination dan Pengamanan HTTPS #
Salah satu fitur terbaik dari Ingress adalah kemampuannya melakukan TLS Termination (Pengakhiran TLS). Dengan TLS termination, proses jabat tangan kriptografi SSL/TLS yang berat didelegasikan sepenuhnya di tingkat Ingress Controller.
Lalu lintas data dari internet luar ke Ingress Controller berjalan di port aman 443 HTTPS terenkripsi. Setelah didekripsi di Ingress Controller, lalu lintas data diteruskan ke Pod internal kluster menggunakan port HTTP biasa (port 80). Hal ini sangat menghemat penggunaan daya CPU pada Pod aplikasi kita karena mereka tidak perlu melakukan proses enkripsi/dekripsi secara berulang-ulang.
1. Membuat Secret TLS Secara Manual #
Kita harus menyimpan berkas sertifikat SSL (.crt atau .pem) dan kunci privat (.key) kita ke dalam bentuk objek Secret Kubernetes bertipe kubernetes.io/tls:
kubectl create secret tls wildcard-tls-secret \
--cert=path/to/fullchain.pem \
--key=path/to/privkey.pem \
-n production
2. Integrasi Otomatis dengan cert-manager (Let’s Encrypt) #
Daripada memperbarui sertifikat SSL secara manual setiap tiga bulan sekali, kita sangat disarankan menginstal addon cert-manager. cert-manager akan berkolaborasi dengan Let’s Encrypt menggunakan protokol ACME untuk mengotomatiskan pembuatan, penerbitan, dan perpanjangan sertifikat SSL kita.
Kita cukup menambahkan anotasi khusus pada Ingress Resource kita:
apiVersion: v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-prod-account-key
solvers:
- http01:
ingress:
class: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auto-ssl-ingress
namespace: production
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod" # Memicu cert-manager membuat SSL otomatis
spec:
ingressClassName: nginx
tls:
- hosts:
- app.mycompany.com
secretName: app-tls-auto-secret # cert-manager akan menulis sertifikat Let's Encrypt ke Secret ini
rules:
- host: app.mycompany.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
Optimasi Anotasi Ingress NGINX untuk Produksi #
Karena spesifikasi dasar Ingress Kubernetes sangat sederhana, seluruh konfigurasi canggih tingkat lanjut reverse proxy (seperti rate limiting, CORS, rewrite, dst) diselesaikan menggunakan annotations yang spesifik sesuai dengan Ingress Controller yang kita pilih.
Berikut adalah anotasi penting untuk NGINX Ingress Controller yang sering kita butuhkan di produksi:
1. Rate Limiting (Pencegahan DDOS & Brute Force) #
Membatasi jumlah permintaan koneksi dari satu alamat IP client per detik demi mengamankan ketersediaan backend:
nginx.ingress.kubernetes.io/limit-rps: "15" # Maksimal 15 request per detik dari satu IP client
nginx.ingress.kubernetes.io/limit-burst-multiplier: "3"
2. Mengizinkan Unggahan File Besar #
Secara default, NGINX membatasi ukuran body request maksimal 1MB. Jika aplikasi kita memiliki fitur unggah file gambar atau dokumen, kita harus menaikkan batas ini agar tidak mengalami error 413 Request Entity Too Large:
nginx.ingress.kubernetes.io/proxy-body-size: "50m" # Menaikkan batas unggahan file hingga 50 MegaBytes
3. Konfigurasi CORS (Cross-Origin Resource Sharing) #
Mengizinkan aplikasi frontend di domain lain (misalnya mobile app atau partner API) untuk melakukan kueri ke API kluster secara aman:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://my-partner-domain.com"
4. Konfigurasi Timeout Koneksi #
Mencegah koneksi tertahan terlalu lama saat memproses kueri database yang berat:
nginx.ingress.kubernetes.io/proxy-read-timeout: "120" # Batas waktu baca timeout disetel ke 120 detik
nginx.ingress.kubernetes.io/proxy-send-timeout: "120"
Ingress vs Gateway API: Masa Depan Routing Jaringan #
Meskipun Ingress sangat sukses, spesifikasi Ingress memiliki keterbatasan struktural yang mendasar. Karena spesifikasi Ingress dibuat sangat sederhana, konfigurasi kompleks akhirnya ditumpuk pada annotations. Hal ini membuat manifes Ingress antar kluster tidak portable (misalnya anotasi NGINX tidak bisa dipahami oleh Traefik). Selain itu, Ingress memaksakan satu file manifes dikelola bersama oleh SysOps (mengurus domain/SSL) dan Developer (mengurus path routing).
Untuk mengatasi keterbatasan ini, CNCF mengembangkan Gateway API sebagai standar routing modern generasi berikutnya.
flowchart TD
Ops["1. Cluster Operator / SysOps (Mengurus GatewayClass)<br>'Gunakan Controller Envoy untuk Load Balancer'"]
Ops --> Plat["2. Platform Engineer (Mengurus Gateway)<br>'Buka Port 443 HTTPS dengan SSL Wildcard Domain'"]
Plat --> Dev["3. Application Developer (Mengurus HTTPRoute)<br>'Petakan path /payments ke Service payment-service'"]
Kelebihan Utama Gateway API #
- Separation of Concerns: Memisahkan tanggung jawab pengelolaan jaringan secara deklaratif melalui objek-objek terpisah (
GatewayClass,Gateway, danHTTPRoute). - Kecanggihan Bawaan: Mendukung fitur canggih seperti weighted traffic splitting (canary deployment), header-based routing, dan URL redirection secara standar langsung dari spec API tanpa bantuan annotations.
- Keamanan Multi-Tenant: Platform Engineer dapat menentukan kebijakan keamanan ketat di objek
Gatewayuntuk membatasi namespace mana saja yang boleh membuat objekHTTPRoutedi domain tertentu.
Anti-Pattern vs Solusi dalam Desain Ingress #
Mari kita pelajari beberapa kesalahan konfigurasi fatal yang sering kita temukan saat mengimplementasikan Ingress di kluster produksi.
Anti-Pattern 1: Mengabaikan Penentuan ingressClassName Modern
#
Kita mendeploy objek Ingress Resource tanpa menyertakan properti ingressClassName, melainkan mengandalkan anotasi legacy kubernetes.io/ingress.class: "nginx".
Kode Manifest Salah (Gaya Lama Tanpa Kelas Eksplisit) #
# JANGAN GUNAKAN STYLE INI LAGI
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress-legacy
namespace: production
annotations:
kubernetes.io/ingress.class: "nginx" # ANOTASI LEGACY: Rentan diabaikan oleh kluster modern
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80
Konsekuensi Buruk #
Mulai Kubernetes versi 1.22+, anotasi kubernetes.io/ingress.class telah dinyatakan deprecated (usang). Jika kluster kita menjalankan lebih dari satu Ingress Controller (misalnya menjalankan NGINX untuk akses publik dan Kong untuk API Gateway internal), mengosongkan properti ingressClassName dapat memicu kegagalan routing karena tidak ada controller yang merasa bertanggung jawab memproses manifest tersebut.
Kode Solusi (Gaya Modern Deklaratif) #
# SOLUSI: Selalu gunakan properti ingressClassName yang eksplisit
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress-modern
namespace: production
spec:
ingressClassName: nginx # Eksplisit memilih NGINX Ingress Controller
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80
Anti-Pattern 2: Salah Konfigurasi Regex pada Anotasi URL Rewrite #
Kita ingin agar seluruh request dengan URL prefix /api diteruskan ke backend aplikasi web kita, tetapi kita ingin agar Ingress memotong kata /api tersebut saat paket tiba di backend (misalnya kueri /api/v1/users di-rewrite menjadi /v1/users).
Kode Manifest Salah (Rewrite Tanpa Capturing Group) #
# JANGAN LAKUKAN INI: Memotong path secara mentah
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress-rewrite-failure
namespace: production
annotations:
nginx.ingress.kubernetes.io/rewrite-target: / # Menimpa seluruh path menjadi root!
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /api # Tanpa regex capturing group
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 80
Konsekuensi Buruk #
Dengan konfigurasi di atas, jika client mengakses http://app.example.com/api/v1/users, NGINX akan menimpa seluruh URL path tersebut menjadi root /. Aplikasi backend kita akan menerima request di path / dan mengembalikan respon error 404 karena path /v1/users hilang seluruhnya akibat proses rewrite yang salah sasaran.
Kode Solusi (Menggunakan Capturing Group Regex secara Tepat) #
# SOLUSI: Gunakan capturing group regex untuk melestarikan sub-path
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress-rewrite-success
namespace: production
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2 # Mengambil sisa path dari group kedua ($2)
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /api(/|$)(.*) # Group 1: (/|$), Group 2: sisa path (.*)
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 80
Panduan Praktis Debugging Konektivitas Ingress #
Jika domain publik kita mengembalikan pesan error 502 Bad Gateway atau 503 Service Temporarily Unavailable, berikut adalah langkah-langkah audit sistematis:
1. Memeriksa Alamat IP Ingress #
Pastikan API Server berhasil memberikan alokasi IP eksternal publik pada objek Ingress kita:
kubectl get ingress -n production
Jika kolom ADDRESS kosong setelah beberapa menit, periksa apakah Ingress Controller telah dikonfigurasi dengan LoadBalancer Service yang sehat.
2. Memeriksa Log Ingress Controller Pod #
Kunci utama pemecahan masalah Ingress berada di dalam berkas log pod controller-nya. Cari pod NGINX Ingress Controller di namespace kube-system atau namespace kustomnya:
# Mengambil log dari NGINX Ingress Controller
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=100
Tinjau apakah ada baris log berisi error reload:
"Configuration is invalid ...": Terjadi kesalahan sintaksis pada regex path atau parameter SSL secret yang kita definisikan."502 Bad Gateway": Ingress Controller berhasil mengidentifikasi rute, tetapi Pod backend aplikasi kita tidak merespon (misalnya Pod crash atau port kontainer tidak cocok dengan targetPort Service).
Ringkasan #
- Ingress meminimalkan cloud cost: Menggunakan satu unit Load Balancer cloud untuk melayani puluhan Service internal kluster melalui mekanisme routing HTTP layer 7.
- Pahami peran Controller vs Resource: Ingress Resource adalah berkas konfigurasi statis, sedangkan Ingress Controller (seperti NGINX) adalah engine proxy aktif yang menjalankan aturan tersebut.
- Implementasikan TLS Termination: Bebaskan beban CPU Pod aplikasi kita dari proses dekripsi SSL/TLS dengan mengakhiri koneksi HTTPS secara aman di tingkat Ingress Controller.
- Gunakan cert-manager untuk manajemen SSL: Otomatiskan proses pembuatan dan perpanjangan sertifikat SSL Let’s Encrypt dengan mengintegrasikan cert-manager langsung ke Ingress Resource.
- Manfaatkan annotations untuk fitur produksi: Konfigurasi rate limiting, proxy body size, CORS, dan timeout koneksi menggunakan annotations spesifik controller.
- Gunakan regex capturing group untuk rewrite: Pastikan penulisan target rewrite URL menyertakan capturing group agar tidak merusak segmentasi sub-path yang dikirim ke aplikasi backend.
← Sebelumnya: DNS & Service Discovery Berikutnya: Network Policy →