
인그레스 운영 사례 분석: 왜 도입이 필요했을까요
마이크로서비스 아키텍처(MSA)로 전환하면서 가장 먼저 마주한 벽은 네트워크 관리였어요. 처음에는 단순히 서비스 하나를 외부에 노출하는 게 문제라고 생각했어요. 하지만 서비스가 10개, 20개로 늘어나면서 상황은 완전히 달라졌어요. 각 서비스마다 LoadBalancer 타입을 사용하여 외부 IP를 할당받기 시작하니 클라우드 비용이 기하급수적으로 치솟았어요.
단순히 비용 문제만 있었던 건 아니에요. 관리 포인트가 너무 많아졌어요. 새로운 API를 출시할 때마다 클라우드 콘솔에 접속해 로드밸런서를 생성하고, DNS 설정을 변경하고, 방화벽 규칙을 하나하나 확인해야 했어요. 인프라 엔지니어링 팀의 업무 부하가 임계점에 도달했고, 배포 속도는 눈에 띄게 느려졌어요. 서비스 간의 라우팅 규칙을 관리하는 일은 마치 거미줄처럼 엉켜버렸어요.
이런 혼란을 잠재우기 위해 선택한 것이 바로 인그레스(Ingress)였어요. 하나의 진입점을 만들고, 그 안에서 규칙에 따라 트래픽을 분산해 주는 구조를 꿈꿨어요. 이 글에서는 실제 운영 환경에서 인그레스를 도입하며 겪었던 구체적인 과정과, 설정 과정에서 만났던 예상치 못한 문제들, 그리고 최종적으로 얻어낸 운영 효율성을 가감 없이 공유할게요.
인그레스는 단순한 로드밸런서가 아니에요. 쿠버네티스 클러스터 외부에서 내부 서비스로 HTTP/HTTPS 트래픽을 전달하는 규칙 집합이며, 이를 실제로 구현하는 엔진이 인그레스 컨트롤러예요.
오늘 다룰 핵심 내용은 다음과 같아요.
- 기존 노드포트와 로드밸런서 방식의 한계점
- 인그레스 컨트롤러 선정과 초기 설정 과정
- 실제 YAML 설정 예시와 경로 기반 라우팅 구현
- 운영 중 마주한 트러블슈팅과 최적화 팁
사전 준비: 인그레스 도입 전 꼭 알아야 할 것들
인그레스를 무턱대고 설치한다고 해서 모든 문제가 해결되지는 않아요. 어떤 컨트롤러를 쓸 것인지, 우리 서비스의 트래픽 패턴은 어떠한지를 먼저 파악해야 해요. 준비 없이 도입했다가는 오히려 설정의 복잡함 때문에 운영 난이도만 올라가는 낭패를 볼 수 있어요.
서비스 노출 방식의 차이점 이해하기
가장 먼저 현재 우리가 사용하는 노출 방식의 특징을 명확히 구분해야 해요. 클라우드 환경에서는 보통 세 가지 방식을 고민하게 돼요. 각각의 장단점이 뚜렷해서 우리 조직의 상황에 맞는 선택이 필요해요.
| 비교 항목 | NodePort | LoadBalancer | Ingress |
|---|---|---|---|
| 비용 효율성 | 매우 높음 | 매우 낮음 (서비스당 발생) | 매우 높음 (단일 LB 사용) |
| 관리 편의성 | 낮음 (포트 관리 어려움) | 보통 | 매우 높음 (규칙 기반) |
| 보안/TLS 지원 | 수동 설정 필요 | 클라우드 종속적 | 매우 유연함 (Annotation 활용) |
| 추천 상황 | 테스트 환경 | 단일 서비스 노출 | MSA/다수 서비스 운영 |
위 표에서 알 수 있듯이, 서비스 개수가 늘어날수록 인그레스의 비용 효율성은 압도적이에요. 하지만 인그레스는 별도의 컨트롤러를 관리해야 한다는 운영 부담이 따르기 때문에, 우리 팀이 이를 관리할 역량이 있는지를 먼저 자문해봐야 해요.
선택을 위한 체크리스트
도입을 결정했다면 다음 세 가지 질문에 답을 내릴 수 있어야 해요. 이 답변이 준비되지 않으면 도입 직후부터 운영 이슈가 터져 나올 거예요.
- 트래픽의 종류: 대부분 HTTP/HTTPS 트래픽인가요? 아니면 TCP/UDP 기반의 특수 프로토콜이 필요한가요? 인그레스는 기본적으로 L7 계층의 동작에 최적화되어 있어요.
- 컨트롤러 선정 기준: 오픈소스인 Nginx Ingress Controller를 사용할 것인가요, 아니면 AWS ALB 컨트롤러처럼 클라우드 네이티브한 방식을 사용할 것인가요? Nginx는 커스터마이징이 강력하지만 직접 관리해야 할 요소가 많고, 클라우드 방식은 관리는 편하지만 세밀한 설정에 제약이 있어요.
- 보안 정책: SSL/TLS 인증서를 어떻게 관리할 것인가요? Cert-manager 같은 도구를 함께 도입할 준비가 되었나요?
인그레스 컨트롤러 자체가 단일 장애 지점(SPOF)이 될 수 있어요. 컨트롤러가 죽으면 모든 서비스가 중단되므로, 컨트롤러 자체의 고가용성(HA) 구성 계획을 반드시 세워야 해요.
핵심 본문: 인그레스 구축부터 실제 운영까지의 5단계
실제 현장에서 인그레스를 구축하며 거쳤던 단계별 실행 과정을 공유할게요. 이론적인 설명보다는 우리가 어떤 순서로 움직였고, 어떤 설정을 적용했는지에 집중해서 봐주세요.
STEP 1. 인그레스 컨트롤러 설치 및 기본 검증
우리는 가장 범용적인 Nginx Ingress Controller를 선택했어요. Helm 차트를 이용해 클러스터에 설치하는 과정을 거쳤죠. 설치 시 가장 중요한 점은 컨트롤러가 사용할 로드밸런서의 타입을 결정하는 것이었어요. 우리는 클라우드 제공업체의 로드밸런서를 통해 컨트롤러를 외부에 노출하도록 설정했어요.
설치 직후에는 아무런 규칙도 없는 상태예요. 따라서 가장 먼저 테스트용 Pod와 Service를 띄우고, 인그레스 리소스를 생성해서 실제로 트래픽이 잘 흘러가는지 확인하는 과정이 필요해요. 이때 kubectl logs 명령어를 통해 컨트롤러의 로그를 실시간으로 모니터링하는 습관을 들여야 해요. 설정 오류가 발생하면 로그에 아주 명확한 이유가 찍히거든요.
STEP 2. 경로 및 호스트 기반 라우팅 설정
이제 본격적으로 서비스를 나누는 단계예요. 우리는 하나의 도메인(api.example.com) 아래에 경로별로 서비스를 분리하는 방식을 택했어요. 예를 들어, `/users` 경로는 사용자 관리 서비스로, `/orders` 경로는 주문 서비스로 보내는 식이죠.
이때 작성하는 YAML 설정 파일의 구조는 다음과 같아요. 설정 시 주의할 점은 pathType을 정확히 지정하는 것이에요. Prefix와 Exact의 차이를 모르면 엉뚱한 서비스로 트래픽이 전달될 수 있어요.
Prefix 타입은 지정한 경로로 시작하는 모든 요청을 포함하고, Exact 타입은 정확히 그 경로와 일치하는 요청만 매칭해요.
실제 적용한 설정 예시를 살펴볼까요?
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
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
위 설정에서 rewrite-target 어노테이션은 매우 중요해요. 만약 서비스 내부 코드가 `/users`라는 경로를 인식하지 못하고 루트(`/`) 경로 기준으로 동작한다면, 인그레스가 경로를 깎아주는 역할을 해줘야 하기 때문이에요.
STEP 3. TLS 인증서 자동화 적용
보안을 위해 모든 통신은 HTTPS로 이루어져야 해요. 하지만 서비스가 늘어날 때마다 인증서를 수동으로 발급받고 업데이트하는 건 불가능에 가까워요. 그래서 우리는 Cert-manager를 도입했어요. Let’s Encrypt와 연동하여 인증서 발급부터 갱신까지 전 과정을 자동화했죠.
인증서가 적용된 인그레스 리소스는 다음과 같이 구성돼요. secretName 항목에 인증서 정보가 담긴 Secret 이름을 지정해주면, 컨트롤러가 이를 읽어 TLS 핸드셰이크를 수행해요. 이 과정이 자동화되면서 인증서 만료로 인해 서비스가 중단되는 사고를 완벽하게 방지할 수 있었어요.
STEP 4. 카나리(Canary) 배포를 통한 안정적 전환
새로운 버전의 서비스를 배포할 때, 전체 트래픽을 한 번에 돌리는 건 너무 위험해요. 인그레스의 강력한 기능 중 하나는 트래픽의 일부만 새로운 버전으로 보내는 Canary 배포를 지원한다는 점이에요. Nginx Ingress Controller의 어노테이션을 사용하면 아주 쉽게 구현할 수 있어요.
예를 들어, 새로운 버전인 `order-service-v2`로 트래픽의 10%만 보내고 싶다면, 별도의 인그레스 리소스를 만들고 다음과 같이 어노테이션을 추가하면 돼요.
- `nginx.ingress.kubernetes.io/canary: “true”`
- `nginx.ingress.kubernetes.io/canary-weight: “10”`
이 방식을 사용하면 실제 사용자들에게 영향을 최소화하면서 새로운 기능의 안정성을 검증할 수 있어요. 우리는 이 기능을 통해 배포 실패 시에도 즉각적으로 트래픽을 차단하고 이전 버전으로 복구할 수 있었어요.
STEP 5. 모니터링 및 성능 최적화
마지막 단계는 운영 중 발생하는 지표를 관찰하는 것이에요. 인그레스 컨트롤러의 CPU와 메모리 사용량, 그리고 HTTP 응답 코드(2xx, 4xx, 5xx)의 비율을 반드시 모니터링해야 해요. 특히 5xx 에러가 급증한다면 백엔드 서비스의 문제인지, 아니면 인그레스의 타임아웃 설정 문제인지를 빠르게 판단해야 해요.
우리는 Prometheus와 Grafana를 연동하여 인그레스의 요청 처리량(RPS)과 레이턴시(Latency)를 시각화했어요. 이를 통해 특정 시간대에 트래픽이 몰릴 때 컨트롤러의 리소스를 얼마나 늘려야 하는지 데이터에 기반한 의사결정을 내릴 수 있게 되었어요.
[운영 시나리오: 서비스 통합 전환 기록]
과거에는 서비스 5개가 각각 5개의 로드밸런서를 가지고 있었어요. 이로 인해 월 비용이 $200 이상 발생했죠. 인그레스를 도입한 후, 단 하나의 로드밸런서와 인그레스 컨트롤러만 유지하게 되었고, 비용은 $30 수준으로 약 85% 절감되었어요. 또한, 신규 서비스 배포 시 소요되던 인프라 설정 시간이 평균 30분에서 3분 이내로 단축되었어요.
자주 하는 실수와 해결법 + FAQ
인그레스를 운영하다 보면 누구나 한 번쯤은 당황스러운 상황을 마주하게 돼요. 저희 팀이 실제로 겪었던 시행착오를 바탕으로 정리해 보았어요.
자주 하는 실수와 해결법
❌ 실수: 서비스 경로 불일치로 인한 404 에러
왜 발생하는가: 인그레스의 경로(path) 설정과 실제 애플리케이션이 기대하는 경로가 다르기 때문이에요. 예를 들어, 인그레스는 `/api/v1`으로 요청을 받지만, 애플리케이션은 `/v1`부터 시작하는 경우예요.
✅ 해결법: rewrite-target 어노테이션을 사용하여 인그레스 단계에서 경로를 재작성해 주어야 해요.
❌ 실수: 대용량 파일 업로드 시 413 Request Entity Too Large 에러
왜 발생하는가: Nginx Ingress의 기본 클라이언트 본문 크기 제한이 설정되어 있기 때문이에요.
✅ 해결법: nginx.ingress.kubernetes.io/proxy-body-size 어노테이션을 사용하여 허용 용량을 늘려주세요.
❌ 실수: TLS 인증서 갱신 실패로 인한 접속 불가
왜 발생하는가: Cert-manager의 Issuer 설정이 잘못되었거나, DNS-01 챌린지 과정에서 권한 문제가 발생했기 때문이에요.
✅ 해결법: Cert-manager의 로그를 확인하고, Issuer 리소스가 정상적으로 Ready 상태인지 주기적으로 체크해야 해요.
❌ 실수: 헤더 유실 문제 (Host, X-Forwarded-For 등)
왜 발생하는가: 프록시 계층을 거치면서 클라이언트의 원본 정보가 사라지는 현상이에요.
✅ 해결법: 인그레스 컨트롤러 설정에서 use-forwarded-headers 옵션을 활성화해야 해요.
❌ 실수: 타임아웃 설정 미흡으로 인한 504 Gateway Timeout
왜 발생하는가: 백엔드 서비스의 처리 시간이 인그레스의 기본 프록시 타임아웃 설정보다 길기 때문이에요.
✅ 해결법: proxy-read-timeout과 proxy-send-timeout 값을 서비스 특성에 맞춰 적절히 늘려주세요.
자주 묻는 질문
Q. 인그레스와 서비스(Service)의 차이점은 무엇인가요?
서비스는 클러스터 내부의 Pod들에게 트래픽을 전달하는 역할에 집중하고, 인그레스는 외부에서 들어오는 HTTP/HTTPS 요청을 어떤 서비스로 보낼지 결정하는 L7 규칙 역할을 해요. 즉, 인그레스는 서비스를 관리하는 상위 계층의 개념이라고 이해하면 쉬워요.
Q. 인그레스 컨트롤러를 여러 개 사용할 수 있나요?
네, 가능해요. 예를 들어, 일반적인 API 트래픽용 Nginx 컨트롤러와 대용량 미디어 스트리밍용 별도의 컨트롤러를 구분하여 운영할 수 있어요. 각 인그레스 리소스의 ingressClassName을 통해 어떤 컨트롤러가 처리할지 지정하면 돼요.
Q. 보안을 위해 인그레스에서 WAF를 사용할 수 있나요?
당연히 가능해요. 클라우드 제공업체의 WAF를 로드밸런서에 연동하거나, 인그레스 컨트롤러 단계에서 ModSecurity 같은 오픈소스 WAF를 추가하여 보안을 강화할 수 있어요.
Q. 인그레스 설정이 변경될 때마다 서비스가 끊기나요?
설정이 적용되는 찰나의 순간에 아주 미세한 지연이 발생할 수는 있지만, Nginx 컨트롤러는 설정 변경 시 새로운 설정을 로드하고 기존 연결을 유지하는 방식을 사용하기 때문에 일반적으로 서비스 중단은 발생하지 않아요.
Q. 모든 트래픽을 인그레스로 처리하는 게 좋은가요?
HTTP/HTTPS 트래픽은 인그레스가 최적이지만, 게임 서버나 DB 연결 같은 TCP/UDP 기반의 트래픽은 인그레스보다는 LoadBalancer 타입을 직접 사용하는 것이 성능과 관리 면에서 훨씬 유리해요.
성공적인 인그레스 운영을 위한 마지막 정리
인그레스 도입은 단순히 기술적인 변경을 넘어, 인프라 운영 비용을 절감하고 배포의 유연성을 확보하는 중요한 전환점이었어요. 처음에는 복잡한 설정과 예상치 못한 에러 때문에 고생도 많았지만, 결과적으로 우리 팀은 훨씬 안정적이고 효율적인 환경을 갖추게 되었어요.
- 서비스가 늘어날수록 LoadBalancer보다 인그레스가 훨씬 경제적이에요.
- 경로(Path) 설정 시 Prefix와 Exact의 차이를 반드시 구분하세요.
- Cert-manager를 활용해 SSL 인증서 관리를 자동화하는 것을 강력히 추천해요.
- 카나리 배포 기능을 통해 배포 리스크를 최소화할 수 있어요.
- 트래픽 패턴에 맞춰 타임아웃과 바디 사이즈 설정을 최적화해야 해요.
- 인그레스 컨트롤러 자체의 고가용성(HA) 확보는 필수예요.
인그레스를 성공적으로 도입하기 위해 오늘 바로 실천할 수 있는 단계들을 제안할게요.
- 오늘 할 일: 현재 우리 클러스터에서 서비스별로 생성된 LoadBalancer 개수를 파악하고 예상 절감 비용을 계산해 보세요.
- 이번 주 할 일: 개발 환경에 Nginx Ingress Controller를 설치하고, 간단한 경로 기반 라우팅 테스트를 진행해 보세요.
- 실행 직전 할 일: Cert-manager를 설치하여 테스트용 도메인에 인증서가 자동으로 발급되는지 검증해 보세요.
인그레스 설정 중에 막히는 부분이 있거나, 실제 운영 환경에서 해결하기 어려운 특수한 케이스를 만났다면 주저하지 말고 댓글로 질문을 남겨 주세요. 함께 고민하면 답을 찾을 수 있을 거예요. 실습 환경에서 직접 부딪히며 익히는 것이 가장 빠른 학습 방법이라는 점을 잊지 마세요!
관련하여 더 깊이 있는 내용이 궁금하다면 아래 글들도 함께 읽어보시는 것을 추천해요.
🔗 쿠버네티스 인그레스 기본 개념 및 동작 원리 정리
🔗 안정적인 쿠버네티스 클러스터 구축 입문 가이드