멀티 서비스 쿠버네티스 앱을 만들었는데 실제로 고장 난 것은 이것이다
Source: Dev.to
위에 제공된 소스 링크 외에 번역할 텍스트를 알려주시면, 해당 내용을 한국어로 번역해 드리겠습니다.
개요
앱은 각각 자체 컨테이너에서 실행되고 Kubernetes에 의해 별도로 관리되는 다섯 개의 독립적인 구성 요소로 구성됩니다. 구성 요소들은 포드 IP를 알지 못하며, 모든 통신은 Kubernetes 서비스 디스커버리를 통해 이루어집니다. 이는 실제 프로덕션 환경에서 마이크로서비스가 동작하는 방식을 반영합니다.
구성 요소
투표 프론트엔드
사용자가 투표를 진행하는 UI.
결과 프론트엔드
사용자가 집계된 결과를 확인하는 UI.
Redis
들어오는 투표를 위한 큐 역할을 함.
PostgreSQL
투표 결과를 영구 저장함.
워커 서비스
Redis에서 투표를 읽어 비동기적으로 처리하고, 결과를 PostgreSQL에 기록함.
Kubernetes Resources Used
Deployments, Pods, Services
- Deployments는 각 구성 요소의 원하는 상태를 관리합니다.
- Pods는 가장 작은 배포 단위이며, 필요 시 자동으로 재생성됩니다.
- Services는 파드에 대한 안정적인 네트워크 엔드포인트와 DNS 이름을 제공합니다.
Service Types
| 유형 | 목적 | 일반적인 사용 사례 |
|---|---|---|
| ClusterIP | 내부 전용 통신 | Redis, PostgreSQL, 내부 API |
| NodePort | 각 노드의 IP에 서비스를 노출 (테스트에 유용) | Ingress 이전에 프론트엔드를 임시로 노출 |
| Ingress | 클러스터 외부에서의 HTTP 수준 라우팅 | 프로덕션 수준 외부 접근 |
Ingress와 Ingress Controller
Ingress 리소스는 라우팅 규칙만 정의하고 자체적으로는 아무 작업도 하지 않습니다. 해당 규칙을 감시하고 실제로 들어오는 트래픽을 처리하는 Ingress Controller를 실행해야 합니다. 컨트롤러가 없으면 Ingress 규칙은 쓸모가 없습니다—제가 직접 겪은 교훈입니다.
트래픽 흐름
클러스터 내부
- Voting frontend은
redis서비스 이름을 사용하여 Redis에 투표를 전송합니다. - Worker는 동일한 서비스 이름을 사용하여 Redis에서 읽습니다.
- Worker는
postgresql서비스 이름을 사용하여 결과를 PostgreSQL에 기록합니다. - Results frontend는
postgresql서비스 이름을 사용하여 PostgreSQL에서 읽습니다.
모든 통신은 Service DNS를 사용하며, pod IP가 하드코딩되지 않습니다.
브라우저에서 애플리케이션으로
- 사용자가 HTTP 요청을 보냅니다.
- 요청이 Ingress Controller에 도달합니다.
- Ingress 규칙이 평가됩니다.
- 트래픽이 적절한 Service로 전달됩니다.
- Service가 요청을 백엔드 pod들에 로드밸런싱합니다.
Ingress는 HTTP 레벨에서 작동하며, 애플리케이션을 노출하는 프로덕션 급 방법입니다.
일반적인 함정 및 해결책
| 문제 | 해결책 |
|---|---|
| Ingress 규칙이 아무 효과도 없었습니다 | Ingress Controller (예: NGINX, Traefik)를 설치합니다. |
| Pods가 새 IP로 재생성되어 하드코딩된 주소가 깨짐 | 서비스만 사용합니다; 서비스는 안정적인 엔드포인트를 제공합니다. |
| Service 유형에 대한 혼동 | ClusterIP를 내부 트래픽에 사용하고, NodePort는 임시 테스트에만 사용하며, 외부 HTTP 트래픽에는 Ingress를 사용합니다. |
| Ingress Controller pod가 Pending 상태에 머무름 | 노드 라벨과 톨러레이션을 조정하여 컨트롤 플레인 노드에 스케줄될 수 있도록 합니다(로컬 클러스터에 해당). |
| 로컬 컨테이너 기반 클러스터에서 앱에 접근할 수 없음 | Ingress Controller 포트를 로컬 머신으로 포트 포워딩하여 클라우드 로드 밸런서를 시뮬레이션합니다. |
| 네임스페이스 간 Service 이름이 해결되지 않음 | Service DNS는 네임스페이스 범위임을 기억하고, 필요할 경우 완전한 도메인 이름(service.namespace.svc.cluster.local)을 사용합니다. |
교훈
- 쿠버네티스 네트워킹은 서비스‑중심이며, 파드‑중심이 아닙니다.
- Ingress는 작동하기 위해 규칙 및 컨트롤러가 모두 필요합니다.
- 로컬 클러스터는 관리형 클라우드 클러스터와 다르게 동작합니다(노드 스케줄링, 로드 밸런싱 등).
- 서비스 디스커버리는 DNS를 통해 이루어지며, 절대 하드코딩된 IP를 사용하지 않습니다.
- 효과적인 디버깅을 위해서는 플랫폼과 애플리케이션 아키텍처를 모두 이해해야 합니다.
이 사고 모델이 잡히면, 고급 주제(네트워크 정책, 서비스 메시 등)가 이해되기 시작합니다.
코드 얻는 방법
전체 소스 코드와 단계‑별 설정 안내는 저장소에서 확인할 수 있습니다:
kubernetes-sample-voting-app-project1
(실제 Git URL이 있다면 교체하세요.)
Kubernetes를 배우고 있다면, 다중 서비스 애플리케이션을 선택해 배포한 뒤 일부러 문제를 일으켜 보세요. 문제를 해결하면서 필요한 깊은 이해를 얻을 수 있습니다. Kubernetes에서 가장 어려웠던 부분은 무엇인가요? 댓글로 알려 주세요!
Tags: kubernetes devops learning microservices