SW/Kubernetes, Docker

물리 서버, VM, Docker, Kubernetes 네트워킹 차이: 어디서 막히는지 한 번에 이해하기

얇은생각 2026. 5. 31. 07:30
반응형

웹이 안 열릴 때 사람들은 곧바로 쿠버네티스나 클라우드를 의심합니다. 그런데 실제로는 훨씬 아래층, 주소(IP), 이름(DNS), 입구(포트), 경로(라우팅) 중 하나가 꼬인 경우가 더 많습니다. 이 글은 물리 서버부터 VM, Docker, Kubernetes까지를 따로 외우는 대신, 요청 하나가 어디에서 막히는지 같은 눈으로 보는 법을 정리합니다.

도구 이름은 계속 바뀌어도, 결국 확인해야 하는 것은 비슷합니다. 어디로 가야 하는지, 무슨 이름으로 찾는지, 어느 입구로 들어가는지, 누가 길을 막는지. 이 네 가지만 놓치지 않으면 최신 플랫폼이 나와도 덜 흔들립니다.

 

단일 물리 서버에서 VM, 컨테이너, 쿠버네티스 클러스터로 이어지는 네트워크 구조의 변화를 한 장면으로 보여 주는 그림

 

왜 아직도 네트워크에서 자꾸 막힐까

인프라가 복잡해질수록 도구 이름은 늘어나지만, 실제로 확인해야 할 질문은 늘 비슷합니다.

  • 이 요청은 어디로 가야 하나: 주소(IP)
  • 사람이 읽는 이름은 무엇으로 바뀌나: DNS
  • 서버 안에서 어느 프로세스로 들어가나: 포트
  • 중간에서 누가 막고, 누가 길을 안내하나: 라우팅과 보안 규칙

 

이 네 가지를 한 줄로 붙여 놓으면 물리 서버, VM, 클라우드, Docker, Kubernetes가 따로 노는 개념이 아니라 한 흐름으로 보입니다.

 

단계 새로 얻는 것 새로 생기는 착각 먼저 볼 것
물리 서버 구조가 단순함 서버만 살아 있으면 다 되는 줄 앎 IP, DNS, 포트
VM 격리, 스냅샷, 자원 활용 public IP와 private IP를 자주 혼동함 private IP, NAT, 방화벽
클라우드 VPC 네트워크 분리와 정책화 subnet만 나누면 자동으로 안전하다고 생각함 route table, security group, gateway
Docker 빠른 배포와 이식성 컨테이너 포트가 바로 외부에 열리는 줄 앎 bridge, port mapping
Kubernetes 자동 복구와 확장 Pod IP를 고정 주소처럼 다룸 Service, DNS, Ingress, NetworkPolicy

 

추상화가 올라갈수록 편해지는 일도 분명히 있습니다. 대신 문지기가 늘어납니다. DNS, 방화벽, NAT, security group, Service, Ingress, NetworkPolicy가 앞단에 하나씩 추가되기 때문에, 문제는 줄지 않고 더 잘 숨어버립니다.

 

 

출발점은 늘 같다: IP, DNS, 포트, eth0

처음 서비스를 올릴 때는 보통 하나의 물리 서버에서 모든 것이 시작됩니다. 웹 앱, 데이터베이스, 백그라운드 작업이 한 대에서 돌고, 외부에서는 그 서버의 공인 IP 하나만 바라봅니다.

여기서 제일 먼저 잡아야 할 감각은 "요청이 들어오는 순서"입니다.

  1. 사용자는 도메인 이름을 입력합니다.
  2. DNS가 그 이름을 IP 주소로 바꿉니다.
  3. 요청은 서버의 네트워크 인터페이스, 예를 들면 eth0 같은 입구로 들어옵니다.
  4. 운영체제가 포트 번호를 보고 어느 프로세스로 넘길지 결정합니다.

 

이 흐름을 놓치면 이후 단계도 계속 헷갈립니다. 웹 서버는 보통 80이나 443을 받고, 데이터베이스는 3306이나 5432 같은 포트를 씁니다. 즉 IP는 집 주소, eth0는 현관문, 포트는 방 번호라고 보면 됩니다.

 

실전에서는 여기서부터 이미 자주 막힙니다.

  • DNS는 맞는데 앱이 죽어 있으면 이름은 맞아도 응답이 없습니다.
  • 서버는 살아 있지만 앱이 다른 포트에서 듣고 있으면 접속이 안 됩니다.
  • 앱이 127.0.0.1에만 바인딩돼 있으면 서버 안에서는 보이는데 외부에서는 안 보입니다.

 

네트워크 기초를 다시 볼 때 중요한 건 "IP가 뭐다"를 외우는 게 아니라, 요청이 서버 안 프로세스까지 어떻게 들어가는지 머릿속에 그려 보는 일입니다.

 

 

VM으로 넘어가면 뭐가 좋아지고, 뭐가 새로 꼬일까

물리 서버 한 대에 모든 것을 몰아넣는 방식은 단순하지만 치명적인 약점이 있습니다. 장애가 나면 전부 같이 멈추고, 트래픽이 늘어도 유연하게 나누기 어렵고, 업데이트 한 번에도 전체 서비스가 흔들립니다.

그래서 등장한 것이 가상화와 VM입니다. 하나의 큰 물리 서버 위에 여러 개의 독립된 컴퓨터처럼 보이는 VM을 올리면, 서비스별로 나눠 담을 수 있고 장애 격리도 쉬워집니다. 무엇보다 스냅샷과 복구가 쉬워져 운영 부담이 크게 줄어듭니다.

하지만 네트워크는 여기서부터 한 단계 복잡해집니다. VM마다 private IP가 생기고, 바깥에서는 물리 호스트의 public IP를 통해 접근하게 됩니다. 즉 "안쪽 주소"와 "바깥 주소"가 분리됩니다.

이때 자주 헷갈리는 포인트는 세 가지입니다.

  • VM끼리는 private IP로 통신할 수 있지만, 그 주소는 인터넷에서 바로 보이지 않습니다.
  • 외부 통신은 NAT를 거치며 public IP 뒤에서 나갑니다.
  • 통신이 안 되면 애플리케이션 문제일 수도 있지만, 중간 방화벽 규칙이나 가상 네트워크 설정 문제일 수도 있습니다.

 

초보자가 가장 많이 하는 착각은 "VM에 앱이 떠 있으니 이제 접근만 하면 되겠지"입니다. 실제로는 그 전에 private IP가 맞는지, 외부에서 들어오는 길이 열려 있는지, 어느 계층의 방화벽이 막고 있는지를 따져야 합니다.

 

 

클라우드에서 자주 헷갈리는 건 서버가 아니라 경계다

클라우드로 올라오면 서버를 직접 들여놓고 케이블을 꽂을 필요는 줄어듭니다. 대신 경계를 설계하는 일이 더 중요해집니다. AWS 기준으로 보면 VPC는 내 서비스만 쓰는 격리된 네트워크 공간이고, subnet은 그 안을 역할별로 나눈 구역입니다.

여기서 중요한 건 "무엇을 public에 둘 것인가"보다 "무엇을 절대 public에 두면 안 되는가"를 먼저 정하는 일입니다. 웹 진입점은 public에 둘 수 있어도, 데이터베이스나 내부 서비스는 private에 남겨야 합니다. 이 선을 잘못 그으면 성능 문제가 아니라 보안 사고나 연결 불가가 먼저 옵니다.

  • public subnet: 인터넷에서 직접 받아야 하는 진입점, 예를 들면 웹 서버나 로드 밸런서
  • private subnet: 외부에서 바로 보이면 안 되는 데이터베이스나 내부 애플리케이션
  • security group: 누가 어느 포트로 들어오고 나갈 수 있는지 정하는 규칙
  • route table: 트래픽이 어느 길로 나가고 들어오는지 정하는 지도
  • NAT gateway: private subnet 자원이 바깥으로 나갈 때 쓰는 중간 출구

 

운영에서 자주 생기는 실패는 의외로 단순합니다. 데이터베이스를 private subnet에 넣어 놓고도 애플리케이션이 그 subnet까지 갈 경로를 안 열어 놓는다거나, private subnet 인스턴스가 패키지 업데이트를 받아야 하는데 NAT gateway 없이 막혀 있는 경우입니다.

즉 클라우드 네트워킹은 "서버를 더 많이 아는 게임"이 아니라 "경계를 잘못 그리면 아무것도 붙지 않는 게임"에 가깝습니다.

 

 

Docker에서 가장 많이 틀리는 건 이미지가 아니라 포트다

Docker는 앱과 의존성을 이미지로 묶어 배포를 가볍게 만듭니다. 하지만 접속 문제만 놓고 보면 진짜 함정은 이미지 빌드보다 네트워크 쪽에 더 많이 숨어 있습니다.

Docker에서 먼저 잡아야 할 것은 세 가지입니다.

  • bridge: 같은 호스트 안 컨테이너끼리 통신하는 기본 네트워크
  • overlay: 여러 호스트에 걸친 컨테이너 통신
  • port mapping: 호스트 포트와 컨테이너 포트를 연결하는 규칙

 

예를 들어 호스트의 80을 컨테이너의 8080에 매핑하면, 외부에서 들어온 요청은 먼저 호스트에 도착한 뒤 그다음 컨테이너 내부 포트로 전달됩니다. 즉 컨테이너가 8080에서 잘 떠 있어도 host port를 안 열어 두면 밖에서는 접속할 수 없습니다.

또 하나 많이 놓치는 점은 이름 해석 범위입니다. 같은 Docker 네트워크 안에서는 컨테이너 이름으로 통신할 수 있어도, 다른 네트워크나 외부에서는 그 이름이 그대로 통하지 않습니다. Docker의 공식 bridge 네트워크 설명도 이 범위를 기준으로 이해하면 훨씬 덜 헷갈립니다. Docker bridge network 공식 문서

컨테이너와 오케스트레이션 흐름을 같이 정리하고 싶다면 Kubernetes 입문 전 알아야 할 Docker 오케스트레이션 핵심 개념 총정리를 이어서 보는 것이 자연스럽습니다.

 

 

쿠버네티스에서 진짜 중요한 건 Pod IP를 믿지 않는 습관

쿠버네티스로 오면 많은 사람이 갑자기 개념이 폭증했다고 느낍니다. 그런데 핵심만 남기면 의외로 단순합니다. "컨테이너 수가 너무 많아져서 수동 관리가 안 되니, 배치와 복구와 연결을 자동화한다"는 이야기입니다.

네트워크 관점에서 가장 중요한 변화는 Pod마다 IP가 생긴다는 점입니다. Pod는 클러스터 내부에서 서로 직접 통신할 수 있지만, 그 IP를 믿고 다른 서비스가 직접 붙기 시작하면 금방 문제가 생깁니다. Pod는 자주 재시작되고, 옮겨지고, 교체되기 때문입니다.

그래서 쿠버네티스에서는 Pod IP 대신 Service를 씁니다. Service는 뒤에 어떤 Pod가 살아 있든 앞단의 고정된 접근 지점을 유지해 줍니다. 공식 문서도 Service를 "Pod 집합 위의 안정적인 네트워크 추상화"로 설명합니다. Kubernetes Service 공식 문서

여기서 역할을 헷갈리지 않게 한 번에 묶어 두면 훨씬 편합니다.

  • Pod: 실제 애플리케이션이 도는 실행 단위
  • CNI: Pod에 네트워크 인터페이스와 IP를 붙여 주는 구성 요소
  • Service: Pod가 바뀌어도 접근 지점을 고정해 주는 이름과 IP
  • Ingress: 외부 사용자가 들어오는 단일 진입점
  • NetworkPolicy: Pod 간 통신 허용 범위를 잠그는 규칙

 

실무에서 특히 자주 꼬이는 부분은 세 군데입니다.

  • Ingress 리소스만 만들었다고 외부 노출이 끝나는 것은 아닙니다. 실제로 트래픽을 받아 줄 Ingress Controller가 있어야 합니다.
  • Service 포트와 Pod가 실제로 듣는 포트가 다르면 이름은 맞는데 연결은 실패합니다.
  • NetworkPolicy는 YAML만 써 놓는다고 끝나지 않습니다. 사용하는 네트워크 플러그인이 정책 집행을 지원해야 실제로 차단됩니다. 이 조건은 Kubernetes 공식 문서에도 분명히 적혀 있습니다. Kubernetes NetworkPolicy 공식 문서

 

예를 들어 브라우저는 443으로 들어오고, Ingress는 그 요청을 Service 80으로 넘기고, 실제 Pod는 8080에서 듣고 있을 수 있습니다. 숫자가 셋 다 달라도 이상한 것이 아닙니다. 연결 규칙이 정확히 이어져 있느냐가 핵심입니다.

쿠버네티스가 인프라 자체를 자동으로 만들어 주는 도구라고 생각하고 있었다면, 쿠버네티스가 서버까지 만들어줄까? 오케스트레이션 vs 인프라 프로비저닝 완벽 가이드도 함께 보면 개념 경계가 더 또렷해집니다.

 

 

장애가 나면 어디부터 보면 될까

이 글을 다 읽고도 실제로 필요한 건 결국 체크 순서입니다. 아래 순서로 보면 대개 원인을 훨씬 빨리 좁힐 수 있습니다.

 

1. 이름이 맞는가

도메인이 올바른 IP로 해석되는지 먼저 봅니다. 여기서 틀리면 뒤를 아무리 봐도 소용이 없습니다.

 

2. 그 주소까지 길이 열려 있는가

라우팅, subnet, route table, gateway, load balancer, Ingress 중 어디에서 길이 끊겼는지 봅니다. 클라우드에서는 이 단계에서 막히는 일이 생각보다 많습니다.

 

3. 입구가 맞는가

서버 포트가 열려 있는지, Docker라면 host port와 container port가 제대로 매핑됐는지, Kubernetes라면 Ingress와 Service 포트가 맞는지 확인합니다.

 

4. 뒤에 있는 대상이 살아 있는가

프로세스가 실제로 떠 있는지, 컨테이너가 정상인지, Pod가 Ready 상태인지 확인합니다. 입구가 맞아도 뒤에 받을 대상이 없으면 결국 실패합니다.

 

5. 규칙이 막고 있지 않은가

호스트 방화벽, security group, network policy 가운데 누가 막고 있는지 마지막으로 좁힙니다. 많은 장애가 앱 버그처럼 보이다가 사실은 여기서 끝납니다.

이 순서는 환경이 바뀌어도 거의 그대로 재사용됩니다. 물리 서버에서든, VM에서든, Kubernetes에서든 결국 주소, 길, 입구, 대상, 규칙을 보는 방식은 같습니다.

 

 

정리: 새 도구를 배워도 확인 순서는 거의 같다

물리 서버에서 시작한 네트워크는 VM, 클라우드, Docker, Kubernetes로 갈수록 더 강력해졌습니다. 대신 추상화가 늘어난 만큼 어디에서 막히는지 감을 잃기 쉬워졌습니다.

그래서 새 도구를 만날 때마다 겁먹기보다 먼저 이렇게 생각하면 됩니다. "이 요청의 이름은 맞나, 주소는 맞나, 입구는 맞나, 뒤에 받을 대상은 있나, 누가 막고 있나?" 이 순서만 몸에 붙으면 설명이 긴 문서보다 훨씬 빨리 문제를 좁힐 수 있습니다.

 

 

FAQ

쿠버네티스에서는 왜 Pod IP 대신 Service 이름을 써야 하나요?

Pod는 자주 다시 만들어져서 주소가 바뀔 수 있습니다. Service는 앞쪽 주소를 고정해 주기 때문에, 앱끼리는 Pod가 바뀌어도 같은 이름으로 안정적으로 붙을 수 있습니다.

보안 그룹과 네트워크 폴리시는 같은 건가요?

아니요. 보안 그룹은 클라우드 인스턴스 쪽 경계에서 주로 보고, 네트워크 폴리시는 쿠버네티스 안에서 Pod끼리 누가 누구와 통신할지 더 세밀하게 다룹니다.

반응형