궁금한게 많은 개발자 노트

컨테이너와 가상 머신 본문

DevOps

컨테이너와 가상 머신

궁금한게 많은 개발자 2024. 9. 23. 13:56

container와 virtual macine

container는 운영체제 수준의 가상화 기술로 호스트 운영체제와 리눅스 커널을 공유하면서도 프로세스를 격리된 환경에서 실행하는 기술입니다. 하드웨어를 가상화하는 가상 머신과 달리 커널을 공유하는 방식이기에 실행 속도가 빠르고 성능 상의 손실이 거의 없습니다. 

컨테이너의 격리는 리눅스 네임스페이스, cgroup 등의 커널 기능을 활용하여 이루어집니다. 이러한 격리 기술 덕분에 호스트 머신에서는 프로세스로 인식되지만, 컨테이너 관점에서는 독립적인 환경을 가진 가상 머신처럼 동작됩니다.

 

VM은 하이퍼바이저라는 것이 존재하며 리소스에 대한 액세스를 효율적으로 관리하여 가상 머신을 개별 서버로 활용할 수 있도록 해줍니다. 하이퍼바이저를 통하여 물리적 하드웨어를 가상화하여 각각의 가상 머신이 자신만의 운영 체제를 실행할 수 있도록 하는 기술입니다.
(하이퍼바이저: 물리적 하드웨어 위에서 동작하며, 다수의 가상 머신을 생성하고 자원을 분배)

 

container장점

- 경량화: VM에 비해 훨씬 가벼운 리소스 사용, OS전체 가상화 하지 X, CPU/메모리 사용량이 비교적 적음

- 빠른 실행: 부팅 시간 없기에 거의 즉시 시작

- 이식성: 어떤 환경에서도 동일하게 실행되므로, 개발/테스트/프로덕션 환경 간 일관성이 보장

- 빠른 배포 및 롤백: 애플리케이션의 여러 버전을 쉽게 배포하고 필요시 빠르게 롤백 가능

container단점

- 운영 체제 종속성: 호스트 운영 체제와 커털을 공유하기 때문에 동일한 유형의 운영 체제만 사용 가능

- 격리 수준: VM에 비해 컨테이너는 완전한 하드웨어 수준의 격리는 X, 호스트 운영 체제에 영향을 미칠 수 있음

- 보안: 커널을 공유하기 때문에 완전한 하드웨어 격리보다는 약함, 커널 취약 시 다수 컨테이너에 영향

 

VM장점

- 완전한 격리, 다양한 OS지원, 보안성, 기존 환경과 호환성

VM단점

- 무거운 리소스 사용, 느린 부팅 시간, 비효율성(동일한 OS내 여러 VM운영 시 동일한 커널 복제하므로), 관리 복잡성

 

도커 컨테이너가 적합한 경우:

  • 경량화된 애플리케이션을 빠르게 배포하고 실행해야 할 때.
  • 마이크로서비스 아키텍처를 사용하여 서비스 간 격리와 빠른 배포가 필요할 때.
  • CI/CD 파이프라인에서 빠른 테스트 및 배포 주기가 요구될 때.
  • 개발 환경과 프로덕션 환경을 일관성 있게 유지하고자 할 때.

가상 머신이 적합한 경우:

  • 여러 운영 체제를 필요로 하거나 다양한 OS 환경에서 애플리케이션을 실행해야 할 때.
  • 보안이 매우 중요하고, 완전한 격리된 환경이 요구될 때.
  • 기존의 레거시 애플리케이션을 가상화하여 사용해야 할 때.
  • 리소스 사용량이 덜 중요한 경우 또는 물리 서버를 여러 가상 머신으로 나누어 사용하는 경우.

 

cgroup과 네임스페이스 격리

control group의 약자로 프로세스 그룹을 단위로 시스템 리소스를 수집, 제한, 격리하는데 사용되는 리눅스 커널의 기능입니다. 컨테이너에서 사용할 리소스를 제한하여 독립된 프로세스 환경을 만들어줌과 동시에 하나의 컨테이너가 리소스를 모두 사용해 다른 컨테이너에 영향을 주는 것을 방지합니다. 또한 그룹에 계층 구조를 적용할 수 있어 체계적으로 리소스를 관리할 수 있습니다.

 

cgroup이 리소스를 격리하는 것에 사용되었다면, 네임스페이스는 컨테이너가 볼 수 있는 영역을 격리시켜 프로세스를 독립시켜주는 가상화 기술입니다. 네임스페이스는 nested process tree를 만들어주며, 분리된 프로세스 트리를 가지게 되면 다른 프로세스 트리에서 분리된 프로세스를 확인하거나 제어할 수 없습니다. 분리된 프로세스 트리의 가장 윗 프로세스가 PID 1번으로 init 프로세스를 대체하게 됩니다. 

 

containter 사이의 통신

도커에서 기본적으로 같은 노드(host)사이의 통신은 docker default bridge라는 것을 이용하여 각 컨테이너의 가상 네트워크 인터페이스 veth를 브릿지로 연결합니다. 연결된 컨테이너들은 브릿지로 통신이 가능하지만 같은 브릿지에 연결되지 않은 컨테이너는 격리됩니다. 또한 컨테이너에서 외부로 통신 시에도 브릿지를 경유하여 통신이 가능하게 됩니다.

각 컨테이너는 네임스페이스로 격리되며 eth을 기본적으로 가지고 있으며 이것은 서로 연결되기 전까지는 독립적이지만, veth, 브릿지를 통해 서로 연결되면 통신이 가능합니다.

 

다른 호스트에 있는 컨테이너간 통신은 별도의 오버레이 네트워크가 필요하며, 도커 스웜이나 다른 네트워크 플러그인이 있어야 가능합니다.

 

pod 사이의 통신

쿠버네티스는 도커와 달리 파드 단위로 컨테이너를 관리합니다. 파드는 여러개의 컨테이너로 이루어질 수 있으며, 컨테이너들은 모두 동일한 IP를 할당받습니다. 이 때 컨테이너가 모두 같은 IP를 할당받게 해주는 것은 pause 컨테이너입니다.

pause 컨테이너는 파드 내 컨테이너들에게 같은 네임스페이스를 제공하고 공유하게 하여 같은 IP를 사용할 수 있게 하고 port를 통해 컨테이너를 구분 할 수 있습니다. (Pod내 컨테이너는 네임스페이스, IPC, 스토리지를 공유)

 

파드는 veth라는 가상 네트워크 인터페이스로 인해 고유한 IP를 가집니다. 각 pod 는 kubenet또는 CNI로 구성된 네트워크 인터페이스를 통해 고유한 IP로 서로 통신이 가능합니다. 이 때 CNI 플러그인은 각 pod가 중복되지 않는 고유한 IP를 갖게 할당해주며, 이러기 위해서 모든 워커 노드에게 중복되지 않는 Subnet을 제공합니다. 또한 Pod간 routing table 규칙을 설정하여 통신이 가능하게 해줍니다. 일반적으로 Pod IP를 통해 통신이 이루어지지 않으며 서비스라는 개념을 통해 여러 개일 수 있는 파드에 요청을 전달해줍니다. 이 때 domain name을 통해 pod들은 서로 요청을 하는데, domain name을 service의 cluster IP로 변환해주는 것을 coredns라는 컴포넌트가 처리해주고 service ip를 pod ip로 변환해주는 것은 kube-proxy가 처리합니다. 

즉, 파드는 서비스의 dns name으로 요청을 보내게 되고, cluster의 dns서버인 coredns에서 해당 이름을 service cluster ip로 매핑 및 변환해줍니다. 이에 server ip를 kube-proxy가 pod ip로 변환하여 요청하면 CNI plugin의 라우팅 테이블을 거쳐 target pod에 전달됩니다.

 

 

'DevOps' 카테고리의 다른 글

AWS와 Azure  (0) 2024.11.01
클라우드 관련 업무 지식  (0) 2024.09.23
서버리스 (Serverless)  (2) 2024.09.17
[ k8s ] Kubernetes Cluster AutoScaler VS Karpenter  (0) 2024.04.19
[ CKA ] Cluster 업그레이드  (0) 2024.03.16
Comments