AKS Application Routing Add-on의 관리형 NGINX는 2026년 11월까지만 중요 보안 패치를 받고, Upstream ingress-nginx는 2026년 3월에 유지보수가 끝났습니다. Microsoft가 권장하는 이전 경로는 같은 Add-on의 Gateway API 구현(approuting-istio)으로, Ingress를 Gateway와 HTTPRoute로 바꾸고 두 경로를 나란히 띄운 뒤 DNS만 바꿔 전환합니다. WAF가 필요하다면 클러스터 밖에서 동작하는 Application Gateway for Containers도 선택지입니다.
1. 지금 옮겨야 하는 이유
AKS에서 많이 쓰던 Ingress는 Application Routing Add-on이 관리해 주는 NGINX였습니다(Azure Kubernetes Service 구성 정리). 이 NGINX의 바탕인 Upstream ingress-nginx 프로젝트가 은퇴하면서, AKS도 관리형 NGINX 지원 종료 일정을 발표했습니다. 지원이 끝난 뒤에는 보안 취약점이 나와도 패치를 받을 수 없으므로 그 전에 이전을 마쳐야 합니다.
| 시점 | 내용 |
| 2025년 11월 | Kubernetes SIG Network가 Ingress NGINX 프로젝트 은퇴 발표 |
| 2026년 3월 | Upstream ingress-nginx 유지보수 종료 |
| 2026년 4월 | Application Routing의 Gateway API 구현(approuting-istio) GA |
| AKS 1.36 | 새 AKS Automatic 클러스터의 기본 Ingress가 Gateway API 구현으로 바뀜 |
| 2026년 11월 | Application Routing 관리형 NGINX의 중요 보안 패치 지원 종료 |
2. Gateway API 구조

GatewayClass, Gateway, HTTPRoute가 역할별로 나뉘고, Load Balancer로 들어온 요청이 Gateway를 거쳐 HTTPRoute 규칙대로 Service에 전달되는 구성
Gateway API는 Ingress 다음 세대의 Kubernetes 표준 트래픽 API입니다. Ingress는 리소스 하나에 호스트, 경로, TLS를 모두 적고 리다이렉트나 Rewrite 같은 기능은 컨트롤러마다 다른 어노테이션으로 넣었습니다. Gateway API는 이를 역할별 리소스로 나누고, 자주 쓰는 기능을 표준 필드로 정의했습니다.
| 항목 | Ingress | Gateway API |
| 리소스 | Ingress 하나에 규칙과 TLS를 모두 적음 | GatewayClass, Gateway, HTTPRoute로 나뉨 |
| 고급 기능 | 컨트롤러별 어노테이션 (nginx.ingress.kubernetes.io/...) |
표준 필드(filters, weight, redirect) |
| 권한 분리 | 한 리소스라 나누기 어려움 | 플랫폼 팀은 Gateway, 앱 팀은 HTTPRoute 관리 |
| 프로토콜 | HTTP, HTTPS | HTTP, HTTPS, gRPC 등(구현마다 다름) |
| 이식성 | 어노테이션이 컨트롤러에 묶임 | 구현을 바꿔도 리소스 대부분을 그대로 사용 |
approuting-istio에서 Gateway를 만들면 aks-istio-system Namespace의 Control Plane이 Envoy 프록시 Deployment와 LoadBalancer Service를 자동으로 만듭니다. 프록시에는 HPA(Horizontal Pod Autoscaler, 2~5개)와 PDB(PodDisruptionBudget, 최소 1개 유지)가 함께 붙습니다. Service Mesh 전체가 아니라 Ingress에 필요한 Istio만 가볍게 올리는 방식이라 Sidecar는 주입되지 않습니다.
3. AKS에서 고를 수 있는 선택지
| 방식 | 동작 위치 · API | 특징 | 용도 |
| Application Routing Gateway API 구현 |
클러스터 안 Envoy 프록시 Gateway API |
AKS Add-on, 관리형 업그레이드, Ingress 전용 | 대부분의 NGINX 이전 (Microsoft 권장 경로) |
| Application Gateway for Containers |
클러스터 밖(Azure 관리) Gateway API, Ingress |
WAF, mTLS(상호 TLS 인증), 트래픽 분할, 헤더·URL Rewrite |
WAF가 필요하거나 Ingress를 클러스터 밖으로 뺄 때 |
| Istio Service Mesh Add-on |
클러스터 안 Istio Gateway API, Istio API |
Sidecar, 서비스 간 mTLS, 트래픽 관리 | Service Mesh까지 필요할 때 |
| 직접 설치한 ingress-nginx |
클러스터 안 Ingress |
Upstream 유지보수 종료 | 권장하지 않음 |
Application Gateway for Containers는 기존 Application Gateway(Application Gateway 정리)와 별개인 Kubernetes 전용 서비스로, 클러스터 안의 ALB Controller가 Kubernetes 설정을 Azure 쪽 구성으로 옮겨 줍니다. Application Routing의 Gateway API 구현과 Istio Service Mesh Add-on은 한 클러스터에서 함께 켤 수 없습니다. 이 글은 가장 많이 쓰일 Application Routing Gateway API 구현을 기준으로 설명합니다.
4. 이전 절차

ingress-nginx와 Gateway가 각자 IP를 받아 나란히 동작하고, DNS 레코드만 바꿔 트래픽을 옮기는 구성
두 경로는 서로 다른 Load Balancer IP를 쓰기 때문에, 새 Gateway를 먼저 띄워 검증하고 DNS만 바꾸면 전환됩니다. 문제가 생기면 DNS를 되돌리는 것으로 롤백합니다.
4.1 현재 상태 확인과 DNS TTL 낮추기
RG=rg-aks
AKS=aks-demo
# 어떤 IngressClass와 Ingress를 쓰는지 확인
kubectl get ingressclass
kubectl get ingress -A
Application Routing NGINX의 IngressClass는 webapprouting.kubernetes.azure.com입니다. 전환 하루 전에는 도메인의 DNS TTL(캐시 유지 시간)을 60초 정도로 낮춰 두어야 레코드를 바꿨을 때 빨리 반영됩니다.
4.2 Gateway API 구현 켜기
# Gateway API CRD와 구현 켜기(Azure CLI 2.86.0 이상)
az aks update --resource-group $RG --name $AKS \
--enable-gateway-api --enable-app-routing-istio
kubectl get gatewayclass
kubectl get pods -n aks-istio-system
Gateway API CRD(Custom Resource Definition, 사용자 정의 리소스)는 AKS가 관리하는 것만 지원합니다. 직접 설치한 CRD가 있다면 먼저 정리합니다. gatewayclass 목록에 approuting-istio가 보이면 준비가 끝난 것입니다.
4.3 Ingress를 Gateway와 HTTPRoute로 바꾸기
예시로 app.example.com의 /는 web 서비스로, /api는 api 서비스로 보내고 HTTP를 HTTPS로 리다이렉트하는 Ingress를 옮깁니다.
# 이전 전: NGINX Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: webapprouting.kubernetes.azure.com
tls:
- hosts: ["app.example.com"]
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service: {name: api, port: {number: 8080}}
- path: /
pathType: Prefix
backend:
service: {name: web, port: {number: 80}}
# 이전 후: Gateway + HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: web-gateway
spec:
gatewayClassName: approuting-istio
listeners:
- name: http
port: 80
protocol: HTTP
- name: https
port: 443
protocol: HTTPS
hostname: app.example.com
tls:
mode: Terminate
certificateRefs:
- name: app-tls
---
# ssl-redirect 대신: HTTP 요청을 HTTPS로 리다이렉트
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web-redirect
spec:
parentRefs:
- name: web-gateway
sectionName: http
hostnames: ["app.example.com"]
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web
spec:
parentRefs:
- name: web-gateway
sectionName: https
hostnames: ["app.example.com"]
rules:
- matches:
- path: {type: PathPrefix, value: /api}
backendRefs:
- name: api
port: 8080
- matches:
- path: {type: PathPrefix, value: /}
backendRefs:
- name: web
port: 80
Ingress가 많다면 Kubernetes SIG Network의 ingress2gateway로 초안을 만들고 검토하는 편이 빠릅니다. 변환 결과의 gatewayClassName은 approuting-istio로 바꾸고, 지원하지 않는 어노테이션이 빠지지 않았는지 확인합니다.
# ingress2gateway v1.0.0: go install 또는 brew install ingress2gateway
ingress2gateway print --providers=ingress-nginx -A \
--ingress-nginx-ingress-class=webapprouting.kubernetes.azure.com > gateway.yaml
4.4 전환 전에 새 경로 검증
kubectl apply -f gateway.yaml
kubectl get gateway web-gateway
GW_IP=$(kubectl get gateway web-gateway -o jsonpath='{.status.addresses[0].value}')
# DNS를 바꾸기 전에 새 IP로 직접 요청해 확인
curl -I -H "Host: app.example.com" http://$GW_IP/
curl --resolve app.example.com:443:$GW_IP https://app.example.com/api
첫 요청은 301 리다이렉트, 두 번째 요청은 api 서비스의 응답이 오면 됩니다. 이 단계까지는 사용자 트래픽이 계속 ingress-nginx로 가므로 서비스에 영향이 없습니다.
4.5 DNS 전환과 정리
DNS A 레코드를 GW_IP로 바꿉니다. Azure Front Door Origin(Azure Front Door 정리), Traffic Manager 엔드포인트, 외부 방화벽 허용 목록처럼 기존 NGINX IP를 직접 적어 둔 곳도 함께 바꿉니다. ingress-nginx로 가는 트래픽이 줄어드는 것을 확인하고, 몇 시간 지켜본 뒤 TTL을 원래 값으로 돌립니다.
# 트래픽이 모두 넘어온 뒤 NGINX 정리
az aks approuting update --resource-group $RG --name $AKS --nginx None
kubectl delete nginxingresscontrollers.approuting.kubernetes.azure.com --all
kubectl delete ingress web
5. 어노테이션 옮기기
| NGINX Ingress | Gateway API |
| pathType: Prefix / Exact | path.type: PathPrefix / Exact |
| spec.tls, secretName | Gateway의 HTTPS listener와 certificateRefs |
| ssl-redirect, force-ssl-redirect | HTTP listener에 붙인 HTTPRoute의 RequestRedirect 필터 |
| rewrite-target | URLRewrite 필터(ReplacePrefixMatch) |
| canary, canary-weight | backendRefs의 weight |
| 요청·응답 헤더 추가 | RequestHeaderModifier, ResponseHeaderModifier 필터 |
| proxy-body-size, limit-rps, configuration-snippet |
Application Routing Gateway API 구현에서는 대응 기능 없음 |
요청 본문 크기 제한, Rate Limiting, 스니펫처럼 NGINX 설정을 직접 넣던 기능은 Gateway API 표준에 없고, 이 구현에서는 EnvoyFilter도 막혀 있습니다. 이런 기능에 의존한다면 앱으로 옮기거나 앞단의 WAF 규칙(Front Door의 Rate Limit 규칙 등)으로 대신하고, 그래도 부족하면 필요한 기능을 지원하는 다른 구현을 검토합니다.
6. 운영 시 주의점
| 항목 | 조치 |
| Gateway API 구현이 켜지지 않음 | Istio Service Mesh Add-on과는 함께 쓸 수 없습니다. 직접 설치한 Gateway API CRD도 지원하지 않으므로 정리한 뒤 관리형 CRD를 켭니다. |
| HTTPS listener가 Ready가 아님 | certificateRefs의 Secret이 Gateway와 같은 Namespace에 있는지 확인합니다. 다른 Namespace라면 ReferenceGrant가 필요합니다. |
| HTTPRoute가 붙지 않음 | parentRefs의 이름과 sectionName, hostnames가 Gateway listener와 맞는지, allowedRoutes가 HTTPRoute의 Namespace를 허용하는지 확인합니다. |
| 전환 뒤 일부 사용자가 예전 IP로 접속 | DNS TTL을 미리 낮추지 않았거나, Front Door·방화벽에 예전 IP가 남아 있는 경우입니다. |
| 큰 파일 업로드, Rate Limit | NGINX 어노테이션으로 하던 설정은 옮겨지지 않습니다. 앞단이나 다른 구현으로 대신합니다. |
| 노드 자원 | Gateway마다 프록시가 2~5개 뜨고 PDB가 있으므로, Node Pool에 여유를 두고 업그레이드 시 drain이 막히지 않게 합니다. |
7. 정리
- Application Routing 관리형 NGINX는 2026년 11월에 지원이 끝나므로, 같은 Add-on의 Gateway API 구현(approuting-istio)으로 옮깁니다.
- Ingress를 Gateway와 HTTPRoute로 바꾸고 새 IP로 검증한 뒤, DNS TTL을 낮춘 상태에서 레코드만 바꿔 전환하고 NGINX를 정리합니다.
- 본문 크기 제한, Rate Limit, 스니펫 같은 NGINX 전용 설정은 옮겨지지 않으므로, 전환 전에 앱이나 앞단 WAF로 대신할 방법을 정해 둡니다.
참고
'Cloud > Azure' 카테고리의 다른 글
| [Azure] Azure Firewall 구성 정리 (0) | 2026.09.25 |
|---|---|
| [Azure] Microsoft Foundry 구성 정리 (0) | 2026.09.25 |
| [Azure] Azure NAT Gateway 정리 (0) | 2026.09.25 |
| [Azure] Azure Kubernetes Service 구성 정리 (0) | 2026.09.25 |
| [Azure] Private DNS Zone과 DNS Private Resolver 정리 (0) | 2026.09.25 |