Trong nhiều năm, Ingress NGINX là cách rất quen thuộc để publish ứng dụng ra bên ngoài trong Kubernetes. Nó đủ đơn giản, đủ dễ dùng và đã theo rất nhiều hệ thống đi qua giai đoạn đầu.

Nhưng khi nhu cầu routing, bảo mật và vận hành bắt đầu phức tạp hơn, mô hình này cũng bắt đầu không còn đáp ứng tốt. Cấu hình ngày càng dồn nhiều vào annotations, ranh giới giữa phần việc của hạ tầng với ứng dụng ngày càng mờ, còn những nhu cầu mới như canary, header-based routing hay multi-protocol thì không còn dễ xử lý như trước.
Nếu tiếp tục giữ cách làm cũ, lớp traffic management sẽ ngày càng khó đọc, khó mở rộng và khó vận hành an toàn. Đó là lý do Gateway API đang được xem là hướng đi kế tiếp rõ ràng hơn cho Kubernetes. Bài viết này sẽ đi vào đúng chỗ đó: vì sao Ingress NGINX không còn phù hợp như trước, Gateway API giải quyết được gì, và nên migration theo cách nào để giảm rủi ro.
Nguyên nhân Ingress NGINX dừng hoạt động
Nguyên nhân chính khiến Ingress NGINX không còn được tiếp tục sử dụng là do thành phần này đã chính thức kết thúc vòng đời hỗ trợ (EOL) vào tháng 3 năm 2026. Việc ngừng hỗ trợ này dẫn đến một số vấn đề đáng lo ngại, cụ thể như sau:
- Rủi ro bảo mật nghiêm trọng: vì Ingress NGINX đã EOL, các lỗ hổng bảo mật phát sinh trong tương lai sẽ không còn được cung cấp các bản vá lỗi. Các sự cố bảo mật gần đây với các lỗ hổng nguy hiểm mang mã CVE-2026-24512 và CVE-2026-3288, thậm chí có lỗ hổng nghiêm trọng hơn IngressNightmare nhằm tấn công qua http khai thác cấu hình secret, mật khẩu, chứng chỉ mật sâu bên trong lan rộng trên toàn bộ cụm Kubernetes
- Ngưng cập nhật tính năng mới: Mặc dù bản thân Kubernetes Ingress API vẫn được hỗ trợ duy trì, nhưng nó đã ở trạng thái đóng băng tính năng. Điều này có nghĩa là công nghệ này sẽ không còn được cập nhật hay phát triển thêm bất kỳ tính năng mới nào để đáp ứng các nhu cầu mạng hoặc định tuyến hiện đại phức tạp hơn.
Vì những lý do này, Kubernetes đã khuyến nghị người dùng nên từ bỏ Ingress NGINX và chuyển sang Kubernetes Gateway API, hệ thống được chỉ định kế nhiệm thay thế chính thức với nhiều tính năng hỗ trợ mạnh mẽ và linh hoạt hơn
Kubernetes Gateway API
Kubernetes Gateway API là bản thay thế chính thức của hệ thống Ingress NGINX cũ, được xây dựng để đáp ứng các mô hình mạng dành cho Kubernetes multi-team hiện đại.
Về bản chất, Gateway API là một spec và API resources tiêu chuẩn mới của Kubernetes để quản lý luồng traffic từ bên ngoài vào cluster, và nó được triển khai vào thực tế thông qua các controllers từ các dự án mã nguồn mở hoặc từ các nhà cung cấp dịch vụ cloud.
Kubernetes Gateway API hoạt động dựa trên thiết kế phân quyền (role-oriented), tách biệt rõ ràng việc quản lý luồng lưu lượng thành các tài nguyên độc lập dành cho các vai trò vận hành khác nhau:
- GatewayClass: Được quản lý bởi Infrastructure Provider (như AWS, GCP, Azure, Istio). Nó xác định loại Controller và hạ tầng cấp thấp (underlying infrastructure) nào sẽ được triển khai.
- Gateway: Được quản lý bởi Cluster Admin/Platform Operator. Nó quản lý các entry points để nhận traffic dùng chung (bao gồm ports, protocols, TLS) và thiết lập các ràng buộc bảo mật để kiểm soát nghiêm ngặt những Route hoặc namespace nào được phép attach vào Gateway
- Route: Được quản lý bởi nhà phát triển ứng dụng. Tài nguyên này định nghĩa các rule routing cụ thể (dựa trên path, header, hostname) để đẩy request về đúng backend services của ứng dụng.
- ReferenceGrant: Tài nguyên dùng để cho phép và cấp quyền tạo các tham chiếu chéo giữa các namespace khác nhau một cách an toàn.
Dưới đây là những khác biệt chính giữa Gateway API và Ingress NGINX
- Phân quyền rõ ràng vs. Dùng chung cấu hình: Ingress NGINX gom toàn bộ cấu hình hạ tầng mạng và ứng dụng vào một đối tượng duy nhất, buộc các admin và dev phải chia sẻ chung trách nhiệm, điều này thường dễ gây ra các xung đột ưu tiên. Gateway API giải quyết vấn đề này bằng cách trao quyền kiểm soát Gateway cho quản trị viên cụm và quyền kiểm soát Route cho nhà phát triển ứng dụng, thiết lập ranh giới vận hành rõ ràng
- Loại bỏ phụ thuộc vào annotations: Ingress NGINX phụ thuộc rất nhiều vào các custom annotations để định cấu hình các chức năng nâng cao. Gateway API chuyển hóa các tính năng này thành một tiêu chuẩn trực tiếp trên core API, đảm bảo tính nhất quán trên nhiều nền tảng.
- Định tuyến nâng cao và Đa giao thức: So với khả năng khớp đường dẫn HTTP đơn giản của Ingress API cũ, Gateway API cung cấp sẵn khả năng chia nhỏ traffic ứng dụng cho các chiến lược canary hay blue/green deployment, định tuyến theo header, và đặc biệt là hỗ trợ đa giao thức trên cả Layer 4 và Layer 7 (gồm HTTP, gRPC, TCP, UDP, và các kết nối dài hạn cho AI).
- Kiểm soát Cross-namespace: Ingress NGINX thường mặc định cho phép trỏ tới các backend thuộc namespace khác. Đối với Gateway API, kết nối chéo này yêu cầu phải có một xác thực bảo mật rõ ràng thông qua tài nguyên ReferenceGrant; nếu không có tài nguyên này, Route sẽ bị từ chối kết nối
- Quản trị qua policies: Cluster operators có thể attach thẳng các policy vào logic định tuyến để áp đặt các quy định vận hành chung như rate limiting, WAF, audit logging, và retry/timeout lên toàn bộ cluster.
Migration từ Ingress NGINX sang Kubernetes Gateway API
Quá trình migration từ Ingress NGINX sang Kubernetes Gateway API đòi hỏi một phương pháp tiếp cận có cấu trúc và từng bước để đảm bảo tính an toàn. Dưới đây là quy trình 7 bước chi tiết để thực hiện:
1. Chọn controller cho Gateway API
Trước khi bắt đầu migration, cần xác định rõ rằng Gateway API chỉ là spec, không phải controller hoàn chỉnh. Vì vậy trước khi migration, cần chọn một Gateway API controller phù hợp để thực thi các tài nguyên như Gateway, GatewayClass và Route.
Việc chọn controller là bước đầu tiên và quan trọng, vì nó quyết định cách routing hoạt động, mức hỗ trợ tính năng và cách bạn vận hành hệ thống sau này.
Không có một controller tốt nhất cho mọi trường hợp. Cần chọn theo:
- loại traffic đang có, nhất là có dùng TCP/UDP hay không?
- môi trường triển khai là self-managed/bare-metal hay cloud-managed
- mô hình vận hành hiện tại, ví dụ có dùng service mesh hay không?
Các nhóm controller phổ biến có thể hiểu đơn giản như sau:
- NGINX Gateway Fabric: phù hợp nếu đang đi lên từ
ingress-nginx, muốn migration nhẹ và quen cách vận hành cũ. - Istio: phù hợp nếu hệ thống đã có hoặc sẽ dùng service mesh.
- Envoy Gateway: phù hợp nếu nền tảng đang chuẩn hóa theo Envoy.
- Cloud-managed controller: phù hợp nếu chạy trên cloud và muốn giảm công tự vận hành.
Với hệ thống đang dùng Ingress NGINX, cần kiểm tra thêm xem có xử lý Layer 4 traffic hay không bằng:
kubectl get configmap tcp-services -n ingress-nginx
kubectl get configmap udp-services -n ingress-nginx
Mục tiêu của bước này không phải chọn controller mạnh nhất, mà là chọn controller phù hợp nhất với hạ tầng hiện tại, loại traffic đang có và cách vận hành của đội ngũ.
2. Thiết lập baseline trước khi migration
Trước khi migration sang Gateway API, cần thiết lập baseline vận hành để trả lời hai câu hỏi: hệ thống hiện tại có thực sự cần migration hay chưa, và nếu có thì đã đủ điều kiện để đi tiếp sang bước triển khai song song hay chưa.
Ở bước này, mục tiêu không chỉ là đo hiệu năng, mà còn là đánh giá hiện trạng của hệ thống đang chạy trên Ingress NGINX. Cần xem kiến trúc hiện tại có còn phù hợp với nhu cầu kỹ thuật và vận hành hay không, đặc biệt ở các điểm như:
- cấu hình routing có đang phụ thuộc quá nhiều vào annotations
- hệ thống có bắt đầu xuất hiện nhu cầu routing nâng cao như canary, header-based routing hoặc multi-protocol
- việc áp dụng các policy vận hành chung như timeout, retry, rate limit hoặc logging có đang khó kiểm soát
Sau đó, cần ghi nhận baseline từ traffic thực tế đi qua toàn bộ tuyến truy cập bên ngoài. Các chỉ số tối thiểu nên theo dõi gồm:
- Request volume: lưu lượng request bình thường của hệ thống
- Latency: nên theo dõi thêm p95 hoặc p99, không chỉ giá trị trung bình
- Error rate: đặc biệt là lỗi 5xx
- Có thể bổ sung thêm 4xx, upstream failures, traffic theo host/path, log hoặc trace nếu hệ thống cần quan sát sâu hơn
Kết thúc bước này, cần chốt rõ có nên đi tiếp sang Bước 3 hay không. Chỉ nên triển khai Gateway API song song khi đã xác định rõ lý do migration, có baseline đủ tin cậy.
3. Cài Gateway API song song với Ingress NGINX cũ
Sau khi thiết lập baseline, nhiệm vụ tiếp theo là triển khai Gateway API bằng NGINX Gateway Fabric song song với Ingress NGINX hiện tại để tạo một nhánh traffic mới phục vụ test migration.
Trong phần này DevOps VietNam sẽ đưa ra phương hướng để thiết lập cơ chế try & fallback ngay tại Load Balancer. NGINX Gateway Fabric được dùng như một cách triển khai tham khảo. Điều cần quan tâm không phải là controller cụ thể, mà là nguyên tắc: lớp routing mới phải được tách khỏi luồng hiện tại để dễ quan sát và rollback.
Mô hình luồng dữ liệu:
- Luồng cũ:
User Request->http://game-2048.sample.com->Ingress NGINX(30080) -> Apps. - Luồng mới:
User Request->http://new-game-2048.sample.com->NGINX Gateway Fabric(31080) ->HTTPRoute-> Apps (V2)

3.1 Cài Gateway API CRDs
Trước hết, cần cài các CRDs của Gateway API để cluster có thể làm việc với các resource như GatewayClass, Gateway, HTTPRoute và ReferenceGrant.
kubectl kustomize "https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/standard?ref=v2.5.1" | kubectl apply -f -
Kiểm tra các CRDs đã được cài đặt:
kubectl get crd | grep gateway.networking.k8s.io
Output như sau:
backendtlspolicies.gateway.networking.k8s.io
gatewayclasses.gateway.networking.k8s.io
gateways.gateway.networking.k8s.io
grpcroutes.gateway.networking.k8s.io
httproutes.gateway.networking.k8s.io
listenersets.gateway.networking.k8s.io
referencegrants.gateway.networking.k8s.io
tlsroutes.gateway.networking.k8s.io
3.2 Cài NGINX Gateway Fabric
Sau khi có CRDs, bước tiếp theo là cài Gateway API controller để triển khai lớp định tuyến mới. Trong ví dụ này, dataplane được tách sang cổng khác để tránh xung đột với ingress-nginx hiện tại.
helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
--create-namespace -n nginx-gateway \
--set nginx.service.type=NodePort \
--set nginx.service.externalTrafficPolicy=Cluster \
--set-json 'nginx.service.nodePorts=[{"port":31080,"listenerPort":80},{"port":31443,"listenerPort":443}]'
Kiểm tra controller đã chạy:
kubectl get pods -n nginx-gateway
kubectl get gatewayclass
3.3 Tạo Gateway để controller provision dataplane
Khi controller đã sẵn sàng, cần tạo một Gateway làm điểm tiếp nhận traffic mới để các Route attach vào ở các bước sau.
Tạo namespace riêng cho Gateway:
kubectl create namespace edge-gateway
Tạo file gateway.yaml:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: web-gw
namespace: edge-gateway
spec:
gatewayClassName: nginx
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: All
3.4 Cấu hình máy load balancer để mở đường test mới
Khi dataplane mới đã sẵn sàng, cần mở một hướng truy cập để bắt đầu test thực tế. Trong ví dụ này, tầng load balancer được cấu hình theo hướng ưu tiên Gateway API và fallback về Ingress cũ.
Ví dụ cấu hình:
upstream ingress_old {
server 192.168.196.11:30080;
server 192.168.196.12:30080;
server 192.168.196.13:30080;
}
upstream gwapi_new {
server 192.168.196.11:31080;
server 192.168.196.12:31080;
server 192.168.196.13:31080;
}
server {
listen 80;
location / {
# Thử gửi vào Gateway API mới trước
proxy_pass http://gwapi_new;
# Bật tính năng đánh chặn lỗi
proxy_intercept_errors on;
recursive_error_pages on;
# Nếu Gateway API báo 404 (không tìm thấy Route), đẩy sang Ingress cũ
error_page 404 = @fallback_to_ingress;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location @fallback_to_ingress {
proxy_pass http://ingress_old;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Kiểm tra và reload:
sudo nginx -t
sudo systemctl reload nginx
4. Triển khai ứng dụng
Khi lớp Gateway API đã sẵn sàng, bước tiếp theo là đưa ứng dụng vào mô hình routing mới với phạm vi kiểm soát được. Mục tiêu ở đây là tạo một điểm thử nghiệm đủ rõ để quan sát cách traffic được phân phối giữa luồng cũ và luồng mới trước khi rollout ở bước sau.
4.1 Triển khai Workload
Triển khai hai phiên bản workload để phục vụ cho stable/canary trong giai đoạn migration.
# --- V1 (Stable - 2 Replicas) ---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: game-2048
name: deployment-2048-v1
spec:
replicas: 2
selector:
matchLabels:
app.kubernetes.io/name: app-2048
version: v1
template:
metadata:
labels:
app.kubernetes.io/name: app-2048
version: v1
spec:
containers:
- name: app-2048
image: public.ecr.aws/l6m2t8p7/docker-2048:latest
ports:
- containerPort: 80
---
# --- V2 (Canary - 1 Replica) ---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: game-2048
name: deployment-2048-v2
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: app-2048
version: v2
template:
metadata:
labels:
app.kubernetes.io/name: app-2048
version: v2
spec:
containers:
- name: app-2048
image: public.ecr.aws/l6m2t8p7/docker-2048:latest
ports:
- containerPort: 80
4.2 Cấu hình Backend Services (Multi-Service Mapping)
# Service dành cho Gateway API
apiVersion: v1
kind: Service
metadata:
namespace: game-2048
name: svc-v1
spec:
selector: { app.kubernetes.io/name: app-2048, version: v1 }
ports: [{ port: 80, targetPort: 80 }]
---
apiVersion: v1
kind: Service
metadata:
namespace: game-2048
name: svc-v2
spec:
selector: { app.kubernetes.io/name: app-2048, version: v2 }
ports: [{ port: 80, targetPort: 80 }]
---
# Service giữ nguyên cho Ingress cũ
apiVersion: v1
kind: Service
metadata:
namespace: game-2048
name: service-2048
spec:
selector: { app.kubernetes.io/name: app-2048 }
ports: [{ port: 80, targetPort: 80 }]
Cấu hình Ingress NGINX cũ
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: game-2048
name: ingress-2048
spec:
ingressClassName: nginx
rules:
- host: game-2048.sample.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service-2048
port:
number: 80
4.3 Tạo HTTPRoute cho application
Tại bước này, logic routing mới được khai báo trên Gateway API. Trong ví dụ dưới đây, request nội bộ được tách riêng bằng header, còn traffic mặc định được chia theo tỉ lệ giữa bản ổn định và bản thử nghiệm.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: game-api-route
namespace: game-2048
spec:
parentRefs: [{ name: web-gw, namespace: edge-gateway }]
hostnames: ["new-game-2048.sample.com"]
rules:
- matches: # Ưu tiên Test nội bộ
- headers: [{ name: "X-Environment", value: "staging" }]
backendRefs: [{ name: svc-v2, port: 80 }]
- matches: # Weighted canary (90/10)
- path: { type: PathPrefix, value: / }
backendRefs:
- { name: svc-v1, port: 80, weight: 90 }
- { name: svc-v2, port: 80, weight: 10 }

5. Rollout và Kiểm tra kết quả
Sau khi route mới đã sẵn sàng, bước tiếp theo là migration traffic từng phần để kiểm tra tính đúng đắn và độ ổn định trước khi mở rộng phạm vi rollout.
5.1 Kích hoạt Canary (10% Traffic)
Bắt đầu với một tỉ lệ nhỏ traffic để kiểm tra bản mới (10%), nhưng vẫn giữ phần lớn lưu lượng ở bản ổn định.
# Cập nhật v1 xuống 90% và v2 lên 10%
kubectl patch httproute game-api-route -n game-2048 --type='json' -p='[
{"op": "replace", "path": "/spec/rules/1/backendRefs/0/weight", "value": 90},
{"op": "replace", "path": "/spec/rules/1/backendRefs/1/weight", "value": 10}
]'
Kiểm tra bằng vòng lặp curl để quan sát tỉ lệ phân phối traffic:
for i in {1..20}; do
curl -s -H "Host: new-game-2048.sample.com" http://192.168.196.10 | \
grep -q "CANARY V2" && echo "V2 (Canary)" || echo "V1 (Stable)"
done | sort | uniq -c
5.2 Tăng dần tỉ lệ traffic
Khi các kiểm tra ở Bước 5.2 cho kết quả tốt, chúng ta tiến hành tăng dần lưu lượng.
Bước 1: tăng tỉ lệ lên 50/50
kubectl patch httproute game-api-route -n game-2048 --type='json' -p='[
{"op": "replace", "path": "/spec/rules/1/backendRefs/0/weight", "value": 50},
{"op": "replace", "path": "/spec/rules/1/backendRefs/1/weight", "value": 50}
]'
Bước 2: chuyển hoàn toàn 100% sang v2
kubectl patch httproute game-api-route -n game-2048 --type='json' -p='[
{"op": "replace", "path": "/spec/rules/1/backendRefs/0/weight", "value": 0},
{"op": "replace", "path": "/spec/rules/1/backendRefs/1/weight", "value": 100}
]'
Khi hoàn tất bước này, toàn bộ request sẽ được chuyển qua Gateway API.
curl -I -H "Host: new-game-2048.sample.com" http://192.168.196.10
6. Observability
Sau khi lưu lượng đã được dịch chuyển thành công ở Bước 5, chúng ta duy trì trạng thái giám sát để đảm bảo hệ thống vận hành ổn định về lâu dài.
6.1 Performance Baseline
Ở giai đoạn này, cần so sánh hạ tầng mới với baseline cũ để đánh giá mức độ ổn định sau migration. Một số chỉ số nên tiếp tục theo dõi gồm:
- Response Time: Bản v2 chạy qua Gateway API có phản hồi nhanh hơn hoặc tương đương bản v1 chạy qua Ingress cũ không?
- Tỉ lệ Fallback: Theo dõi log NGINX Load Balancer để đảm bảo không còn request nào tới tên miền đã migrate bị nhảy sang
@fallback_to_ingress(do lỗi 404 từ Gateway API). - Error Rate: Có phát sinh lỗi 4xx/5xx âm thầm trong log của NGINX Gateway Fabric hay không?
6.2 Giám sát lưu lượng Upstream
Kiểm tra logs của Gateway Controller để xác nhận các request đang được forward chính xác đến IP của các Pod thuộc phiên bản mới.
kubectl logs -n nginx-gateway -l app.kubernetes.io/name=nginx-gateway-fabric -c nginx --tail=100
6.3 Health Check
Một quy trình rollout thành công cần được xác nhận qua 3 chỉ số:
- Success Rate: Tỉ lệ mã trạng thái 2xx đạt ngưỡng 100%.
- Latency: Thời gian phản hồi trên cổng 8080 (Gateway API) tương đương hoặc tốt hơn cổng 80 (Ingress cũ).
- Resource Usage: Các Pod v2 không gặp tình trạng quá tải CPU/RAM sau khi nhận 100% traffic.
6.4 Cleanup
Khi hệ thống mới đã vận hành ổn định trong một khoảng thời gian, có thể bắt đầu gỡ bỏ dần các thành phần cũ để đơn giản hóa lại luồng traffic.
- Gỡ bỏ Ingress cũ: nếu ứng dụng đã hoàn tất migration
- Tối ưu Load Balancer: để bỏ cơ chế fallback không còn cần thiết
Mục tiêu của bước này không chỉ là dọn cấu hình, mà là xác nhận rằng Gateway API đã thực sự trở thành đường đi chính thức của ứng dụng.
Kết luận
Có thể nói đây là một trong những migration đáng chú ý nhất với các đội đang vận hành Kubernetes ở lớp edge traffic. Không chỉ vì ingress-nginx controller đã hết vòng đời, mà còn vì Gateway API đang mở ra một mô hình rõ ràng hơn cho routing, policy và multi-team operations. Chuyển đổi theo từng bước, chạy song song và đo lại toàn bộ baseline sẽ là cách thực tế nhất để đi từ Ingress NGINX sang kiến trúc mới mà không tự tăng rủi ro cho production.









