
인그레스 운영 사례 분석: 왜 인그레스가 필요할까요?
마이크로서비스 아키텍처(MSA)를 운영하다 보면 누구나 한 번쯤 마주하는 벽이 있어요. 서비스가 5개일 때는 괜찮았는데, 어느덧 20개, 30개가 넘어가면서 관리가 불가능해지는 시점이 오거든요. 특히 각 서비스마다 별도의 LoadBalancer를 생성해서 외부로 노출하고 있다면, 매달 청구되는 클라우드 비용 고지서를 보며 뒷목을 잡게 될지도 몰라요.
저희 팀도 비슷한 상황을 겪었어요. 서비스가 늘어날수록 외부로 노출되는 IP 주소와 포트 번호가 기하급수적으로 증가했고, 보안 설정도 제각각이라 관리가 너무 어려웠죠. “이걸 어떻게 하면 하나의 통로로 깔끔하게 관리할 수 있을까?”라는 고민 끝에 내린 결론이 바로 인그레스(Ingress) 도입이었어요.
단순히 기술을 도입하는 것보다 중요한 건, 실제 운영 환경에서 어떤 문제가 발생하고 이를 어떻게 해결하느냐 하는 점이에요. 설정 하나 잘못했다가 전체 서비스에 접속이 안 되는 아찔한 순간도 있었고, SSL 인증서 갱신 문제로 밤을 지새운 적도 있었거든요. 이 글은 이론적인 설명이 아니라, 제가 현장에서 직접 몸으로 부딪치며 얻은 인그레스 운영 사례를 바탕으로 작성했어요.
이 글을 끝까지 읽으시면 다음과 같은 내용을 얻어 가실 수 있어요.
- 기존 서비스 노출 방식의 문제점과 인그레스 도입의 필요성
- 실제 환경에서 적용한 인그레스 설정 방식과 구성 요소
- 도입 후 비용 절감과 관리 효율성 변화
- 운영 중 마주한 트러블슈팅 사례와 해결 방법
이제 복잡했던 네트워크 경로를 어떻게 단순화했는지, 그 생생한 과정을 함께 살펴볼게요.
사전 준비: 인그레스 도입 전 반드시 알아야 할 것들
인그레스를 도입하기로 마음먹었다면, 무턱대고 설정 파일부터 작성해서는 안 돼요. 우리가 해결하려는 문제가 무엇인지, 그리고 현재 클러스터 환경이 인그레스를 받아들일 준비가 되었는지 먼저 점검해야 합니다. 인그레스는 단순히 규칙을 정의하는 ‘설정 파일’일 뿐이고, 실제로 그 규칙을 해석해서 트래픽을 전달해 줄 인그레스 컨트롤러(Ingress Controller)가 반드시 필요하기 때문이에요.
먼저, 우리 서비스에 어떤 방식이 가장 적합할지 결정해야 해요. 흔히 사용하는 세 가지 노출 방식을 비교해 드릴게요. 이 표를 보고 현재 우리 팀의 상황에 맞는 전략을 세워보세요.
| 방식 | 특징 | 장점 | 단점 |
|---|---|---|---|
| NodePort | 모든 노드의 특정 포트를 개방 | 설정이 매우 간단함 | 포트 관리 어려움, 보안 취약 |
| LoadBalancer | 클라우드 제공 L4 로드밸런서 사용 | 안정적이고 사용이 편리함 | 서비스당 비용 발생 (매우 비쌈) |
| Ingress | L7 계층의 경로 기반 라우팅 | 비용 절감, 도메인 기반 관리 가능 | 컨트롤러 설치 및 관리 필요 |
저희는 비용 절감과 도메인 통합 관리를 위해 인그레스 방식을 선택했어요. 하지만 선택 전에 체크해야 할 목록이 몇 가지 더 있습니다.
인그레스 컨트롤러로 가장 많이 쓰이는 것은 Nginx Ingress Controller예요. 설정이 유연하고 커뮤니티가 매우 커서 실무에서 가장 선호됩니다. 클라우드 네이티브한 환경이라면 AWS ALB를 사용하는 방식도 고려해 볼 수 있어요.
체크리스트를 정리해 드릴게요. 이 항목들이 준비되었다면 다음 단계인 실제 구축으로 넘어갈 수 있어요.
- 도메인 관리 권한: 인그레스의 IP로 DNS를 연결할 수 있는 권한이 있나요?
- 컨트롤러 설치 방식 결정: Helm을 사용할 것인가, 매니페스트 파일을 직접 적용할 것인가?
- SSL/TLS 인증서 확보 계획: Let’s Encrypt 같은 자동화 도구를 쓸 것인가, 기존 인증서를 수동으로 등록할 것인가?
- 네트워크 보안 정책: 인그레스 컨트롤러를 통해서만 트래픽이 들어오도록 보안 그룹을 설정했나요?
준비가 끝났다면, 이제 실제 운영 환경에서 인그레스를 어떻게 구성하고 적용했는지 그 디테일한 과정을 살펴보겠습니다.
인그레스 적용기: 실무 환경 구축과 최적화 과정
인그레스 도입은 단순한 설정 변경이 아니라, 서비스로 들어오는 입구를 완전히 재설계하는 과정이었어요. 저희는 기존에 각 마이크로서비스마다 붙어있던 수십 개의 LoadBalancer를 제거하고, 단 하나의 입구를 만드는 것을 목표로 삼았습니다. 이 과정은 크게 6단계로 나누어 진행했어요.
STEP 1. 기존 서비스 구조 분석 및 아키텍처 설계
가장 먼저 한 일은 현재 운영 중인 서비스들의 도메인과 경로(Path)를 전수 조사하는 것이었어요. 어떤 서비스는 api.example.com처럼 서브도메인을 쓰고 있고, 어떤 서비스는 example.com/user처럼 경로를 기준으로 나누어져 있었거든요. 이 체계를 정리하지 않고 인그레스를 적용했다가는 트래픽이 엉뚱한 곳으로 흐르는 대참사가 발생할 수 있어요.
저희는 호스트 기반(Host-based) 라우팅과 경로 기반(Path-based) 라우팅을 혼합하여 설계했습니다. 메인 웹 서비스는 도메인 자체로, API 서버들은 서브도메인으로, 그리고 정적 파일들은 특정 경로로 분리하기로 했죠. 이렇게 설계하니 서비스 간의 경계가 명확해지고, 나중에 새로운 서비스가 추가되어도 기존 설정에 영향을 주지 않고 독립적으로 추가할 수 있게 되었어요.
STEP 2. Nginx 인그레스 컨트롤러 설치 및 기본 설정
설계가 끝난 후, 엔진 역할을 할 Nginx Ingress Controller를 설치했습니다. 저희는 관리가 편한 Helm을 사용했어요. 단순히 설치만 하는 게 아니라, 운영 환경에 맞게 몇 가지 중요한 옵션을 조정했죠. 예를 들어, 클라이언트가 보내는 요청의 헤더 정보를 제대로 전달받기 위해 use-forwarded-headers 옵션을 활성화했습니다. 이 설정을 빠뜨리면, 로그에 찍히는 클라이언트 IP가 실제 사용자의 IP가 아닌 컨트롤러의 내부 IP로 찍히는 문제가 생기거든요.
설치 직후에는 반드시 테스트를 거쳐야 합니다. 인그레스 컨트롤러가 생성한 서비스가 클라우드의 LoadBalancer와 제대로 연결되었는지, 그리고 생성된 단일 IP로 접속했을 때 컨트롤러의 기본 페이지가 뜨는지 확인하는 과정이 필수적이에요.
STEP 3. 서비스 라우팅 규칙 적용 (Host & Path)
이제 본격적으로 서비스를 연결할 차례예요. 인그레스 리소스를 작성할 때 가장 신경 쓴 부분은 경로 매칭 방식이었어요. 쿠버네티스 인그레스 설정에서 경로를 지정할 때 끝에 슬래시(/)를 붙이느냐 마느냐에 따라 매칭 결과가 완전히 달라질 수 있거든요.
예를 들어, `/api`라고 설정하면 `/api/v1`은 매칭되지만, `/api` 자체로는 매칭되지 않는 경우가 생길 수 있어요. 저희는 이런 혼란을 방지하기 위해 모든 경로 규칙을 명확하게 정의하고, ImplementationSpecific 방식 대신 Prefix 방식을 사용하여 유연하게 대응했습니다. 이렇게 하면 `/api/`로 시작하는 모든 요청이 해당 서비스로 부드럽게 흘러 들어갑니다.
STEP 4. SSL/TLS 인증서 자동화 구현
운영 환경에서 HTTPS는 선택이 아닌 필수죠. 서비스가 늘어날수록 수동으로 인증서를 적용하는 건 불가능에 가까워요. 그래서 저희는 Cert-manager를 도입했습니다. Let’s Encrypt를 통해 인증서를 자동으로 발급받고, 만료 30일 전에 알아서 갱신하도록 설정했어요.
인그레스 설정 파일에 tls 섹션을 추가하고, 발급받은 Secret 이름을 적어주기만 하면 끝이에요. 이제 개발자가 일일이 인증서 파일을 서버에 올리고 Nginx를 재시작할 필요가 없어졌습니다. 이 과정에서 자동화가 제대로 작동하는지 확인하기 위해, 테스트용 도메인으로 인증서 발급부터 갱신까지의 사이클을 전체적으로 검증하는 과정을 거쳤습니다.
STEP 5. 성능 최적화 및 어노테이션(Annotations) 활용
기본 설정만으로는 실무의 거친 트래픽을 견디기 어려웠어요. 그래서 인그레스 컨트롤러가 제공하는 다양한 Annotation 기능을 적극적으로 활용했습니다. 가장 먼저 해결해야 했던 건 파일 업로드 용량 문제였어요. 기본 설정값은 매우 작아서, 몇 메가바이트만 넘는 파일을 올리려고 해도 413 Request Entity Too Large 에러가 발생했거든요. 이를 위해 nginx.ingress.kubernetes.io/proxy-body-size 값을 충분히 늘려주었습니다.
또한, 특정 API의 응답 시간이 길어지는 경우를 대비해 Timeout 설정도 세밀하게 조정했습니다. 클라이언트와의 연결이 너무 빨리 끊기지 않도록 proxy-connect-timeout과 proxy-read-timeout 값을 서비스 특성에 맞춰 최적화했죠. 이 과정에서 무작정 값을 크게 잡기보다는, 모니터링 지표를 보면서 적정선을 찾는 것이 핵심입니다.
STEP 6. 모니터링 및 지표 기반 검증
마지막으로, 인그레스가 잘 작동하는지 확인하기 위해 메트릭을 수집했습니다. Prometheus와 Grafana를 사용하여 인그레스 컨트롤러의 요청 수, 에러율(4xx, 5xx), 응답 지연 시간(Latency)을 실시간으로 관찰했습니다. 인그레스를 도입한 후, 서비스별로 트래픽이 얼마나 몰리는지 한눈에 파악할 수 있게 되었고, 특정 서비스에서 에러가 급증할 때 즉각적으로 대응할 수 있는 체계를 갖추게 되었습니다.
- 비용 측면: 서비스별 LoadBalancer 사용 대비 클라우드 비용 약 70% 절감
- 관리 측면: 단일 엔드포인트(IP/도메인)로 모든 서비스 제어 가능
- 보안 측면: 중앙 집중화된 SSL/TLS 관리 및 보안 정책 적용 용이
- 확장성 측면: 새로운 서비스 추가 시 Ingress 리소스 생성만으로 즉시 노출
이렇게 인그레스를 구축하고 나니, 개발팀의 운영 부담이 눈에 띄게 줄어들었어요. 하지만 모든 것이 순탄하기만 했던 것은 아닙니다. 실제 운영 과정에서 겪은 예상치 못한 실수들과 해결 방법들을 다음 단계에서 자세히 공유해 드릴게요.
자주 하는 실수와 해결법 + FAQ
인그레스를 운영하다 보면 정말 별의별 문제가 다 생겨요. 제가 겪었던, 그리고 다른 분들이 자주 겪는 실수들을 정리해 보았습니다. 이 리스트만 숙지해도 삽질 시간을 절반 이상 줄이실 수 있을 거예요.
자주 하는 실수와 해결법
- ❌ 실수: 경로 설정 시 슬래시(/) 처리를 잘못하여 404 에러 발생
❓ 원인: Ingress의 Path 규칙은 매우 엄격해요. `/api`로 설정하면 `/api/v1`은 찾아가지만, `/api`로 끝나는 요청은 못 찾을 수 있습니다.
✅ 해결법: 가급적 Prefix 매칭을 사용하고, 경로 끝에 슬래시를 포함할지 말지를 서비스 요구사항에 맞춰 명확히 정의하세요. - ❌ 실수: SSL 인증서 적용 후 웹사이트 접속 불가
❓ 원인: Ingress 리소스에 TLS 섹션을 추가했지만, 해당 Secret이 실제로 존재하지 않거나 네임스페이스가 다를 때 발생합니다.
✅ 해결법: 인증서 Secret이 인그레스 리소스와 반드시 동일한 네임스페이스에 있는지 확인하세요. - ❌ 실수: 대용량 파일 업로드 시 413 에러 발생
❓ 원인: Nginx의 기본 클라이언트 바디 사이즈 제한 때문입니다.
✅ 해결법: 어노테이션을 통해proxy-body-size값을 넉넉하게 늘려주세요. - ❌ 실수: 서비스 간 통신 시 IP 주소 불일치
❓ 원인: LoadBalancer를 통해 들어온 요청의 실제 클라이언트 IP를 컨트롤러가 전달하지 못하고 있습니다.
✅ 해결법: 컨트롤러 설정에서 use-forwarded-headers 옵션을 활성화하세요. - ❌ 실수: Ingress 설정 변경 후 반영이 안 됨
❓ 원인: 문법 오류가 있거나 컨트롤러가 해당 리소스를 감시(Watch)하지 못하는 상태입니다.
✅ 해결법: kubectl describe ingress [이름] 명령어를 통해 이벤트 로그를 확인하여 에러 메시지를 체크하세요.
인그레스 컨트롤러를 업데이트할 때는 반드시 스테이징 환경에서 먼저 테스트하세요. 컨트롤러 자체의 버전이 올라가면서 기존에 사용하던 어노테이션이 폐기(Deprecated)되어 서비스 전체가 마비될 위험이 있습니다.
자주 묻는 질문
Q. 인그레스가 있으면 서비스(Service) 객체는 안 만들어도 되나요?
아니요, 그렇지 않아요. 인그레스는 트래픽을 어디로 보낼지 결정하는 ‘이정표’일 뿐이에요. 실제 트래픽을 전달받을 대상인 Service 객체는 반드시 있어야 합니다. 인그레스는 서비스의 이름을 참조하여 동작하거든요.
Q. 인그레스 컨트롤러를 여러 개 운영할 수 있나요?
네, 가능합니다. 예를 들어, 내부용 트래픽을 처리하는 인그레스와 외부 공개용 트래픽을 처리하는 인그레스를 별도의 컨트롤러로 분리하여 운영할 수 있어요. 이는 보안과 성능 격리 측면에서 매우 권장되는 방식입니다.
Q. 인그레스 도입 시 비용은 얼마나 절감되나요?
환경마다 다르지만, 서비스가 20개인 환경에서 각각 LoadBalancer를 썼다면 매달 수십만 원의 비용이 나가지만, 인그레스 하나로 통합하면 클라우드 로드밸런서 비용을 1개분만 내면 되므로 매우 드라마틱한 절감 효과를 볼 수 있습니다.
Q. Nginx 말고 다른 컨트롤러를 써도 괜찮을까요?
물론입니다. AWS 환경이라면 ALB Ingress Controller를, GKE라면 GCE Ingress를 사용하는 것이 클라우드 서비스와의 통합성 측면에서 더 유리할 수 있습니다. 각 컨트롤러마다 지원하는 어노테이션이 다르니 주의하세요.
Q. 인그레스 설정 파일이 너무 길어지면 어떻게 관리하나요?
서비스가 많아지면 하나의 파일이 거대해질 수 있어요. 이럴 때는 서비스 단위나 기능 단위로 인그레스 리소스를 여러 개로 쪼개서 관리하는 것이 좋습니다. 쿠버네티스는 여러 개의 인그레스 리소스를 합쳐서 하나의 컨트롤러에서 통합 관리해 줍니다.
마치며: 인그레스 운영을 위한 다음 단계
지금까지 인그레스 운영 사례를 통해 도입 배경부터 실제 적용, 그리고 트러블슈팅까지 살펴보았습니다. 인그레스는 단순히 기술적인 도구를 넘어, 복잡한 마이크로서비스 환경을 하나로 묶어주는 중앙 통제실과 같은 역할을 합니다. 처음에는 설정이 까다롭게 느껴질 수 있지만, 한 번 제대로 구축해 놓으면 운영의 차원이 달라지는 것을 경험하실 수 있을 거예요.
- 인그레스는 설정(Rule)이고, 반드시 컨트롤러가 필요합니다.
- 비용 절감을 위해 서비스별 LoadBalancer 대신 통합 인그레스를 활용하세요.
- 경로 매칭(Path) 시 슬래시(/) 처리에 주의하여 404 에러를 방지하세요.
- SSL 인증서는 Cert-manager를 통해 자동화하는 것이 정신 건강에 이롭습니다.
- 어노테이션(Annotation)을 적극 활용해 타임아웃과 업로드 용량 문제를 해결하세요.
오늘 글을 읽으셨다면, 이제 바로 실천해 볼 차례입니다. 다음 단계를 따라 하나씩 진행해 보세요.
- 오늘 할 일: 현재 운영 중인 서비스의 도메인과 경로 구조를 엑셀이나 문서로 정리해 보세요.
- 이번 주 할 일: 스테이징 환경에 Helm을 이용하여 Nginx 인그레스 컨트롤러를 설치하고 테스트해 보세요.
- 실행 직전 할 일: Cert-manager를 설치하여 테스트 도메인에 SSL 인증서가 자동으로 발급되는지 확인하세요.
인그레스 설정 과정에서 막히는 부분이 있거나, 본인만의 독특한 트러블슈팅 경험이 있다면 언제든 댓글로 질문을 남겨 주세요. 함께 고민하고 해결해 나가면 좋겠습니다. 실습 환경에서 직접 적용해 보시고, 궁금한 점은 편하게 말씀해 주세요!
관련해서 더 깊이 있는 내용이 궁금하시다면 아래 글들도 함께 읽어보시는 것을 추천드려요.
🔗 쿠버네티스 인그레스 기본 개념 글
🔗 클러스터 구축 입문 글