Network & Server Factory

개인 공부 기록

Cloud/Azure

[Azure] AKS Ingress Gateway API 이전 정리

1nfra 2026. 9. 25. 18:47
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로 대신할 방법을 정해 둡니다.

참고

728x90
서울
--:--:--
-전체 글
-카테고리
오늘 방문