Senin, 27 Juli 2026

Ganti Ingress Lawas dengan Kubernetes Gateway API: Nggak Ada Lagi Spaghetti Annotation!

Kalau pernah ngelola Kubernetes di environment production, pasti tau rasanya nempel berderet-deret annotations cuma buat aktifin fitur simpel kayak SSL redirect, canary deployment, atau rate limiting.

Hasilnya? File YAML jadi mirip mi goreng—panjang, ruwet, dan ngunci kita ke satu vendor controller doang (misalnya NGINX Ingress Controller). Begitu mau pindah ke cloud provider lain atau ganti controller, semua manifes Ingress harus dirombak ulang dari nol.

Kubernetes SIG-Network paham betul penderitaan ini. Makanya mereka merilis Kubernetes Gateway API. Ini bukan sekadar CRD kustom biasa, tapi standar baru evolusi jaringan di Kubernetes yang jauh lebih terstruktur, portabel, dan didesain khusus buat kolaborasi multi-tim.

Yuk, kita bahas cara kerja, fitur dasar, sampai praktik hands-on-nya dengan gaya santai dan langsung ke poin utama!


TL;DR

  • Bebas Annotation Aneh: Fitur kayak canary release, header routing, dan URL redirect sekarang jadi spesifikasi native. YAML tetep bersih dan langsung tervalidasi sama OpenAPI schema Kubernetes.

  • Role-Oriented: Akses RBAC dipisah tegas. Tim Infra ngurus infrastruktur Load Balancer (Gateway), tim Developer cuma fokus bikin aturan route aplikasinya (HTTPRoute).

  • Beneran Portabel: Cukup tulis aturan perutean sekali pakai HTTPRoute, manifesnya bisa langsung jalan di atas Envoy Gateway, Cilium, Istio, maupun GKE tanpa perlu diubah sama sekali.

Kenapa Ingress Lawas Mulai Nggak Enak Dirasa?

Spesifikasi Ingress standar yang dibuat tahun 2015 udah kewalahan menghadapi arsitektur cloud-native modern. Ada dua masalah utama yang sering bikin tim DevOps pusing:

1. Pusing di RBAC & Masalah Keamanan

Di Ingress biasa, konfigurasi domain, sertifikat TLS, sampai aturan routing mikro aplikasi ditumpuk di satu file .yaml.

Efek sampingnya: kalau tim Developer mau nambah path baru (/api/v2), mereka terpaksa harus dikasih akses edit Ingress. Sekali ada salah ketik atau keteledoran, sertifikat TLS production bisa kepotong atau domain milik tim akhir malah tidak sengaja tertimpa.

2. Untyped Annotations Itu Jebakan Batman

Ingress bawaan cuma paham aturan path paling standar. Fitur sisanya diserahkan ke vendor lewat annotations.

Masalahnya, annotation itu cuma string mentah tanpa validasi dari API server Kubernetes. Kalau salah ketik nama header di annotation NGINX, kubectl apply bakal tetep bilang success. Tapi fiturnya diem-diem ga jalan (silent failure), dan baru ketahuan pas user komplain di production.

Perbandingan Cara Kerja: Di Balik Layar (Under the Hood)

Biar makin kebayang bedanya, mari kita bedah alur kerja teknis bagaimana Ingress Controller dan Gateway API Controller memproses request dan konfigurasi di dalam cluster.

Alur Kerja Ingress Controller (Pendekatan Monolitis)

[ User Request ] ──► [ Public Load Balancer / IP ]
                            │
                            ▼
                [ Ingress Controller (NGINX/Traefik) ]
                  (Membaca Single Monolithic Ingress YAML)
                            │
                            ▼
                  [ Service ] ──► [ Pods ]

  1. Monolithic Watch: Controller cuma mantau satu jenis objek yaitu Ingress.

  2. String Parsing Annotation: Controller harus membedah baris-baris string di bagian annotations. Setiap vendor punya logika parser sendiri yang tidak saling kompatibel.

  3. Regenerasi Konfigurasi Proxy: Jika ada perubahan pada satu objek Ingress, controller akan meregenerasi file konfigurasi internal proxy (misalnya nginx.conf atau tabel perutean Envoy xDS) secara menyeluruh. Jika ada puluhan tim yang mengedit objek Ingress di namespace berbeda, risiko konflik atau reload error sangat tinggi.

Alur Kerja Gateway API (Pendekatan Decoupled & Event-Driven)

[ User Request ] ──► [ Gateway / Load Balancer ] 
                            │  (Dibuat via Gateway & GatewayClass)
                            ▼
                   [ HTTPRoute Matching ]
                            │  (Divalidasi via OpenAPI & ReferenceGrant)
                            ▼
                  [ Service ] ──► [ Pods ]

  1. Separation of Provisioning & Routing:

    • Saat GatewayClass dan Gateway diterapkan, Gateway Controller secara otomatis memesan alokasi IP publik, membuka port listener, dan menyiapkan instance Load Balancer (baik berupa Pod Envoy internal maupun Cloud Load Balancer seperti GCP Cloud Armor/ALB).

  2. Dynamic Binding via parentRefs:

    • Saat Developer membuat HTTPRoute, objek ini secara aktif mendaftarkan diri (binding) ke Gateway tujuan melalui atribut parentRefs.

  3. Strict Validation & Handshake Check:

    • Sebelum lalu lintas diteruskan ke Pod, controller melakukan validasi dua arah:

      • Apakah Gateway mengizinkan HTTPRoute dari namespace ini (allowedRoutes)?

      • Jika menarget Service di namespace lain, apakah ada bukti izin berupa ReferenceGrant?

  4. Targeted Routing Update:

    • Perubahan pada satu HTTPRoute milik tim A tidak akan mengganggu infrastruktur Gateway utama maupun perutean milik tim B. Setiap perubahan terisolasi dengan rapi di level route.

Solusinya: Pemisahan Tanggung Jawab (Separation of Concerns)

Gateway API membereskan masalah ini dengan memecah manifes monolitis jadi 3 objek terpisah yang disesuaikan dengan peran tim di perusahaan:

         [ Tim Infra / Cloud Provider ]
                       │
                       ▼
   GatewayClass (Blueprint Load Balancer)
                       │
                       ▼
          [ Tim DevOps / Admin Cluster ]
                       │
                       ▼
   Gateway (Entry Point: IP, Port, TLS)
                       │
                       ▼
          [ Tim Application Developer ]
                       │
                       ▼
   HTTPRoute (Aturan Routing ke Service)

Sederhananya:

  1. GatewayClass (Dikelola Infra/Cloud): Menentukan jenis/teknologi Load Balancer yang dipakai di cluster (Envoy, Cilium, GKE, dll).

  2. Gateway (Dikelola DevOps/Cluster Admin): Menyiapkan pintu masuk fisik, seperti alokasi IP publik, pembukaan port (80/443), dan sertifikat TLS.

  3. HTTPRoute (Dikelola App Dev): Mengatur logika perutean lalu lintas dari Gateway ke Service aplikasi. Developer punya kendali penuh di sini tanpa perlu minta izin akses ke infrastruktur global.

Fitur-Fitur Dasar (Tanpa Trik Annotation!)

Fitur jaringan yang paling sering kita pakai sehari-hari sekarang sudah tersedia sebagai atribut baku di dalam spesifikasi HTTPRoute.

1. Traffic Splitting / Canary Release

Mau deploy aplikasi versi baru secara bertahap (misal 90% ke v1 dan 10% ke v2)?:

rules:
  - backendRefs:
      - name: app-v1-service
        port: 8080
        weight: 90  # 90% traffic ke v1
      - name: app-v2-service
        port: 8080
        weight: 10  # 10% traffic ke v2 (canary)

2. Header-Based Routing

Pengen lempar traffic dengan header khusus (misal buat pengujian internal tim QA) ke service terpisah?:

rules:
  - matches:
      - headers:
          - name: env
            value: beta
    backendRefs:
      - name: app-beta-service
        port: 8080

3. HTTP Redirect (Paksa HTTP ke HTTPS)

Pengalihan traffic (seperti paksa HTTP ke HTTPS pakai status code 301) handled secara native:

rules:
  - filters:
      - type: RequestRedirect
        requestRedirect:
          scheme: https
          statusCode: 301

Panduan Hands-On: Implementasi Sederhana

Untuk melihat gambaran nyatanya, yuk kita coba deploy aplikasi sederhana yang di-expose pakai Gateway dan HTTPRoute.

1. Siapkan Aplikasi Sample (Deployment & Service)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  namespace: default
  labels:
    app: web-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
      - name: nginx
        image: nginxdemos/hello:plain-text
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web-service
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: web-app
  ports:
  - port: 80
    targetPort: 80

2. Bikin Objek Gateway (Pintu Masuk Traffic)

Catatan: Sesuaikan gatewayClassName dengan controller yang terpasang di cluster kamu (misalnya eg untuk Envoy Gateway, cilium untuk Cilium Gateway, atau gke-l7-global-external-managed untuk Google Cloud).

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: main-gateway
  namespace: default
spec:
  gatewayClassName: eg
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: Same

3. Bikin Objek HTTPRoute (Aturan Routing Aplikasi)

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: web-app-route
  namespace: default
spec:
  parentRefs:
  - name: main-gateway
    sectionName: http
  hostnames:
  - "app.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: web-service
      port: 80

4. Eksekusi dan Pengujian

  1. Terapkan Manifest:

    kubectl apply -f web-app.yaml
    kubectl apply -f main-gateway.yaml
    kubectl apply -f httproute.yaml
    
  2. Cek IP External Load Balancer:

    kubectl get gateway main-gateway
    

    Tunggu sampai kolom ADDRESS terisi IP Publik Load Balancer.

  3. Uji Akses HTTP:

    curl -H "Host: app.example.com" http://<EXTERNAL-IP-GATEWAY>
    

Aman dari Route Hijacking (ReferenceGrant)

Di Ingress lama, siapa pun yang punya akses bikin Ingress di namespace mana pun bisa aja ngaku-ngaku memakai domain yang sama dan nyuri traffic dari namespace lain (route hijacking).

Gateway API mencegah ini pakai mekanisme "jabat tangan" antar-namespace yang dipatok ketat.

Secara default, kalau objek Gateway milik DevOps ada di namespace infra-system, lalu tim Dev bikin HTTPRoute di namespace dev-team, Gateway bakal nolak nerusin traffic ke Service milik dev-team.

Biar bisa tersambung, tim Dev harus secara sadar ngasih izin pakai objek ReferenceGrant:

apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-infra-gateway
  namespace: dev-team
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: Gateway
      namespace: infra-system
  to:
    - group: ""
      kind: Service

(Catatan: Gunakan apiVersion: gateway.networking.k8s.io/v1 jika cluster kamu sudah menggunakan CRD Gateway API v1.3+ terbaru).

Logikanya: "Kami dari namespace dev-team secara sadar mengizinkan Gateway dari namespace infra-system untuk ngirim traffic ke Service di dalam namespace ini."

Cara Troubleshooting Pas Traffic Nggak Connect

Kalau traffic aplikasi ga nyampe ke Pod tujuan, jangan langsung curiga kodingan aplikasinya yang error. Cek dulu status diagnostik Gateway API yang sudah terstandarisasi.

Jalankan perintah ini:

kubectl describe httproute <nama-httproute> -n <namespace>

Langsung scroll ke bagian Status.Conditions:

  • Accepted: True

    Aturan routing kamu valid dan berhasil diterima oleh controller. Kalau False, coba cek apakah nama parentRefs (nama Gateway-nya) udah bener atau typo.

  • ResolvedRefs: True

    Semua target Service dan port yang dirujuk berhasil ditemukan di cluster. Kalau False, biasanya karena salah ketik nama Service, port ga cocok, atau lupa masang ReferenceGrant (kalau beda namespace).

  • Programmed: True

    Konfigurasi sudah sukses terpasang di hardware / proxy Load Balancer fisik.

Kesimpulan

Kubernetes Gateway API bukan dibuat untuk menambah beban bikin YAML baru, tapi justru buat ngerapiin keos-nya arsitektur jaringan yang selama ini ditutupi annotation Ingress.

Dengan migrasi ke Gateway API:

  1. File YAML aplikasi jadi bersih dan tervalidasi otomatis oleh Kubernetes API server.

  2. Pembagian tugas tim Infra, DevOps, dan Developer jadi jelas sesuai batasan RBAC.

  3. Bebas dari vendor lock-in—pindah controller tinggal tancap tanpa ubah spesifikasi route.

Buat yang mau nyoba, mulai aja dari hal kecil: bikin 1 Gateway sederhana dan 1 HTTPRoute di lingkungan staging. Cobain sendiri bedanya!

Tidak ada komentar:

Posting Komentar