컨테이너로 어플리케이션 워크로드를 운영하는 것은 일반 가상 환경에서 서버를 운영하는 것과 다르다.

특히 실제 서비스 운영 단계에 봉착하면 컨테이너 자체의 관리 뿐 아니라 Docker 설정 환경 상 이슈, 컨테이너 들 간에 Dependency 관리 및 스케일링과 같은 다양한 문제를 만나게 되며, 이러한 문제를 마주치면 컨테이너가 무조건 좋은 기술만은 아니라는 생각이 들게 된다.

 

이 문제를 해결하기 위해 실제 프로덕션 환경에서는 Container 들 간에 논리적인 Orchestration 을 수행하게 된다. 이를 통해 컨테이너를 적절히 배치하고 스케줄링하며 죽은 컨테이너를 재구성해준다.

 

이를 통해 실제로 컨테이너 기반의 서비스를 한다는 것은 기존 전통적인 방식대로 몇개 컨테이너 위에서 서비스를 구동하고 직접 유지보수하는 것이 아니라 수많은 컨테이너를 띄워놓고 Container Orchestration Tool 을 통해 수많은 컨테이너의 관리 및 제어를 하는 것을 의미하게 된다.

이를 통해 각종 리소스의 관리, 컨테이너 라이프사이클 관리 및 서비스 관리 전반을 포괄하는 Container Orchestrator 에 대해서는 반드시 알아야하는 필수 지식이 되게 된다. 컨테이너 오케스트레이터는 YAML, JSON 과 같은 설정 파일을 기반으로 컨테이너 클러스터를 서술하며 이를 통해 어플리케이션 환경, 네트워크 구성 방법, 로그 저장 방식 등 어플리케이션 전체 환경을 포괄하는 코드 파이프라인을 구성한다.

 

가장 유명한 서비스는 역시 구글의 Kubernetes(k8s) 이다. 사실상 컨테이너 오케스트레이션 툴의 스탠다드가 되어가고 있으며, 이를 클라우드 위에서 활용한다면 아마존의 EKS(Elastic Kubernetes Service) 등 위에서 매니지드 인프라를 통해 제공받게 된다.

 

쿠버네티스는 구글에서 시작되어 CNCF 재단에서 기증받아 운영되는 오픈소스 프로젝트로, 운영 환경의 기본 사상 자체가 모든 클러스터 환경의 관리를 kubectl 과 같은 CLI 를 통해 YAML 파일 형태로 관리하는 것을 추구한다. (실제로 수많은 컨테이너를 중앙 관리하려면 코드 없이 관리가 사실 상 불가능하다..)

 

쿠버네티스에서 컨테이너들은 일종의 클러스터(Cluster)를 구성하며 이는 노드들의 집합으로 이해하면 된다.

쿠버네티스는 위와 같이 제어부(Control Plane)와 데이터부(Data Plane)을 갖고 있으며, Control Plane 에서는 Worker Node 들과 Cluster 내의 Pod 들을 관리하고 제어하는 역할을 수행하고, 사용자가 제어할 수 있는 인터페이스를 API 서버 형태로 제공한다.

Data Plane 은 워커 노드(Worker Node)들로 구성되어 있으며 컨테이너화된 어플리케이션의 구성 요소인 파드(Pod)를 호스팅하게 된다.

 

데이터 플레인에는 Kube-proxy 라는 일종의 프록시 서버가 존재하는데, Data Plane 내에서 네트워크의 조작을 담당하며, 특히 각 Pod 가 Failover 될 수 있기 때문에 해당 부분에 대한 제어 등 Access 를 위한 엔드포인트로써 사용되어진다.

Data Plane 의 kubelet 은 컨테이너 제어를 위한 런타임 인터페이스로 초창기에는 Docker 에 종속적인 내부 모듈이었지만, 이제는 표준화된 런타임인 Container Runtime Interface(CRI) 를 기반으로 구성되어 컨테이너 관리를 위한 추상화된 계층 형태를 제공한다.

 

개발자 및 관리자는 Kubectl 이라는 쿠버네티스 API 명령어를 인터페이스로 k8s 클러스터의 컨트롤 플레인과 통신하며, 내부를 CLI 로 제어한다. 

 

 

기초적인 개념에 대한 1차 정리는 여기까지 마치고, 내부 구성 요소들에 대한 개념은 다음 포스팅에 정리합니다. :) 

 


Docker는 가상화 컨테이너에 Application 배포를 자동화시켜주는 오픈소스 엔진으로 마이크로서비스 아키텍처와 함께 각광받고 있는 엔진이다

서버 환경이 전통적인 온프레미스 환경에서 클라우드로 바뀌면서 가상서버를 손쉽게 늘리고 관리할 수 있게 되었지만 이에 따른 배포는 불편한 점이었다

Docker가 제공하는 경량화된 가상화 컨테이너 기술은 환경의 배포와 확장을 하는데 엄청난 이점을 제공해준다.


Docker 엔진은 다음과 같은 구성요소들로 이루어져 있다.


<출처 : https://docs.docker.com/engine/docker-overview/#docker-engine>


Docker 는 Container 와 Image 라는 개념으로 구성되며, Network 및 Data 와 같은 리소스들을 각 엔진별로 다룰 수 있고 이를 위한 인터페이스로 Docker 서버에서 REST API 를 제공한다.


 * Image

Docker의 이미지는 Docker 컨테이너를 만들기 위한 Read Only Layer이다. 각 Image 들은 Docker 엔진 위에서 다른 Image 들을 Base로 하는 Image Layer 를 구성하고 있기 때문에 여러 Image들을 재사용해서 새로운 Image를 빌드하는 것이 가능하다.


 * Container

컨테이너는 실행가능한 Docker 이미지를 말한다. 각 Container 들은 Host 및 다른 Container 들과 완전히 격리된 공간을 구성하며 Image 를 Base로 한 환경에서 격리된 공간의 리소스에 접근할 수 있게 구성되어 있다.


여기서 중요한 사실은, Container Hypervisor와 완전히 다른 개념이라는 것이다.


가상화를 목표한 다는점은 같지만, 하이퍼바이저가 OS 및 커널이 통째로 가상화되는 반면, Container FileSystem의 가상화만 이루어진다. Container Host PC의 커널을 공유하고, 따라서 init(1) 등의 프로세스가 떠있을 필요가 없으며, 가상화 프로그램과는 다르게 적은 메모리 사용량, 적은 Overhead를 보인다

많은 벤치마크 결과가 입증하듯 Container Host PC의 자원을 격리(Isolation)된 상태 그대로 활용하기 때문에 VM에 비해 성능 저하가 눈에 띄게 적다.



여기서 Docker 가상화를 위한 다음과 같은 기술들을 이해하는 것이 중요하다.


-  Namespace : 리눅스에서는 접속한 게스트 별로 독립적인 공간을 제공하고 서로가 충돌하지 않도록 리소스를 격리시키는 namespace 기능을 커널에 내장하고 있다. 일반적으로 Linux 커널에서 지원하는 6가지 namespace 는 다음과 같다.


(1)  Mnt(파일 시스템 마운트) : 호스트 파일시스템에 구애받지 않고 독립적으로 파일시스템을 마운트하거나 언마운트 가능


(2)  Pid(프로세스) : 독립적인 프로세스 공간을 할당


(3)  Net(네트워크) : namespace 간에 network 충돌을 방지 (중복 포트 바인딩 등을 방지)


(4)  Ipc(System IPC) : 프로세스 간의 독립적인 통신통로 할당


(5)  Uts(hostname) : 독립적인 hostname 할당


(6)  User(UID) : 독립적인 사용자 할당

 

namespace 를 지원하는 리눅스 커널을 사용한다면 다음 명령어를 통해 바로 namespace를 만들 수 있다.


> Sudo unshared –fork –pid –mount-proc bash


위와 같은 명령어를 통해 별도의 PID Namespace를 할당할 수 있고, bash pid 1로 할당할 수 있다. 독립된 공간을 할당한 뒤에는 nsenter 라는 명령어를 통해 접근할 수 있으며 Docker에서는 이 역할을 docker exec 라는 명령어가 대신한다.


 네트워크 관점의 namespace 에서 트래픽은 network namespace로 분산한 만큼 방화벽 룰셋이 줄어들며, 결과적으로 지연시간도 줄어든다. Network namespace에 해당하는 conntrack slab allocator를 통해 관리되는데 이 conntrack 도 줄어들게 되므로 자원의 효율이 보장된다.


- Cgroup(Control Groups) : Control Groups 는 자원에 대한 제어를 가능하게 해주는 리눅스 커널의 기능이다. Cgroup은 다음과 같은 리소스들을 제어할 수 있다.


(1)   메모리


(2)   CPU


(3)   I/O


(4)   네트워크


(5)   Device 노드(/dev/)


 만들어진 실행 프로세스들의 그룹은 계층구조를 가지며 시스템의 자원할당, 우선순위 지정, 거부, 관리, 모니터링 등의 제어기능을 수행하므로 자원의 효율성을 향상시킨다. 단순 그루핑을 제공하므로 실제 자원 분배를 위해서는 각 자원마다 해당하는 서브시스템이 필요하다.


- Union File System : Union FS 는 Docker 가 관리하는 각 Layer에서 각 컨테이너가 이용할 수 있는 독립된 파일 시스템 블록을 말한다. 이 FileSystem 은 리눅스 커널이 제공하는 것이 아니기 때문에 Linux 의 종류별로 다른 형태를 제공한다. 가령 Ubuntu 계열의 Linux 는 AUFS 라는 형태의 Storage Backend 를 제공하지만 Redhat 계열은 그렇지 않다.


- Container Format : Docker Engine 을 구성하는 핵심 기술 스택인 namespace, cgroup, UFS 는 컨테이너를 이용하기 위한 Container Wrapper 를 갖고 있으며 이를 맞추기 위한 Container Format 을 관리하게 된다. Default Container 는 libcontainer 를 이용한다.




 

도커(Docker)란 리눅스(Linux) 기반의 컨테이너 런타임 오픈소스로 가상화 기술을 이용한 경량화된 컨테이너를 통해 환경을 격리시켜주고 관리해주는 솔루션이다.




 VM처럼 Docker Engine이 Host 위에서 Container들을 가상화 시켜 관리해주며 이런 환경을 Image 화 함으로써 격리된 환경에서의 모든 어플리케이션들과 리소스들, 그 Dependencies를 전부 포함한 격리된 환경을 구성하고 구조할 수 있다.

(여기서 Host 라 함은 대부분의 OS를 말하고, 그 위에 새로운 환경을 만들어낸다고 생각하면 처음에 이해하기 쉽다. 쉽게 이해해서 OS 안에서 새로운 OS를 구축하는데 그 방법이 VM 보다 훨씬 더 가볍게 이루어진다는 뜻이다.)


여기서 운영체제의 가상화에 대해 간단히 언급하자면 기존의 하드웨어 Machine 에 OS를 탑제하는 것을 가장 간단한 형태의 가상화(Virtualization) 이라고 한다. 


조금 더 경량화된 방식이자, OS 위에서 가상 머신을 돌리기 위한 방법이 반가상화(Paravirtualization) 라 하여, Host OS 위에 Guest OS 형태로 OS 를 별도의 소프트웨어 처럼 동작시키는 방안이 있다. 대부분의 VM Software 들... Virtual Machine 이나 VM Ware 는 반가상화 방식이다.


Docker 는 반가상화 방식보다 경량화된 Container 를 이용하며, 이는 Guest OS 조차 필요없는 운영체제 레벨의 가상화를 구현한다. 그대신 OS 레벨에서의 지원이 필요하기 때문에 아직은 Linux 만 제공되고 있다.



 도커는 Linux 커널이 제공하는 컨테이너 기술(LXC)을 이용하며, 격리된 Container 에서 독립적 작업을 할 수 있게 추상화해준는데, 이 Container 들을 관리해주는 것이 바로 Docker Engine 이다.

(Docker 의 자세한 기술 스택은 추가로 포스팅 하겠다.)


 이렇게 이미지화 한 Container Image들은 Git의 VCS(Version Control System) 처럼 관리 및 배포할 수 있다.(Docker Hub) 이렇듯 설치 및 이용이 빠르고 협업에 있어 손쉬운 패키징이 가능한 장점이 있다. 

이러한 장점들 때문에 Cloud 환경에서 여러대의 서버를 대상으로 환경을 구축하는 것이 매우 편리하며, 각 Instance 에 대한 환경의 일관성이 보장되기 때문에 서버 인스턴스들에 대한 효율적인 모니터링이 가능하다.


 컨테이너들의 효율적인 배포 및 관리와 모니터링 등을 할 수 있게 해주는 것을 Container Orchestration 이라 하며, 이들은 컨테이너의 배치 및 복제, 컨테이너 그룹에 대한 로드밸런싱,  장애 복구(Fail Over), Scaling, Access Control 등의 기능을 갖는다. 다음과 같은 툴들이 대표적이다.





- Kubernetes : 구글에서 만들었으며 최근 각광 받고 있는 Orchestration Tool 이다. VM 환경, Public Cloud 등 다양한 환경에서 작동이 가능하며 손쉽게 접할 수 있도록 지원한다.


- Docker Swarm : 여러개의 Docker 호스트를 클러스터링 하여 단일 Docker Host 를 운영하는 방식이며, 설정 및 운용이 간편하다. 하지만 Kubernetes 만큼 다양한 기능을 제공하진 않는 것으로 보인다.


- Apache Mesos : 확장성이 뛰어나며 다른 아파치 재단의 Hadoop, Hypertable, Spark 와 같은 시스템과 연동하여 쓰기 좋게 되어있다. 



요즘 정말 많이 볼 수 있고, 많은 IT 트렌드 기술들이 Docker 를 응용하여 나은 성능과 효율성을 가져가고 있다. 이미 자리잡은 핵심 기술인 만큼 심도 있게 공부해둘 필요가 있다.



+ Recent posts