Ingress 심화 — 외부 트래픽을 클러스터 내부로 라우팅하는 방법
외부 사용자의 HTTPS 요청이 Kubernetes 클러스터 내부의 올바른 서비스에 도달하기까지 어떤 과정을 거칠까요?
Service의 LoadBalancer 타입으로도 외부 트래픽을 받을 수 있지만, 서비스마다 별도의 로드밸런서가 생성되어 비용이 증가합니다. Ingress는 하나의 진입점으로 호스트와 경로 기반 라우팅을 제공해서 이 문제를 해결합니다.
Ingress의 구성 요소
Ingress 시스템은 두 가지로 구성됩니다.
- Ingress 리소스: 라우팅 규칙을 정의하는 Kubernetes 오브젝트
- Ingress Controller: 규칙을 실제로 실행하는 소프트웨어 (별도 설치 필요)
클라이언트 → 로드밸런서 → Ingress Controller (Pod) → Service → Pod
Ingress 리소스만 만들면 아무 일도 일어나지 않습니다. Controller가 있어야 규칙이 적용됩니다.
기본 Ingress 설정
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx # 사용할 Ingress Controller 지정
rules:
- host: api.example.com
http:
paths:
- path: /users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
- path: /orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 80
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 80
이 설정은 다음과 같이 동작합니다.
api.example.com/users/*→ user-serviceapi.example.com/orders/*→ order-serviceadmin.example.com/*→ admin-service
pathType 옵션
| 타입 | 설명 | /api 규칙에 매칭되는 경로 |
|---|---|---|
Exact | 정확한 매칭 | /api만 |
Prefix | 접두사 매칭 | /api, /api/v1, /api/users |
ImplementationSpecific | Controller 구현에 따름 | Controller마다 다름 |
주요 Ingress Controller 비교
Nginx Ingress Controller
가장 널리 사용되며 안정적입니다.
# 설치 (Helm)
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace
# Nginx 관련 어노테이션
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m" # 업로드 크기 제한
nginx.ingress.kubernetes.io/proxy-read-timeout: "60" # 읽기 타임아웃
nginx.ingress.kubernetes.io/ssl-redirect: "true" # HTTP → HTTPS 리다이렉트
nginx.ingress.kubernetes.io/rate-limit: "10" # Rate Limiting
nginx.ingress.kubernetes.io/cors-allow-origin: "*" # CORS 설정
Traefik
자동 서비스 디스커버리와 Let's Encrypt 자동 인증서가 강점입니다.
# 설치 (Helm)
helm install traefik traefik/traefik \
--namespace traefik \
--create-namespace
AWS ALB Ingress Controller
AWS 환경에서 ALB(Application Load Balancer)를 직접 생성합니다.
metadata:
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:...
TLS 종료
Ingress Controller에서 HTTPS를 처리하고 내부에는 HTTP로 전달합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
spec:
tls:
- hosts:
- api.example.com
secretName: tls-secret # TLS 인증서를 저장한 Secret
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
# TLS Secret 생성
kubectl create secret tls tls-secret \
--cert=tls.crt \
--key=tls.key
cert-manager를 이용한 자동 인증서 관리
cert-manager를 사용하면 Let's Encrypt 인증서를 자동으로 발급하고 갱신합니다.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auto-tls-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- api.example.com
secretName: auto-tls-secret # cert-manager가 자동 생성
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
Default Backend
어떤 규칙에도 매칭되지 않는 요청을 처리합니다.
spec:
defaultBackend:
service:
name: default-service
port:
number: 80
rules:
# ... 생략
Gateway API — Ingress의 진화
Gateway API는 Ingress의 한계를 해결하기 위해 설계된 차세대 API입니다.
Ingress의 한계
- HTTP/HTTPS만 지원 (TCP/UDP 불가)
- 세밀한 트래픽 제어가 어려움 (어노테이션 남용)
- Controller마다 비표준 어노테이션 사용
Gateway API의 구조
GatewayClass → Gateway → HTTPRoute / TCPRoute / GRPCRoute
(인프라팀) (클러스터관리자) (개발팀)
# Gateway 정의 (클러스터 관리자)
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: main-gateway
spec:
gatewayClassName: nginx
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: tls-secret
---
# HTTPRoute 정의 (개발팀)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-route
spec:
parentRefs:
- name: main-gateway
hostnames:
- api.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /api/v1
backendRefs:
- name: api-v1-service
port: 80
weight: 90
- name: api-v2-service
port: 80
weight: 10 # 10% 트래픽을 v2로 (카나리)
Gateway API의 핵심 장점은 역할별 관심사 분리와 표준화된 트래픽 분할입니다.
실무에서 주의할 점
- Ingress Controller 리소스: Controller 자체도 Pod이므로 충분한 리소스와 replicas를 확보하세요
- 어노테이션 문서 확인: Controller마다 어노테이션이 다르므로 공식 문서를 반드시 확인하세요
- Health Check 경로: 백엔드 서비스의 헬스체크 경로가 올바른지 확인하세요
- 로그 확인: 라우팅 문제 시 Controller의 로그를 먼저 확인하세요
# Ingress Controller 로그 확인
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller
# Ingress 리소스 상태 확인
kubectl describe ingress app-ingress
정리
Ingress는 하나의 진입점으로 호스트/경로 기반 라우팅과 TLS 종료를 제공합니다. Ingress 리소스(규칙)와 Ingress Controller(실행)의 분리를 이해하는 것이 핵심이며, cert-manager를 활용하면 인증서 관리도 자동화할 수 있습니다. 더 세밀한 트래픽 제어가 필요하면 Gateway API로의 전환을 고려해 보세요.