เปิด ingress.yaml ของ service หนึ่งใน cluster ที่เคยดูแล แล้วนับ annotation ได้ 17 บรรทัด ตั้งแต่ alb.ingress.kubernetes.io/scheme, target-type, certificate-arn, ssl-policy, healthcheck-path, ไปจนถึง actions.weighted-routing ที่เป็น JSON string ยัดอยู่ในค่า annotation ตัวเดียว อ่านครั้งแรกงงเลยว่า string นี้คือ routing rule จริง ๆ ไม่ใช่ comment ที่ลืมลบ
นี่แหละคือจุดที่ทำให้เริ่มมองหาทางอื่น ไม่ใช่เพราะ ALB Ingress Controller ห่วยนะ มันเสถียรมากด้วยซ้ำ ใช้กันมาเป็นมาตรฐานของ EKS หลายปีแล้ว แต่พอ cluster โตขึ้น มีหลายทีมมาแชร์กัน ปัญหาที่ annotation-based config มันไม่เคยถูกออกแบบมาแก้ ก็เริ่มโผล่ทีละอย่าง
ปัญหาที่ ALB Ingress Controller ไม่ได้ถูกออกแบบมาแก้
Ingress resource แบบเดิมมีข้อจำกัดที่ฝังอยู่ใน spec ตั้งแต่ต้น คือมันถูกออกแบบมาให้เป็น resource เดียว ครอบทุกอย่างตั้งแต่ layer 7 routing ไปจนถึง TLS termination ไปจนถึง load balancer attribute เฉพาะของ cloud provider — ทั้งหมดนี้ยัดผ่าน annotation ที่เป็น string ธรรมดา ไม่มี schema validation ไม่มี type checking พิมพ์ผิดตัวเดียวก็ deploy ผ่านเฉยๆ แล้วไปพังตอน runtime
ปัญหาที่เจอบ่อยที่สุดมีสามเรื่อง
เรื่องแรกคือ ownership ปนกัน ทีม platform ที่ดูแล load balancer scheme, security group, WAF association กับทีม app ที่แค่อยากเพิ่ม path ใหม่ ต้องมาแก้ resource เดียวกัน แก้ผิดจุดทีนึงกระทบทั้ง service เพราะ annotation ผูกกับ Ingress object ทั้งก้อน ไม่ได้แยกตาม concern
เรื่องที่สองคือ cross-namespace routing ทำได้ยาก อยากให้ path หนึ่งของ domain เดียวกันชี้ไป service ที่อยู่คนละ namespace ต้องเล่นทริค เช่น ExternalName service หรือรวม Ingress ไว้ namespace เดียวแล้วเปิดสิทธิ์ backend ข้าม namespace ซึ่งขัดกับ multi-tenant model ที่ EKS ส่วนใหญ่ใช้กันตอนนี้
เรื่องที่สามคือ debug ยาก เวลา routing ไม่ทำงานตามที่คิด ต้องไล่อ่าน annotation string ทีละตัว เทียบกับ AWS Load Balancer Controller log แล้วเดาว่า controller ตีความ annotation ยังไง เพราะ syntax ของ annotation ไม่ได้มี IDE autocomplete หรือ kubectl validation ช่วยเลย
Gateway API คืออะไร ทำไมถึงถูกพูดถึงเยอะขึ้น
Gateway API เป็น evolution ของ Ingress ที่ SIG-Network ผลักดันมาหลายปี จนตัว core API (v1) graduate เป็น GA ไปแล้ว หัวใจของมันคือการแยก role ออกจากกันเป็นสาม layer
GatewayClass เป็นของ cluster operator กำหนดว่า controller ตัวไหนจะจัดการ (เช่น AWS Gateway API Controller หรือ Istio) Gateway เป็นของทีม platform กำหนด listener, port, TLS cert, ผูกกับ load balancer จริง ส่วน HTTPRoute (หรือ GRPCRoute, TCPRoute) เป็นของทีม app แก้ path/routing rule ของตัวเองได้โดยไม่ต้องแตะ Gateway เลย
ข้อดีที่เห็นชัดสุดคือทีม app ขอ HTTPRoute resource แยกของตัวเอง อยู่คนละ namespace กับ Gateway ได้เลย ผ่าน ReferenceGrant ที่ทีม platform เป็นคนอนุญาตไว้ล่วงหน้า ทีม app ไม่ต้องรอ platform ทีมมาแก้ Ingress ก้อนใหญ่ทุกครั้งที่จะเพิ่ม path ใหม่
อีกจุดที่ต่างชัดคือ extensibility ผ่าน Policy attachment แทนการยัด annotation รวมกันหมด เช่นจะทำ retry policy หรือ traffic split ก็สร้างเป็น CRD แยกต่างหาก ผูกกับ Gateway/HTTPRoute ผ่าน targetRef ทำให้ตรวจสอบและ validate แยกเป็นชิ้นๆ ได้ ไม่ต้อง parse string เดา syntax เหมือนเดิม
เทียบกันตรงๆ
ลองแตกเป็นภาพเปรียบเทียบไว้ (ดูรูปประกอบด้านล่าง) สรุปสั้นๆ ตรงนี้ก่อน
ALB Ingress Controller ยังเป็นตัวเลือกที่ดีถ้า cluster เล็ก ทีมเดียวดูแลทั้งหมด ไม่ต้องการ cross-namespace routing ซับซ้อน และอยากได้ความเสถียรที่ผ่านการใช้งานจริงมานาน ส่วน Gateway API เหมาะกับ cluster ที่มีหลายทีมแชร์กัน ต้องการแยก ownership ชัดเจน หรือกำลังจะไปทาง multi-cluster/service mesh ในอนาคต เพราะ Gateway API ถูกออกแบบให้ทำงานร่วมกับ mesh ได้ตั้งแต่ต้น ไม่ใช่ patch ทีหลังแบบ Ingress
จุดที่ต้องคิดหนักคือ maturity ของ AWS Gateway API Controller เอง มันเป็นคนละ binary กับ AWS Load Balancer Controller ที่ใช้กับ Ingress อยู่แล้ว ต้อง install แยก และ feature parity บางตัวอย่าง sticky session, custom health check attribute ยังตามหลัง ALB Ingress Controller อยู่พอสมควร ถ้าจะย้ายต้องเช็ค feature ที่ใช้จริงในทีมก่อนว่ารองรับหรือยัง อย่าเชื่อ marketing slide เฉยๆ
ตัวอย่างการแปลงจาก Ingress annotation เป็น Gateway API
Ingress แบบเดิมที่ทำ weighted routing ระหว่างสอง service หน้าตาประมาณนี้
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: checkout
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/actions.weighted-routing: >
{"type":"forward","forwardConfig":{"targetGroups":[
{"serviceName":"checkout-v1","servicePort":"80","weight":90},
{"serviceName":"checkout-v2","servicePort":"80","weight":10}
]}}
spec:
rules:
- http:
paths:
- path: /checkout
pathType: Prefix
backend:
service:
name: weighted-routing
port:
name: use-annotation
แปลงเป็น Gateway API แยกเป็นสองไฟล์ ทีม platform ดูแล Gateway ทีม app ดูแล HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: shared-gw
namespace: platform-ingress
spec:
gatewayClassName: amazon-vpc-lattice # หรือ eks-alb ตาม controller ที่ใช้
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: allowed
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: checkout-route
namespace: checkout-team
spec:
parentRefs:
- name: shared-gw
namespace: platform-ingress
rules:
- matches:
- path:
type: PathPrefix
value: /checkout
backendRefs:
- name: checkout-v1
port: 80
weight: 90
- name: checkout-v2
port: 80
weight: 10
เห็นความต่างชัดๆ คือ weight ไม่ใช่ JSON string ที่ซ่อนใน annotation อีกแล้ว มันเป็น field จริงใน spec ที่ kubectl validate ได้ และทีม checkout แก้ HTTPRoute ของตัวเองได้เลยโดยไม่ต้องขอ access ไปแก้ Gateway ที่ platform ทีมดูแล
Checklist ก่อนตัดสินใจย้ายจริง
ถ้าคิดจะย้ายจริง อย่าทำทีเดียวทั้ง cluster ทำตามลำดับนี้ดีกว่า
- เช็ค EKS version ก่อน แนะนำ 1.28 ขึ้นไปเพื่อความเข้ากันได้ของ CRD ที่ Gateway API ต้องการ
- Inventory annotation ทั้งหมดที่ใช้อยู่จริงใน Ingress ปัจจุบัน แล้ว map ทีละตัวว่ามี field ตรงใน Gateway API หรือต้องใช้ Policy attachment เสริม
- Install AWS Gateway API Controller แยกต่างหาก อย่า uninstall AWS Load Balancer Controller เดิมทันที ให้รันคู่กันไปก่อนช่วง migration
- เลือก namespace ที่ non-critical สุดมา pilot ก่อน วัด behavior จริงของ weighted routing, health check, TLS
- ตรวจ feature parity ที่ทีมใช้จริง เช่น sticky session, custom timeout ว่า controller เวอร์ชันที่ใช้รองรับหรือยัง
- อัปเดต GitOps repo / Helm chart ให้ generate CRD ใหม่แทน Ingress annotation แล้ว review diff ให้ทีม platform เห็นก่อน merge
- เตรียม rollback plan ไว้เสมอ เผื่อ controller ที่ใช้ยังอยู่ใน early adoption แล้วเจอ edge case ที่ไม่คาดคิด
ข้อสุดท้ายสำคัญสุด อย่าลืมว่า AWS Gateway API Controller ยังใหม่กว่า AWS Load Balancer Controller มาก edge case ที่ไม่มีคนเจอมาก่อนมีสิทธิ์โผล่ได้เสมอ ย้ายแบบค่อยเป็นค่อยไป ดีกว่าเปลี่ยนทีเดียวแล้วมานั่งแก้กลางดึก
จะย้ายเลยไหม
ถ้า cluster เล็ก ทีมเดียวดูแล ALB Ingress Controller ยังทำงานได้ดีอยู่ ไม่ต้องรีบย้ายเพราะกระแส แต่ถ้าเริ่มเห็นสัญญาณแบบที่เล่าไปตอนต้น คือ annotation เยอะจนอ่านไม่ไหว หลายทีมแย่งกันแก้ Ingress ก้อนเดียว หรือกำลังวางแผนไปทาง service mesh ในปีหน้าอยู่แล้ว Gateway API คุ้มที่จะเริ่มทดลองตอนนี้ เพราะ ecosystem กำลังโตเร็ว รอช้าไปอาจต้อง migrate แบบเร่งรีบทีหลัง

Top comments (0)