본문으로 건너뛰기

Ingress에서 Gateway API로 마이그레이션

기존 인그레스(Ingress) 리소스를 Gateway API로 전환하는 방법을 안내합니다. Ingress와 Gateway API의 개념 비교는 Gateway API 배포 > Ingress와 Gateway API 비교를 참고해 주세요.

안내

본 가이드는 커뮤니티 NGINX Ingress Controller(kubernetes/ingress-nginx)의 프로젝트 퇴역(retirement)(2026년 3월 유지보수 종료)에 따라 Gateway API로 전환하는 방법을 안내합니다. 기존 Ingress 환경이 즉시 중단되는 것은 아니지만, 유지보수가 종료되면 보안 패치와 버그 수정이 제공되지 않으므로 향후 전환을 검토해야 합니다.

이 가이드는 NGINX Gateway Fabric을 예시로 설명합니다. Envoy, Istio, Cilium 등 다른 Gateway API 구현체를 선택할 수도 있으며, 구현체에 따라 배포 방법과 설정이 다를 수 있으므로 선택한 프로젝트의 공식 문서를 함께 참고하세요.

마이그레이션 전 주의사항

본 문서는 마이그레이션을 위한 참고용 가이드입니다. 전환 과정에서 서비스 중단이나 트래픽 유실이 발생할 수 있으므로, 반드시 스테이징 환경에서 충분히 검증한 후 운영 환경에 적용하세요.

사전 작업

실제 마이그레이션을 수행하기 전에 다음 사전 작업을 완료합니다.

마이그레이션 전 확인 사항

  • 기존 Ingress 리소스의 커스텀 어노테이션은 Gateway API와 1:1로 대응되지 않습니다. 사용 중인 어노테이션을 확인하고, 선택한 Gateway API 컨트롤러의 공식 문서를 참고하여 개별적으로 변환합니다. 예를 들어 rewrite-target, proxy-body-size, ssl-redirect 등의 어노테이션은 별도 검토가 필요합니다.
  • Kubernetes 1.34 이상 클러스터에서는 Konnectivity를 통해 API 서버와 Admission Webhook 서버가 통신하므로 Admission Webhook 서버 파드에 hostNetwork: true 설정이 필요하지 않습니다. Kubernetes 1.32 및 1.33 클러스터에서는 사용하는 Gateway API 컨트롤러에 Admission Webhook 서버가 포함된 경우 해당 파드에 hostNetwork: true 설정이 필요합니다.
  • Kubernetes Engine에서 Gateway를 통해 생성되는 로드 밸런서는 기본적으로 프라이빗 IP를 할당받습니다. 외부 통신을 위한 퍼블릭 IP가 필요하면 로드 밸런서 생성 및 삭제 > 부록. 로드 밸런서 상세 옵션 설정하기를 참고하여 별도의 로드 밸런서 어노테이션을 설정합니다.

1. 기존 Ingress 설정 백업

마이그레이션 전에 기존 Ingress 리소스를 백업합니다.

모든 네임스페이스의 Ingress 리소스 백업
kubectl --kubeconfig=$KUBE_CONFIG get ingress -A -o yaml > ingress-backup.yaml

2. Gateway API CRD 설치

설치 방법은 Gateway API 배포 > 사전 작업을 참고해 주세요.

Gateway API CRD 설치 확인
kubectl --kubeconfig=$KUBE_CONFIG get crd | grep gateway

3. Gateway API 컨트롤러 배포

NGINX Gateway Fabric 기준 배포 방법은 Gateway API 배포 > Step 1. Gateway API 컨트롤러 배포를 참고해 주세요. 다른 구현체를 사용하는 경우, 해당 컨트롤러의 공식 문서를 참고하여 배포합니다.

Gateway API 컨트롤러 배포 확인
kubectl --kubeconfig=$KUBE_CONFIG get pods -n nginx-gateway

4. Gateway 리소스 생성

생성 방법은 Gateway API 배포 > Step 3. Gateway 리소스 생성을 참고해 주세요.

Gateway 리소스 확인
kubectl --kubeconfig=$KUBE_CONFIG get gateway -n nginx-gateway
실행 결과
NAME            CLASS   ADDRESS                                                                 PROGRAMMED   AGE
nginx-gateway nginx k8s-nginxga-nginxga-xxxxxxxxxx-xxxxxx.ke.kr-central-2.kakaocloud.com True 3m

Ingress 리소스를 변환하는 방법은 자동 변환과 직접 변환으로 나뉩니다. 두 방법 중 하나를 선택합니다.

Step 1. Ingress 리소스 변환

자동 변환

Kubernetes SIG-Network에서 제공하는 ingress2gateway 도구를 사용하면, 기존 Ingress 리소스를 Gateway API 리소스(Gateway + HTTPRoute)로 자동 변환할 수 있습니다.

ingress2gateway 설치

Ingress 리소스를 변환하기 전에 ingress2gateway를 설치합니다.

Go를 사용하여 설치
go install github.com/kubernetes-sigs/ingress2gateway@latest

클러스터에서 직접 변환

현재 클러스터에 배포된 Ingress 리소스를 읽어 Gateway API 리소스로 변환합니다.

클러스터의 Ingress 리소스 변환
ingress2gateway print --kubeconfig=$KUBE_CONFIG --providers=ingress-nginx --all-namespaces
실행 결과
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: nginx
namespace: demo-apps
spec:
gatewayClassName: nginx
listeners:
- name: http
port: 80
protocol: HTTP
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: path-routing-all-hosts
namespace: demo-apps
spec:
parentRefs:
- name: nginx
rules:
- backendRefs:
- name: app-v1
port: 80
matches:
- path:
type: PathPrefix
value: /api
- backendRefs:
- name: app-v2
port: 80
matches:
- path:
type: PathPrefix
value: /web

파일 기반 변환

클러스터에 접속하지 않고, Ingress YAML 파일을 직접 변환할 수도 있습니다.

Ingress YAML 파일을 변환
ingress2gateway print --providers=ingress-nginx --input-file=ingress-backup.yaml
변환 결과를 파일로 저장
ingress2gateway print --providers=ingress-nginx --input-file=ingress-backup.yaml > gateway-api-resources.yaml
주의

ingress2gateway는 호스트, 경로, 백엔드, TLS 같은 핵심 Ingress 필드를 변환하며, ingress-nginx에서 자주 사용하는 일부 어노테이션도 함께 변환할 수 있습니다.

다만 모든 어노테이션과 구현체별 확장 설정이 1:1로 자동 변환되는 것은 아니므로, 자동 생성된 결과물의 gatewayClassName, namespace, hostnames, filters, backendRefs를 반드시 검토해 주시기 바랍니다.

직접 변환 및 필드 매핑

자동 변환 도구를 사용하지 않고 직접 변환하는 경우, 아래 Before/After 예제를 참고해 주세요. 아래 예제들은 Gateway 리소스가 이미 생성되어 있다고 가정합니다.

예제 1. 경로 기반 라우팅

경로 기반 라우팅 설정을 Ingress와 Gateway API 형식으로 비교합니다.

Before — Ingress

ingress-path.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-routing
namespace: demo-apps
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: app-v1
port:
number: 80
- path: /web
pathType: Prefix
backend:
service:
name: app-v2
port:
number: 80

After — HTTPRoute

httproute-path.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: path-routing
namespace: demo-apps
spec:
parentRefs:
- name: nginx-gateway
namespace: nginx-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: app-v1
port: 80
- matches:
- path:
type: PathPrefix
value: /web
backendRefs:
- name: app-v2
port: 80

주요 변경점:

  • ingressClassNameparentRefs로 Gateway를 직접 참조
  • spec.rules[].http.pathsspec.rules[].matches[].path
  • backend.service.name / port.numberbackendRefs[].name / port

예제 2. 호스트 기반 라우팅

호스트 기반 라우팅 설정을 Ingress와 Gateway API 형식으로 비교합니다.

Before — Ingress

ingress-host.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: host-routing
namespace: demo-apps
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 80
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-svc
port:
number: 80

After — HTTPRoute

httproute-host.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-route
namespace: demo-apps
spec:
parentRefs:
- name: nginx-gateway
namespace: nginx-gateway
hostnames:
- api.example.com
rules:
- backendRefs:
- name: api-svc
port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web-route
namespace: demo-apps
spec:
parentRefs:
- name: nginx-gateway
namespace: nginx-gateway
hostnames:
- web.example.com
rules:
- backendRefs:
- name: web-svc
port: 80

주요 변경점:

  • spec.rules[].host → HTTPRoute spec.hostnames
  • 호스트별로 별도의 HTTPRoute를 생성하여 독립적으로 관리 가능 (하나의 HTTPRoute에 여러 hostnames를 정의하는 것도 가능)

예제 3. TLS 종료

TLS 종료 설정을 Ingress와 Gateway API 형식으로 비교합니다.

Before — Ingress

ingress-tls.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
namespace: demo-apps
spec:
ingressClassName: nginx
tls:
- hosts:
- secure.example.com
secretName: tls-secret
rules:
- host: secure.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: secure-svc
port:
number: 80

After — Gateway + HTTPRoute

Gateway API에서는 TLS 설정이 Gateway 리소스의 리스너에 정의됩니다. HTTPRoute는 라우팅 규칙만 담당합니다.

gateway-tls.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: nginx-gateway
namespace: nginx-gateway
spec:
gatewayClassName: nginx
listeners:
- name: https
port: 443
protocol: HTTPS
hostname: secure.example.com
tls:
mode: Terminate
certificateRefs:
- name: tls-secret
allowedRoutes:
namespaces:
from: All
httproute-tls.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: secure-route
namespace: demo-apps
spec:
parentRefs:
- name: nginx-gateway
namespace: nginx-gateway
sectionName: https
hostnames:
- secure.example.com
rules:
- backendRefs:
- name: secure-svc
port: 80

주요 변경점:

  • Ingress spec.tls → Gateway listeners[].tls에서 TLS 종료 설정
  • TLS 인증서(Secret)는 Gateway가 관리하며, HTTPRoute는 라우팅만 정의
  • parentRefs.sectionName으로 특정 리스너를 참조

Step 2. 마이그레이션 수행

기존 Ingress 리소스를 Gateway API로 전환합니다. 병렬 운영 → 검증 → 전환 순서로 안전하게 진행합니다.

1. HTTPRoute 리소스 생성

자동 변환의 결과 또는 직접 변환 및 필드 매핑의 예제를 참고하여, 기존 Ingress 리소스에 대응하는 HTTPRoute를 생성합니다.

HTTPRoute 리소스 적용
kubectl --kubeconfig=$KUBE_CONFIG apply -f httproute-path.yaml
HTTPRoute 생성 확인
kubectl --kubeconfig=$KUBE_CONFIG get httproute -n demo-apps

2. 병렬 운영

기존 Ingress와 새 HTTPRoute를 동시에 운영하여, 트래픽이 양쪽 모두에서 정상적으로 처리되는지 확인합니다.

안내

Ingress Controller와 Gateway API Controller는 각각 별도의 로드 밸런서를 생성하므로 서로 간섭 없이 동시에 운영할 수 있습니다. 단, 기존 Ingress에서 사용하던 로드 밸런서의 IP 주소를 Gateway API 측에서 그대로 사용할 수는 없습니다. 새로운 로드 밸런서 주소가 할당되므로, DNS 레코드를 새 주소로 변경하여 트래픽을 전환해 주시기 바랍니다.

기존 Ingress 로드 밸런서 주소 확인
kubectl --kubeconfig=$KUBE_CONFIG get ingress -n demo-apps
새 Gateway 로드 밸런서 주소 확인
kubectl --kubeconfig=$KUBE_CONFIG get gateway -n nginx-gateway -o jsonpath='{.items[0].status.addresses[0].value}'

3. 트래픽 전환 및 기존 Ingress 삭제

Gateway API 측에서 트래픽이 정상적으로 처리되는 것을 확인한 후, DNS를 Gateway의 로드 밸런서 주소로 전환하고 기존 Ingress 리소스를 삭제합니다.

기존 Ingress 리소스 삭제
kubectl --kubeconfig=$KUBE_CONFIG delete ingress path-routing -n demo-apps
주의

Ingress 리소스를 삭제하면 해당 Ingress Controller의 로드 밸런서를 통한 트래픽이 중단됩니다. 반드시 Gateway API를 통한 트래픽이 정상적으로 동작하는 것을 확인한 후에 삭제하시기 바랍니다.

4. 롤백 방안

마이그레이션 후 문제가 발생하는 경우, 사전 작업에서 백업해 둔 Ingress 리소스를 복원하여 원래 상태로 되돌릴 수 있습니다.

백업한 Ingress 리소스 복원
kubectl --kubeconfig=$KUBE_CONFIG apply -f ingress-backup.yaml
문제가 된 HTTPRoute 리소스 삭제
kubectl --kubeconfig=$KUBE_CONFIG delete httproute path-routing -n demo-apps

DNS를 원래 Ingress 로드 밸런서 주소로 되돌려 주시기 바랍니다.

안내

롤백 가능성을 고려하여, 기존 Ingress Controller는 Gateway API를 통한 트래픽이 충분히 안정화될 때까지 삭제하지 않고 유지하는 것을 권장합니다.

Step 3. 마이그레이션 확인

마이그레이션이 완료된 후, 다음 항목을 확인하여 정상 동작을 검증합니다.

1. Gateway 및 HTTPRoute 상태 확인

Gateway에 ADDRESS가 할당되어 있고 PROGRAMMED: True인지, HTTPRoute가 Accepted: True인지 확인합니다.

Gateway 상태 확인
kubectl --kubeconfig=$KUBE_CONFIG get gateway -n nginx-gateway
HTTPRoute 상세 상태 확인
kubectl --kubeconfig=$KUBE_CONFIG describe httproute path-routing -n demo-apps
정상 상태의 Conditions
Status:
Parents:
Conditions:
Message: The route is accepted
Reason: Accepted
Status: True
Type: Accepted
Message: All references are resolved
Reason: ResolvedRefs
Status: True
Type: ResolvedRefs

2. 라우팅 동작 검증

Gateway의 ADDRESS를 통해 라우팅이 정상적으로 동작하는지 확인합니다.

Gateway ADDRESS 조회
export GW_ADDRESS=$(kubectl --kubeconfig=$KUBE_CONFIG get gateway nginx-gateway -n nginx-gateway -o jsonpath='{.status.addresses[0].value}')
echo $GW_ADDRESS
경로 기반 라우팅 확인
curl -v http://$GW_ADDRESS/api
curl -v http://$GW_ADDRESS/web
호스트 기반 라우팅 확인
curl -v http://$GW_ADDRESS/ -H "Host: api.example.com"
curl -v http://$GW_ADDRESS/ -H "Host: web.example.com"
TLS 라우팅 확인
curl -v https://$GW_ADDRESS/ -H "Host: secure.example.com" --insecure

각 요청이 올바른 백엔드 서비스로 라우팅되면 마이그레이션이 성공적으로 완료된 것입니다.

안내