본문 바로가기
카테고리 없음

MSA 쿠버네티스 배포 (ConfigMap, Service Mesh, 포트포워딩)

by ricepuppy9733 2026. 6. 10.

쿠버네티스로 MSA 환경을 처음 구성해보려는 분들, 혹시 "배포는 됐는데 서비스끼리 왜 못 찾지?" 하고 막막했던 적 없으셨습니까? 저는 있습니다. Gateway가 Eureka를 못 찾아서 30분을 헤맸고, 그제야 ConfigMap 설정을 빠뜨렸다는 걸 알았습니다. 이 글은 그 삽질의 기록이기도 합니다.

MSA 쿠버네티스

ConfigMap과 Eureka로 서비스 연결하기

MSA 환경에서 쿠버네티스에 여러 서비스를 올리다 보면, 설정값을 어디에 어떻게 넣어야 할지 바로 헷갈리기 시작합니다. 환경변수를 Pod 스펙 안에 직접 하드코딩해두면, 값 하나 바뀔 때마다 이미지를 새로 빌드해야 하는 상황이 옵니다. 실제로 제가 처음 실습할 때 그렇게 했다가, DB 비밀번호 하나 바꾸려고 이미지를 두 번 다시 빌드한 기억이 납니다.

그래서 쿠버네티스에서는 ConfigMap을 사용합니다. ConfigMap이란 컨테이너 이미지와 설정값을 분리해서 관리하는 쿠버네티스 오브젝트입니다. 쉽게 말해, 코드는 그대로 두고 설정만 외부에서 갈아끼울 수 있게 해주는 구조입니다. EUREKA_URL이나 DB_URL 같은 값들을 ConfigMap에 선언해두고, Deployment에서 envFrom으로 참조하면 됩니다.

여기서 Eureka란 Spring Cloud Netflix에서 제공하는 Service Discovery 컴포넌트입니다. MSA 환경에서는 Pod가 재시작될 때마다 IP가 바뀌기 때문에, 서비스들이 서로를 고정 주소로 찾을 수가 없습니다. Eureka는 각 서비스가 자신의 위치를 등록하고, 다른 서비스가 그 위치를 조회할 수 있게 해주는 중앙 등록소 역할을 합니다. api-user는 자신을 Eureka에 등록하고, api-gateway는 Eureka에 물어봐서 api-user의 위치를 알아내는 방식입니다.

제가 실습하면서 특히 신경 쓴 부분은 User 서비스의 ConfigMap이었습니다. Gateway는 Eureka 주소만 있으면 되지만, User 서비스는 DB_URL, DB_USER, DB_PASSWORD에 더해 MariaDB 컨테이너 초기화용 환경변수까지 한 ConfigMap에 같이 들어갑니다. MARIADB_ROOT_PASSWORD와 MARIADB_DATABASE 같은 값들이 그것인데, 이는 Spring Boot 애플리케이션이 필요한 클라이언트 설정과, MariaDB 서버 자체가 최초 기동 시 필요한 서버 설정이 하나의 ConfigMap에 공존하는 형태입니다. 처음엔 왜 이걸 같이 넣는지 의아했는데, 같은 Pod 안에 두 컨테이너가 함께 뜨는 구조라서 하나로 묶어두는 편이 관리가 편했습니다.

MSA 배포 시 주요 구성 요소를 정리하면 다음과 같습니다.

  • ConfigMap: 환경변수, DB 접속 정보, Eureka 주소 등 설정값을 외부에서 주입
  • PVC(PersistentVolumeClaim): DB 컨테이너의 데이터를 Pod 재시작 후에도 유지
  • Deployment: Spring Boot 컨테이너와 DB 컨테이너를 같은 Pod에 묶어 배포
  • Service: 라벨 셀렉터(label selector)로 Pod를 찾아 외부와 연결

여기서 PVC란 PersistentVolumeClaim의 약자로, 컨테이너가 사용할 영구 저장 공간을 요청하는 쿠버네티스 오브젝트입니다. Pod가 죽고 다시 뜨더라도 /var/lib/mysql 경로에 연결된 디스크 데이터는 그대로 보존됩니다. 이걸 안 붙여두면 Pod 재시작 때마다 DB가 초기화되는 참사가 벌어집니다. 저도 실습 중에 한 번 겪었고, 그 뒤로는 DB 관련 Deployment에는 PVC를 반드시 확인하게 됐습니다.

Service Mesh와 포트포워딩, 내부 구조까지 보이기 시작했다

서비스 연결이 잡히고 나면 그다음 고민은 "이걸 어떻게 관리하고 모니터링하지?"입니다. 서비스가 3개일 때는 로그를 일일이 들여다볼 수 있지만, 수십 개로 늘어나면 어디서 병목이 생기는지조차 파악하기 힘들어집니다.

이 문제를 해결하기 위해 등장한 개념이 Service Mesh입니다. Service Mesh란 MSA 환경에서 서비스 간 네트워크 통신을 코드 수정 없이 제어·모니터링하는 인프라 계층입니다. 로깅, 모니터링, 트래픽 제어를 각 서비스 코드에 직접 구현하지 않아도 자동으로 처리해 줍니다. 대표적인 오픈소스 구현체가 Istio입니다.

Istio는 사이드카 패턴(Sidecar Pattern) 방식으로 동작합니다. 사이드카 패턴이란 각 서비스 Pod 옆에 Envoy Proxy 컨테이너를 자동으로 붙여두고, 서비스로 들어오고 나가는 모든 네트워크 트래픽을 이 프록시가 대신 처리하게 하는 구조입니다. 덕분에 서비스 코드는 전혀 건드리지 않고도 TLS 암호화, 로드 밸런싱, 재시도 로직, 트래픽 메트릭 수집이 가능해집니다(출처: Istio 공식 문서).

Istio를 설치하면 Prometheus, Grafana, Kiali 같은 애드온도 함께 구성할 수 있습니다. 여기서 Kiali란 Istio에 특화된 서비스 간 트래픽 흐름을 시각화해주는 UI 도구입니다. 어떤 서비스가 어떤 서비스를 몇 번 호출하는지, 어디서 오류가 나는지를 한눈에 볼 수 있습니다. 제가 직접 붙여봤는데, 처음으로 서비스 간 의존 관계가 지도처럼 그려지는 걸 보고 솔직히 이건 예상 밖이었습니다. 그동안 로그만 뒤지던 게 민망할 정도였습니다.

모니터링 도구들은 기본적으로 Service 타입이 ClusterIP로 설정됩니다. ClusterIP란 쿠버네티스 클러스터 내부에서만 접근 가능한 서비스 타입으로, 외부에서는 직접 접속할 수 없습니다. Grafana나 Prometheus 웹 UI에 외부에서 접근하려면 서비스 타입을 LoadBalancer로 변경해야 합니다. MetalLB 같은 로드밸런서가 구성되어 있다면, 외부 IP를 ARP 광고 방식으로 브로드캐스트해서 클러스터 외부에서도 접근 가능하게 만들어 줍니다.

포트포워딩 경로를 nft list ruleset으로 직접 추적해본 경험도 인상 깊었습니다. 31086 포트로 들어온 패킷이 KUBE-NODEPORTS → KUBE-EXT → KUBE-SVC → KUBE-SEP 체인을 거쳐 실제 Pod IP의 포트로 DNAT되는 과정이 그대로 보였습니다. 쿠버네티스 내부가 사실 리눅스 iptables/nftables 기반의 NAT 규칙 덩어리라는 게 체감이 됐고, 그 이후로 네트워크 트러블슈팅이 훨씬 편해졌습니다. 쿠버네티스 내부 네트워크 구조에 대해서는 CNCF의 공식 문서에서도 상세히 다루고 있습니다(출처: CNCF).

MSA를 쿠버네티스에서 직접 구성해보면, 처음엔 ConfigMap 하나도 어디에 어떻게 붙이는지 헷갈립니다. 하지만 Gateway-Discovery-User 서비스 흐름을 한 번 끝까지 연결해보고, 거기에 Istio까지 올려보면 전체 구조가 한꺼번에 이해됩니다. 다음 단계로는 Kiali에서 실제 트래픽 흐름을 보면서 병목 구간을 찾아보시길 권합니다. 이론으로만 읽을 때와 완전히 다른 감각이 생깁니다.


참고: https://dltldnr2563.tistory.com/entry/%EC%BD%94%EB%94%A9%EA%B3%B5%EB%B6%8020250915-service-mash-%ED%8F%AC%ED%8A%B8%ED%8F%AC%EC%9B%8C%EB%94%A9-pm-%ED%8A%B9%EA%B0%95


소개 및 문의 · 개인정보처리방침 · 면책조항

© 2026 자동식단생성 연관 블로그