쿠버네티스 환경에서 외부 트래픽을 관리하는 Ingress의 개념과 동작 원리를 실습과 함께 알아봅니다.
쿠버네티스를 공부하다 보면 이런 의문이 생깁니다.
"URL 기반 라우팅은 Nginx로 할 수 있는 건데, Ingress는 왜 필요한 거지?"
결론부터 말하면: Ingress는 Nginx를 쿠버네티스 방식으로 자동 관리하는 도구입니다.
전통적인 서버 환경에서는 Nginx를 다음과 같이 설정합니다:
# /etc/nginx/nginx.conf
server {
listen 80;
server_name myapp.com;
location / {
proxy_pass http://192.168.1.10:3000; # Frontend 서버
}
location /api {
proxy_pass http://192.168.1.11:8080; # Backend 서버
}
}
특징:
쿠버네티스에서는 상황이 다릅니다:
# 오늘의 Pod IP
$ kubectl get pods -o wide
NAME IP
frontend-aaa 10.244.1.5
backend-bbb 10.244.2.8
# Pod 재시작 후
$ kubectl get pods -o wide
NAME IP
frontend-ccc 10.244.1.9 ← IP 변경!
backend-ddd 10.244.2.3 ← IP 변경!
문제점:
현재 일반적으로 사용하는 NodePort 방식:
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
type: NodePort
ports:
- port: 80
nodePort: 30080 # 30000-32767 범위
접속:
http://xxx.xxx.xxx.xxx:30080 # Frontend
http://xxx.xxx.xxx.xxx:30081 # Backend
문제점:
1. Ingress Resource (규칙)
# YAML로 작성하는 라우팅 규칙
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
spec:
rules:
- host: myapp.com
http:
paths:
- path: /
backend:
service:
name: frontend-service # ← Service 이름만!
port:
number: 80
- path: /api
backend:
service:
name: backend-service
port:
number: 8080
2. Ingress Controller (구현체)
전통적인 방식 (수동):
1. nginx.conf 파일 직접 편집
2. IP 주소 하드코딩
3. 변경 사항 있으면 수동으로 수정
4. nginx -s reload 실행
Ingress 방식 (자동):
1. Ingress YAML 작성 (Service 이름만 명시)
2. kubectl apply
3. Ingress Controller가 자동으로:
- Service의 Pod IP 추적
- Nginx 설정 생성
- 변경 사항 자동 반영
┌─────────────────────────────────────────┐
│ Ingress Controller Pod │
│ │
│ ┌───────────────────────────────────┐ │
│ │ Nginx (실제 프록시 서버) │ │
│ │ - 요청 받기 │ │
│ │ - 라우팅 │ │
│ └───────────────────────────────────┘ │
│ ↑ │
│ ┌───────────────────────────────────┐ │
│ │ Controller (자동화 로직) │ │
│ │ - Ingress 규칙 watch │ │
│ │ - Service Endpoints 추적 │ │
│ │ - Nginx 설정 자동 생성/업데이트 │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────┘
Scenario: Backend Pod 재시작
# 1. 초기 상태
$ kubectl get pods -o wide
NAME IP
backend-aaa 10.244.1.5
backend-bbb 10.244.2.8
# Ingress Controller 내부 Nginx 설정 (자동 생성됨)
upstream backend-service {
server 10.244.1.5:8080;
server 10.244.2.8:8080;
}
# 2. Backend Pod 하나 재시작
$ kubectl delete pod backend-aaa
# 3. 새 Pod 생성 (IP 변경!)
$ kubectl get pods -o wide
NAME IP
backend-ccc 10.244.1.12 ← 새 IP!
backend-bbb 10.244.2.8
Ingress Controller가 자동으로:
1. Service의 Endpoints 변경 감지
2. Nginx 설정 자동 업데이트
upstream backend-service {
server 10.244.1.12:8080; # ← 자동 업데이트!
server 10.244.2.8:8080;
}
→ 우리는 아무것도 안 해도 됨!
아키텍처:
사용자
↓
http://xxx.xxx.xxx.xxx:30080 (Frontend)
http://xxx.xxx.xxx.xxx:30081 (Backend)
↓
NodePort Service
↓
Pod (IP 계속 변경)
문제:
설치:
# Ingress Controller 설치 (Nginx 기반)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/baremetal/deploy.yaml
# 설치 확인
kubectl get pods -n ingress-nginx
# NAME READY
# ingress-nginx-controller-xxxxx-xxxxx 1/1
Ingress 규칙 작성:
# ingress-rules.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
spec:
ingressClassName: nginx
rules:
- host: myapp.local # 또는 실제 도메인
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 8080
적용:
kubectl apply -f ingress-rules.yaml
# 확인
kubectl get ingress
# NAME HOSTS ADDRESS PORTS
# myapp-ingress myapp.local xxx.xxx.xxx.xxx 80
최종 아키텍처:
사용자
↓
http://myapp.local/ (Frontend)
http://myapp.local/api (Backend)
↓
Ingress Controller (Nginx Pod)
├─ / → Frontend Service
└─ /api → Backend Service
↓
Frontend/Backend Pods
| 항목 | NodePort | Ingress |
|---|---|---|
| URL | http://IP:30080 | http://myapp.com/ |
| 포트 | 여러 개 필요 | 80/443만 |
| 도메인 | 어려움 | 쉬움 |
| SSL | 서비스별 설정 | 한 곳에서 설정 |
| 라우팅 | Service마다 포트 | 경로로 구분 |
# Ingress Controller Pod 찾기
INGRESS_POD=$(kubectl get pods -n ingress-nginx -l app.kubernetes.io/component=controller -o jsonpath='{.items[0].metadata.name}')
# Nginx 설정 파일 확인
kubectl exec -n ingress-nginx $INGRESS_POD -- cat /etc/nginx/nginx.conf
출력 예시 (일부):
# 자동 생성된 설정!
upstream default-backend-service-8080 {
# Service Endpoints 자동 추적
server 10.244.1.12:8080 max_fails=0 fail_timeout=0;
server 10.244.2.8:8080 max_fails=0 fail_timeout=0;
}
server {
listen 80;
server_name myapp.local;
location /api {
proxy_pass http://default-backend-service-8080;
# ... 기타 설정
}
}
→ 결국 Nginx 설정이지만, 자동으로 생성/관리됨!
# Backend를 3개로 스케일업
kubectl scale deployment backend --replicas=3
# 잠시 후 Nginx 설정 다시 확인
kubectl exec -n ingress-nginx $INGRESS_POD -- cat /etc/nginx/nginx.conf | grep "server 10.244"
출력:
server 10.244.1.12:8080; # 기존
server 10.244.2.8:8080; # 기존
server 10.244.1.15:8080; # ← 자동으로 추가됨!
많은 사람들이 헷갈려하는 부분:
# frontend deployment
containers:
- name: nginx
image: nginx:alpine
# HTML 파일 서빙
# /api 요청을 Backend로 프록시
역할:
kubectl get pods -n ingress-nginx
# ingress-nginx-controller-xxxxx
역할:
인터넷
↓
Ingress Controller (Nginx #1)
├─ myapp.com/ → Frontend Service
│ ↓
│ Frontend Pod
│ ↓
│ Nginx #2 (HTML 서빙)
│
└─ myapp.com/api → Backend Service
↓
Backend Pod
비유:
Ingress Controller = 공항 입구 안내 데스크
"어느 게이트로 가실까요?"
Frontend Pod Nginx = 탑승구 직원
"탑승권 확인하고 좌석 안내해드릴게요"
✅ 자동화
✅ 통합 관리
✅ 쿠버네티스 네이티브
✅ 고급 기능
❌ 초기 복잡도
❌ 디버깅
❌ 리소스
도메인이 없어도 테스트 가능:
# /etc/hosts (Linux/Mac) 또는 C:\Windows\System32\drivers\etc\hosts (Windows)
xxx.xxx.xxx.xxx myapp.local
이제 브라우저에서:
http://myapp.local/
http://myapp.local/api
# Ingress 상태 확인
kubectl describe ingress myapp-ingress
# Ingress Controller 로그
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller
# Endpoints 확인 (Service가 올바른 Pod를 가리키는지)
kubectl get endpoints
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- myapp.com
secretName: myapp-tls
rules:
- host: myapp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
Ingress는 Nginx를 쿠버네티스 방식으로 관리하는 도구
왜 필요한가?
어떻게 동작하나?
언제 사용하나?
| 관점 | 수동 Nginx | Ingress |
|---|---|---|
| 설정 | nginx.conf 직접 편집 | YAML 선언 |
| IP 관리 | 수동 | 자동 |
| 업데이트 | 수동 reload | 자동 |
| 환경 | 정적 서버 | 동적 쿠버네티스 |
| 러닝 커브 | 낮음 | 중간 |
| 운영 효율 | 낮음 | 높음 |