콘텐츠로 이동

쿠버네티스 클러스터 내부 통신

11/9(월)

한 줄 요약: 같은 클러스터 안의 파드끼리는 어느 노드에 있든 내부 주소로 서로 부를 수 있다. 하지만 이건 "길이 있다"는 뜻일 뿐이다. 토큰 검사, 막는 규칙, 브라우저용 공개 주소는 따로 챙겨야 한다.

📍 만난 상황

  • 2026-11-09 16:04 — Next.js 기준 전체 아키텍처 페이지를 받은 직후였다. "Next.js 컨테이너 파드를 우리 쪽 노드에 띄우면 내부 통신에 문제없지?"라고 물었다. → 그날 일지
  • hub-dev는 외부에서 열리지 않는다. 그래서 대시보드를 같은 곳에 두면 이 문제가 풀리는지 확인하고 싶었다.
  • 답: 큰 방향은 맞다. 다만 정확한 말은 "노드"가 아니라 "같은 클러스터의 namespace"다. 확인할 점이 네 가지 남는다.

🧩 쉽게 말하면

큰 회사 사옥을 떠올리면 된다. 사옥 전체가 클러스터, 각 층이 노드, 직원이 파드, 부서가 namespace다.

같은 부서 직원도 여러 층에 흩어져 앉는다. 자리는 총무팀(쿠버네티스)이 빈자리를 보고 정한다. 그래도 사내 내선(내부 주소)으로 "기획팀 김 대리"를 부르면 어느 층이든 연결된다.

그래도 서버실에 들어가려면 출입증(토큰)이 있어야 한다. 보안팀이 특정 부서 간 통화를 막아 둘 수도 있다(NetworkPolicy). 외부 손님은 정문(공개 주소)으로만 들어온다.

이 구조가 없으면 앱마다 서버 IP를 외워 직접 연결해야 한다. 서버가 바뀔 때마다 설정을 고쳐야 한다.

📖 제대로 알기

구성 요소

용어 정체 누가 정하나
클러스터 쿠버네티스가 관리하는 서버 묶음 전체 플랫폼팀
노드 클러스터를 이루는 서버(기계) 한 대 플랫폼팀
파드 컨테이너를 실제로 돌리는 가장 작은 실행 단위 쿠버네티스가 노드에 배치
namespace 클러스터 안을 이름으로 나눈 구역(폴더 같은 것) 우리가 고름
Service 파드 묶음에 붙는 고정 이름과 주소 우리가 만듦
  • 파드는 자주 바뀐다. 재시작하면 새 파드가 생기고 IP도 바뀐다. 그래서 파드 IP를 직접 쓰지 않는다.
  • Service(서비스: 바뀌는 파드들 앞에 놓인 고정 창구)가 이 문제를 푼다. 이름이 고정되고, 요청을 살아 있는 파드로 넘겨 준다.

내부 주소 (클러스터 DNS)

  • 클러스터 안에는 DNS(이름 → 주소 변환기)가 있다. Service를 만들면 이름이 자동 등록된다.
  • 모양: 서비스이름.namespace.svc.cluster.local
  • 같은 namespace 안이면 서비스이름만 써도 된다.

바깥과 이어지는 문

  • Ingress / Gateway API(클러스터 정문: 바깥 요청을 안쪽 Service로 넘김). smartoffice가 쓰는 HTTPRoute는 Gateway API의 "이 주소는 이 서비스로" 규칙이다.
  • 바깥(브라우저)은 내부 주소를 모른다. 공개 도메인과 정문 설정이 있어야 들어온다.

막는 장치

  • NetworkPolicy(네트워크 정책: "이 namespace는 저 namespace로만 갈 수 있다" 같은 규칙).
  • 서비스 메시(istio 등: 파드 사이 통신을 가로채 암호화·권한 검사를 하는 층).
  • 둘 다 없으면 클러스터 안은 기본적으로 서로 다 통한다. 있으면 길을 열어 달라고 해야 한다.

⚙️ 어떻게 동작하나

  1. 배포: 우리가 "대시보드 namespace에 Next.js 파드 2개"를 요청한다.
  2. 배치: 쿠버네티스 스케줄러(배치 담당)가 남는 자원을 보고 노드를 고른다. 2개가 서로 다른 노드에 갈 수도 있다.
  3. 이름 부여: Service가 파드들 앞에 고정 이름을 붙이고 DNS에 등록한다.
  4. 찾기: Next.js 서버 코드가 매니저의 내부 주소를 부른다. DNS가 그 이름을 Service 주소로 바꾼다.
  5. 전달: 클러스터 네트워크가 노드 사이를 이어 준다. 다른 노드의 파드에도 그대로 닿는다.
  6. 규칙 검사: NetworkPolicy·서비스 메시가 있으면 여기서 통과 여부를 본다.
  7. 앱 검사: 매니저가 요청의 토큰을 보고 권한을 판정한다. 네트워크가 통해도 여기서 거절될 수 있다.

flowchart LR
  B["이용자 브라우저"] -->|"① 공개 도메인"| G["정문<br/>(Gateway)"]
  G --> N["Next.js 파드<br/>(대시보드 ns)"]
  N -->|"② 내부 주소 + 토큰"| M["dhub2-manager<br/>(매니저 ns)"]
  N -->|"② 내부 주소"| P[("PostgreSQL<br/>(대시보드 ns)")]
  B -.->|"③ 로그인 화면<br/>공개 주소"| M
②만 내부 통신이다. ①과 ③은 브라우저가 직접 가는 길이라 공개 주소가 필요하다. 특히 ③(로그인)을 놓치기 쉽다.

🧪 예시

  • 예시 1 · 일상에 빗대어: 사옥 10개 층에 직원 300명이 있다. 기획팀 5명은 3층에 2명, 7층에 3명 앉아 있다. 내선 "기획팀-대표번호"로 걸면 그중 받을 수 있는 사람에게 연결된다. 하지만 외부 손님은 내선을 걸 수 없다. 정문 안내 데스크(공개 주소)를 거쳐야 한다.
  • 예시 2 · 실제로는: 대시보드 앱의 환경 설정이다(이름은 자리표시).

# ① 서버끼리: 클러스터 안 주소
MANAGER_INTERNAL_URL=http://<매니저서비스>.<매니저ns>.svc.cluster.local
# ② 같은 namespace의 DB는 서비스 이름만
DATABASE_HOST=<postgres서비스>
# ③ 로그인 발급처: 브라우저가 여는 공개 주소
OIDC_ISSUER=https://<매니저 공개 도메인>
# ④ 대시보드 자신의 공개 주소(로그인 후 돌아올 곳)
APP_PUBLIC_URL=https://<대시보드 공개 도메인>
- ① 데이터 조회는 서버끼리라 내부 주소로 충분하다. 다만 매번 토큰을 붙인다. - ② namespace가 같으면 짧은 이름으로 부른다. - ③ 토큰 안의 issuer(발급처)는 공개 주소로 찍힌다. 검증할 때 이 값과 같아야 해서 내부 주소로 바꿔 쓰면 안 된다. - ④ 로그인 후 브라우저가 돌아올 주소다. 브라우저 기준이라 역시 공개 주소다.

⚖️ 비교 · 흔한 오해

무엇을 나누는 단위인가

단위 나누는 것 우리가 고르나
클러스터 완전히 다른 쿠버네티스 묶음 예(어느 클러스터에 배포할지)
노드 물리 기계 보통 아니요
namespace 이름·권한·설정의 구역 예

오해 1: "우리 쪽 노드에 띄운다"

  • 실제: 노드는 고르지 않는다. 고르는 건 클러스터와 namespace다.
  • 왜 그렇게 생각하기 쉬운가: 서버 한 대에 프로그램을 설치하던 경험 때문이다. "가까운 기계에 두면 통한다"는 물리적 그림이 남아 있다. 쿠버네티스에서는 같은 클러스터면 노드가 달라도 통한다.

오해 2: "내부망이면 다 통한다"

  • 실제: 통하는 건 네트워크 층뿐이다. 권한은 앱이 따로 본다.
  • 매니저는 내부 요청에도 토큰을 요구한다.
  • NetworkPolicy·서비스 메시가 namespace 사이를 막아 둘 수 있다.
  • 브라우저가 가는 길(화면, 로그인)은 내부망이 아니다.
  • 왜 그렇게 생각하기 쉬운가: 예전 사내망은 "안에 들어오면 믿는다"는 방식이 많았다. 지금은 안에서도 매번 확인(제로 트러스트)하는 쪽이 기본이다.

🛠️ 실무에서는

  • 쓰면 좋을 때: 앱이 플랫폼 API·DB를 서버끼리 부르고, 플랫폼이 외부에 열려 있지 않을 때.
  • 배포 전 체크리스트
  • 어느 클러스터, 어느 namespace에 배포하는지 플랫폼팀과 정했다.
  • 대시보드 ns → 매니저 ns 통신이 NetworkPolicy·istio에서 허용되는지 물었다.
  • 서버가 쓸 토큰(서비스 계정 또는 사용자 토큰 교환)을 준비했다.
  • 대시보드 공개 도메인과 정문 규칙(HTTPRoute 등)을 신청했다.
  • 매니저 로그인 화면이 이용자 브라우저에서 열리는지 확인했다.
  • 안 될 때 먼저 볼 것
  • 이름을 못 찾음 → 서비스 이름·namespace 오타, DNS 주소 형태.
  • 연결 시간 초과 → NetworkPolicy·서비스 메시 차단.
  • 401·403 → 네트워크는 통했다. 토큰·권한 문제다.
  • 로그인만 실패 → issuer 불일치, 공개 주소 접근 불가.

❓ 자주 묻는 질문

  • Q. 같은 노드에 두면 더 빠르지 않나? A. 약간 빠를 수 있지만 보통 신경 쓰지 않는다. 노드 고정은 장애에 약해져서 특별한 이유가 있을 때만 한다.
  • Q. namespace가 다르면 서로 못 부르나? A. 기본은 부를 수 있다. 막는 규칙이 있을 때만 막힌다. 주소에 namespace를 넣어 부르면 된다.
  • Q. 클러스터가 다르면? A. 내부 주소로는 안 된다. 그때는 공개 주소나 클러스터 사이 전용 연결이 필요하다.
  • Q. 내부 통신이면 HTTPS가 필요 없나? A. 클러스터 정책에 따른다. 서비스 메시가 자동으로 암호화하기도 한다. 플랫폼팀 규칙을 따른다.

🔭 더 깊이 보기

  • Service의 종류(ClusterIP, NodePort, LoadBalancer)는 어떻게 다른가? — 내부 전용과 외부 공개가 어떻게 갈리는지 알 수 있다.
  • NetworkPolicy는 어떻게 쓰나? — "우리 ns에서 매니저로 가는 길을 열어 주세요"를 정확히 요청할 수 있다.
  • 제로 트러스트란? — 내부망에서도 토큰을 요구하는 이유의 배경이다.
  • 관련 주제: OIDC 로그인 흐름 · 프론트엔드와 백엔드 서버 구조 · Docker Compose 로컬 개발환경

📚 참고 자료

  • 서비스 (Kubernetes 한국어 문서) — 파드 앞에 고정 이름을 붙이는 Service 개념 · 링크
  • 서비스 및 파드용 DNS (Kubernetes 한국어 문서) — svc.cluster.local 주소가 만들어지는 규칙 · 링크
  • 네트워크 정책 (Kubernetes 한국어 문서) — namespace 사이 통신을 막고 여는 규칙 · 링크

🗓️ 이력

  • 2026-11-09: Next.js 파드를 "우리 쪽 노드"에 띄우면 내부 통신이 되는지 물음. 노드 대신 클러스터·namespace, 토큰·공개 주소가 여전히 필요함을 정리 → 일지

🕸️ 연결된 주제