
쿠버네티스의 기본 네트워크 리소스인 Service를 배우고 나니
"외부 접속이 필요하면 그냥 Service를 type: LoadBalancer로 설정해서 띄우면 끝 아닌가?"
이런 생각이 들었다.
컨테이너가 몇 개 없는 단일 프로젝트라면 그 말대로 LoadBalancer 타입의 서비스 하나만 띄워도 아무런 문제가 없다.
하지만 서비스 규모가 커져 사용자(user), 상품(item), 주문(order), 결제(pay) 등 마이크로서비스 파드가 20개로 늘어나는 순간, Service 단독 구성은 곧바로 두 가지 치명적인 한계에 부딪힌다.
type: LoadBalancer를 선언하면, AWS에 L4 로드밸런서인 NLB가 20개 생성된다. 로드밸런서 기본 유지비만으로도 매달 막대한 클라우드 비용이 청구된다.Service는 오직 IP와 포트 번호(L4)만 볼 줄 안다. 따라서 하나의 도메인(api.shop.com)으로 들어온 요청을 /orders는 주문 파드로, /pay는 결제 파드로 나누어 보내는 HTTP URL 경로 기반 라우팅을 처리할 수 없다.결국 우리는 "바깥에는 로드밸런서를 딱 1개만 세워 비용을 아끼고, 도메인과 URL 경로를 분석해 내부의 20개 서비스(ClusterIP)로 길을 나눠주는 똑똑한 L7 안내데스크"가 필요하다.
이 한계를 해결하기 위해 등장한 것이 바로 Ingress이며, 여기서부터 Ingress-Nginx, Gateway API, 그리고 Istio로 이어지는 쿠버네티스 네트워킹의 확장이 시작된다.
쿠버네티스의 YAML 파일은 그저 '종이 주문서'일 뿐이다.
kind: Ingress라는 주문서를 작성했을 때, 이를 실제로 구현하는 방식은 현업에서 크게 2가지 아키텍처로 나뉜다. 여기서 ALB만 쓰는 구조와 NLB + Ingress-Nginx를 함께 쓰는 구조의 차이가 발생한다.
[방식 A : AWS ALB 단독 사용]
외부 유저 ──▶ [AWS ALB (L7, 여기서 경로 분기 끝)] ──▶ [Service (ClusterIP)] ──▶ [Pod]
[방식 B : AWS NLB + Ingress-Nginx 조합]
외부 유저 ──▶ [AWS NLB (L4, 단순 통과)] ──▶ [Ingress-Nginx 파드 (L7, 클러스터 안에서 경로 분기)] ──▶ [Service (ClusterIP)] ──▶ [Pod]
클러스터 외부의 AWS ALB에게 안내데스크(L7 경로 분기) 역할을 통째로 맡기는 방식이다.
Ingress YAML을 배포하면 AWS에 ALB가 딱 1개 생성된다. (이 구조에서는 NLB를 아예 쓰지 않는다.)target-type: ip 설정을 통해 노드를 거치지 않고 파드 IP로 직결 라우팅할 수 있다.apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop-alb-ingress
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip # 파드 IP로 직결
alb.ingress.kubernetes.io/group.name: shared-alb # 여러 Ingress를 단 1개의 ALB로 통합
spec:
ingressClassName: alb
rules:
- host: api.shop.com
http:
paths:
- path: /orders
pathType: Prefix
backend:
service:
name: order-svc # 뒤쪽의 ClusterIP 서비스와 연결
port:
number: 80
AWS의 ALB를 쓰지 않고, 쿠버네티스 클러스터 내부에 직접 Nginx 웹서버 파드(Ingress-Nginx)를 띄워서 안내데스크 역할을 시키는 방식이다.
Ingress-Nginx 파드를 외부와 연결해 줘야 하므로, 그 앞단에 단순 문지기 역할인 AWS NLB(type: LoadBalancer)를 딱 1개만 세운다.Ingress-Nginx 파드(L7)에 도착하면, 이 Nginx 파드가 Ingress YAML 규칙을 읽고 /orders는 order-svc로, /pay는 pay-svc로 토스해 준다.Ingress 덕분에 로드밸런서 비용도 아끼고 경로 분기도 해결했다. 그런데 서비스 규모가 커지면서 Ingress 자체에 두 가지 심각한 구조적 한계가 드러났다.
Ingress 문법에는 SSL 설정, 타임아웃, 카나리 배포 같은 기능이 아예 없다. 그래서 위 YAML처럼 annotations: 밑에 AWS 전용 주석이나 Nginx 전용 주석을 20~30줄씩 덕지덕지 붙여야만 했다./orders 같은 API 경로를 추가하는 백엔드 개발자가 똑같은 Ingress YAML 파일 하나를 같이 수정해야 한다. 개발자가 경로를 고치다가 실수로 SSL 인증서 설정을 지워버리면 전체 서비스 장애가 발생한다.이 문제를 근본적으로 해결하기 위해 쿠버네티스가 새롭게 내놓은 공식 차세대 표준이 바로 Gateway API다.
[인프라 엔지니어 담당] ──▶ Gateway (로드밸런서 생성, 443 포트 개방, TLS 인증서 장착)
│
│ (연결)
▼
[백엔드 개발자 담당] ──▶ HTTPRoute ("/orders" 경로 매핑, 90:10 카나리 배포 설정)
Gateway만 관리한다인프라 팀은 로드밸런서의 물리적 설정과 보안만 정의해 두고 권한(RBAC)을 잠근다.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: prod-gateway
namespace: infra-system
spec:
gatewayClassName: aws-alb-class
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: shop-tls-cert
HTTPRoute만 관리한다개발자는 인프라 설정(Gateway)을 건드릴 필요 없이, 본인의 네임스페이스에서 경로와 카나리 배포(가중치 분할)만 안전하게 선언한다. 어노테이션 없이 표준 문법(weight)만으로 트래픽을 90:10으로 쪼갤 수 있다.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: order-route
namespace: order-team
spec:
parentRefs:
- name: prod-gateway
namespace: infra-system
hostnames:
- "api.shop.com"
rules:
- matches:
- path:
type: PathPrefix
value: /orders
backendRefs:
- name: order-svc-v1
port: 80
weight: 90 # 기존 버전에 90% 트래픽 할당
- name: order-svc-v2
port: 80
weight: 10 # 신규 버전에 10% 트래픽 할당 (Canary 배포)
지금까지 다룬 Ingress, Ingress-Nginx, Gateway API는 모두 한 가지 공통점이 있다.
바로 "클러스터 바깥에서 안으로 들어오는 입구 트래픽(North-South Traffic)"만 관리한다는 점이다.
그런데 현업에서 마이크로서비스(MSA)가 50개, 100개로 늘어나면 진짜 문제는 입구를 통과한 그 이후, 즉 클러스터 내부에서 파드들끼리 서로 통신할 때(East-West Traffic) 터진다.
주문 파드 -> 결제 파드 -> 포인트 파드 -> 알림 파드로 연쇄 호출이 일어날 때, 만약 포인트 파드 하나가 느려지면 앞단의 모든 파드가 줄줄이 멈춰버리는 연쇄 장애가 발생한다.Service(ClusterIP)에는 그런 기능이 없다.이 "클러스터 내부 파드 간의 통신 제어와 보안"을 해결하기 위해 등장한 기술이 바로 Istio (서비스 메시, Service Mesh)다.
[일반 구조]
[주문 컨테이너] ────────────────(맨몸 통신)────────────────▶ [결제 컨테이너]
[Istio 적용 구조 (사이드카 패턴)]
[주문 파드: 주문 컨테이너 + Envoy 프록시] ──(mTLS 암호화 / 서킷 브레이커)──▶ [결제 파드: Envoy 프록시 + 결제 컨테이너]
Istio를 도입하면, 모든 비즈니스 파드가 뜰 때마다 그 파드 안에 Envoy라는 초소형 네트워크 대리인(사이드카 컨테이너)이 1개씩 자동으로 함께 장착된다.Envoy 대리인을 통해서만 대화를 주고받는다.Istio IngressGateway): 외부 트래픽을 받아들이는 고성능 관문 역할(Ingress 대체)을 수행한다.Gateway API를 그대로 채택해 통합되고 있다.)쿠버네티스 네트워크 기술들의 관계와 선택 기준을 한 표로 정리하면 다음과 같다.
| 기술 명칭 | 담당하는 구간 | 핵심 역할 및 선택해야 하는 순간 |
|---|---|---|
Service (ClusterIP) | 클러스터 내부 기본 연결 | 모든 구조의 필수 부품. 변하는 파드들을 묶어 고정 IP와 도메인(CoreDNS)을 부여할 때 |
Ingress (AWS ALB) | 외부 -> 내부 입구 (L7) | AWS 환경에서 가장 간편하게 단일 ALB로 도메인/경로 분기와 WAF/SSL을 연동하고 싶을 때 |
Ingress-Nginx (NLB + Nginx) | 외부 -> 내부 입구 (L7) | 클라우드 종속성을 피하고, 앞단에 NLB 1개만 둔 채 내부 Nginx 파드로 세밀한 L7 제어를 하고 싶을 때 |
| Gateway API | 외부 -> 내부 입구 (차세대 표준) | 기존 Ingress의 어노테이션 남발을 없애고, 인프라팀(Gateway)과 개발팀(HTTPRoute)의 권한을 분리 및 카나리 배포를 표준화할 때 |
Istio (Service Mesh) | 입구 + 내부 파드 간 통신 전체 | 입구 라우팅을 넘어, 내부 파드끼리의 mTLS 보안 암호화, 서킷 브레이커(장애 격리), 세밀한 트래픽 제어까지 필요한 대규모 MSA 환경일 때 |
결국 이 기술들은 서로 동떨어진 것이 아니라, "단일 진입점 확보(Service) -> 입구 L7 라우팅 통합(Ingress / Ingress-Nginx) -> 역할 분리 및 표준화(Gateway API) -> 내부 동서 트래픽 제어(Istio)"라는 명확한 한계 극복을 위해 단계별로 발전해 온 하나의 흐름이다.
이상.