컨테이너(Container) 기술이 가능한 이유
컨테이너(Container)를 가능하게 하는 요소들.
여는 글
와우. 오랜만입니다. 거의 한달만에 포스팅이네요. 작년 9월말에 부트캠프를 끝내고. 현재 1월까지. 너무나 많은 일들이 있었습니다. 그동안 있었던 일들을 늘어놓고 싶으나. 제 개인사를 궁금해 하시는 분들은 없겠죠 ㅎㅎ 바로 오늘 포스팅 시작하겠습니다.
컨테이너(Container)를 가능하게 하는 요소들
기억이 나실지 모르겠지만, 저저번 포스팅에선 컨테이너(Container) 동작 원리를 알아보았습니다. docker CLI
를 통해 컨테이너(Container)를 실행하는 명령어를 입력한다고 했을 때 CLI 도구는 Docker daemon
에 API 요청을 보냅니다. Docker daemon
은 컨테이너로 실행하고자 하는 image
가 local(VM) image cache
에 있는지 확인하고, 만약 없다면 ‘Docker Hub Registry’에서 가져옵니다. 그리고 나서image
를 컴퓨터에 다운로드한 후 Docker daemon
은 해당 이미지를 컨테이너를 실행합니다. 라는 복습을 잠시 해봤습니다.
컨테이너의 동작 원리를 알았으니 이제는 컨테이너 기술을 면밀히 살펴보려 합니다.
리눅스 네임스페이스(Linux Namespace)
컨테이너의 특징중에 컨테이너는 각각 독립된 환경에서 실행된다는 특징이 있습니다. 이를 가능하게 하는 기술이 리눅스 네임스페이스(Linux namespace)인데요. 리눅스 네임스페이스는 각 프로세스가 시스템의 독립적인 뷰를 갖게 해줍니다. 이는 컨테이너 내에서 실행되는 프로세스가 시스템상의 일부 파일, 프로세스, 네트워크 인터페이스만을 볼 수 있으며, 별도의 가상 머신에서 실행되는 것처럼 다른 시스템 호스트명을 가지게 해줍니다.
처음에는 리눅스 OS(Linux OS)에서 사용 가능한 모든 시스템 자원이 모든 프로세스가 보고 사용하는 같은 ‘네임스페이스(Namespace)’에 속해 있습니다. 커널은 추가 ‘네임스페이스(Namespace)’를 생성하고 자원을 그 안으로 이동시켜, 더 작은 세트로 구성할 수 있습니다. 이를 통해 각 세트를 오직 한 프로세스나 프로세스 그룹에만 보이도록 만들 수 있습니다. 새 프로세스를 생성할 때 사용할 네임스페이스를 지정할 수 있습니다.
요약하자면, 리눅스 네임스페이스는 각 프로세스에 대해 격리된 환경을 제공해주고, 이를 통해 프로세스는 필요한 자원만을 볼 수 있습니다. 이는 컨테이너가 각기 다른 환경을 가질 수 있도록 하는 요소 중 하나입니다.
네임스페이스 유형(Namesapce Type)
더 구체적으로, 각 리소스 타입마다 다양한 네임스페이스 타입이 존재합니다. 따라서 프로세스는 하나의 네임스페이스를 사용하는 것이 아니라, 각 타입에 대한 하나의 네임스페이스를 사용합니다.
타입 | 설명 |
---|---|
마운트 네임스페이스(mnt) | 마운트 지점(파일 시스템)을 격리합니다. |
프로세스 ID 네임스페이스(pid) | 프로세스 ID를 격리합니다. |
네트워크 네임스페이스(net) | 네트워크 장치, 스택,포트 등을 격리합니다. |
프로세스 간 통신 네임스페이스(ipc) | 프로세스 간의 통신을 격리합니다.(메시지 큐, 공유 메모리 등) |
UNIX 시분할 시스템(UTS)네임스페이스 | 시스템 호스트명과 네트워크 정보 서비스(NIS) 도메인 이름을 격리합니다. |
사용자 ID 네임스페이스(user) | 사용자 및 그룹 ID를 격리합니다. |
Cgroup 네임스페이스 | 컨트롤 그룹 루트 디렉토리를 격리합니다. |
네트워크 네임스페이스(Network Namespace)
프로세스가 실행되는 네트워크 네임스페이스에 따라 프로세스가 볼 수 있는 네트워크 인터페이스가 결정됩니다. 각 네트워크 인터페이스는 특정 네임스페이스에 속하며, 필요에 따라 다른 네임스페이로 이동시킬 수 있습니다. 만약 각 컨테이너가 고유한 네트워크 네임스페이스를 사용한다면, 컨테이너는 오직 자신에게 할당된 네트워크 인터페이스들만을 볼 수 있게 됩니다.
*그림 1.1
[그림1-1]을 보면 네트워크 네임스페이스를 이용하여 컨테이너를 어떻게 만드는지 알 수 있습니다. 컨테이너화된 프로세스를 실행하고자 할때, 이 프로세스에게는 오직 그 프로세스만 사용할 수 있는 독립된 네트워크 인터페이스 세트를 제공하고자 한다고 가정하겠습니다.
처음에는 기본 네트워크 네임스페이스만 존재합니다. 그 후, 컨테이너를 위한 두 개의 새로운 네트워크 인터페이스와 함께 새로운 네트워크 네임스페이스를 만듭니다. 이 인터페이스들은 필요에 따라 기존 네임스페이스에서 새로운 네임스페이스로 옮겨질 수 있으며, 이동 후에는 네임스페이스 안에서만 고유해야 하기 때문에 이름을 변경할 수 있습니다. 마지막으로, 이 네트워크 네임 스페이스 안에서 프로세스를 시작하여, 프로세스는 자신을 위해 만들어진 두 인터페이스만 인식하게 됩니다.
이러한 네트워크 네임스페이스의 격리 효과는 컨테이너와 같은 격리된 환경에서 프로세스가 실행될 때 그것이 실제 물리적 환경과 유사한 네트워크 환경을 갖게 해줍니다. 프로세스는 자신이 컨테이너 안에 있는지, 가상 머신 안에 있는지, 베어 메탈 하드웨어에서 직접 실행되는 운영 체제안에 있는지 구별할 수 없게 됩니다.
UNIX 시분할 시스템(UTS) 네임스페이스
프로세스가 자체 호스트에서 실행되는 것처럼 보이게 만드는 또 다른 방법은 UNIX 시분할 시스템(UTS)을 사용하는 것입니다. UTS 네임스페이스는 해당 네임스페이스 내에서 실행되는 프로세스가 인식하는 호스트명과 도메인 이름을결정합니다. 두 개의 서로 다른 프로세스에 다른 UTS 네임스페이스를 할당함으로써, 각 프로세스가 서로 다른 시스템 호스트명을 보게 할 수 있습니다. 이렇게 하면, 두 프로세스에게는 마치 두 대의 다른 컴퓨터에서 실행되고 있는 것처럼 보입니다.
네임스페이스가 프로세스를 서로 격리하는 방법 이해하기
모든 사용 가능한 네임스페이스 타임에 대해 전용 네임스페이스 인스턴스를 생성하고 이를 프로세스에 할당하면, 프로세스는 자신만의 운영 체제에서 실행되고 있다고 믿게 됩니다. 이는 각 프로세스가 독립적인 환경을 가지기 때문입니다. 프로세스는 자신이 속한 네임스페이스 내의 자원만 볼 수 있고 사용할 수 있으며, 다른 네임스페이스의 자원을 사용할 수 없습니다. 마찬가지로, 다른 프로세스들도 해당 프로세스의 자원을 사용할 수 없습니다. 이러한 방식으로 컨테이너는 내부에서 실행되는 프로세스들의 환경을 서로 격리합니다.
여러 프로세스간 네임스페이스 공유
컨테이너를 서로 완전히 격리시키지 않아야 할때가 있습니다. 관련된 컨테이너들이 특정 자원을 공유하고자 할 때인데요. 프로세스는 특정 자원을 공유하기를 원할 수도 있고, 다른 자원은 공유하고 싶지 않을 수도 있습니다. 이는 서로 다른 종류의 네임스페이스가 존재하기 때문에 가능한 것입니다. 각각의 네임스페이스 타입에 따라 프로세스는 자신만의 연관된 네임스페이스를 가질 수 있습니다.
정리
이렇게 컨테이너 기술을 간단히 살펴보았는데요. ‘컨테이너 안에서’ 실행되는 프로세스는, 가상 머신과 같이 물리적으로 구분된 공간 안에서 동작하는 것이 아닙니다. 실제로 컨테이너는 각각 다른 기능을 가진 7개의 네임스페이스(각 타입별로 하나씩)가 할당된 프로세스입니다. 이 중 일부 네임스페이스는 다른 프로세스와 공유되기도 하고, 일부는 독립적으로 사용됩니다. 이는 프로세스들 사이의 경계가 일정하지 않다는 것을 의미합니다.
닫는 글
오랜만에 3달전 글에 이어 포스팅을 해봤습니다. 앞으로 포스팅을 자주자주 해보도록 하겠습니다…그럼 이만.