1. 컨테이너란? 

  • 호스트 OS상에 논리적인 구획을 만들고 애플리케이션을 작동시키기 위해 필요한 라이브러리나 애플리케이션을 하나로 모아, 마치 별도의 서버인 것처럼 사용할 수 있게 만든 것

  • 호스트 OS의 리소스를 논리적으로 분리하고 오버헤드가 적기 때문에 고속으로 작동한다 

 

호스트형 서버 가상화

  • 위의 그림은 과거 많이 사용된 대표적인 가상화 툴인 virtual box의 구조이다. 
  • 사용해본 사람은 느꼈듯이 가상환경을 만들고 부팅을 진행하는데 꽤 시간이 소모된다
  • 각 가상 환경마다 각각의 OS를 가동하고 있기 때문에 overhead가 크다

 

컨테이너형 서버 가상화

  • 도커의 구조는 호스트 OS에 의존하는 형식이다. 
  • virtualbox가 초기 시작할 때 " 이 부분은 내 거야 " 하고 차지하고 시작하는 것과는 다르게 도커는 호스트와 대부분의 리소스를 공유한다
  • 호스트 OS의 사용자를 추가하는 느낌 

 

하이퍼바이저형 가상화

  • 호스트형 서버 가상화와 비슷한 모양이지만 호스트 OS가 빠지고 각각의 가상 환경에 OS가 있다. 
  • 호스트 OS없이 각 가상 환경마다 별도의 OS가 하드웨어를 직접 제어하기 때문에 자원을 효율적으로 사용할 수 있다. 
  • docker와는 지향하는 바가 다르다. 하이퍼바이저형은 서로 다른 환경을 어떻게 효율적으로 emulate 할지라는 점을 지향하고 있다

 

2. docker 개요

  • 애플리케이션의 이식성 - portability
    - 기존의 water fall형 개발방식에서는 애플리케이션 개발 환경과 테스트 환경, 실제 서비스 환경의 환경이 모두 달랐다. 그렇기에 각각의 과정마다 애플리케이션에 문제가 발생할 확률이 높았다
    - docker의 경우 docker file 형태로 환경을 구성하고 git 같은 CI를 이용하여 애플리케이션 개발부터 실제 서비스 환경까지 모두 같은 docker file을 이용하여 제작하므로 환경의 다름으로 인한 문제가 발생하지 않는다 
    - 이러한 환경의 제약이 많은 어플리케이션일수록 docker를 이용한 배포가 효과를 발휘한다 

 

3. docker의 기능 

  • Build - 이미지를 만드는 기능
    - 하나의 이미지는 하나의 어플리케이션을 넣어 두고 여러 개의 컨테이너를 조합하여 서비스 구축을 권장
    ( CentOS , Ubuntu, ......)
    - docker 이미지의 경우 명령어를 통해 수동으로 만들 수도 있지만 CI를 위하여 docker file형태로 작성하는 것을 권장한다 
    - docker는 이미지를 겹쳐서 새로운 이미지를 만들 수 있다 - docker는 각 이미지를 차분(이미지 레이어)로 관리하기 때문에 각각의 겹치는 부분에서 변경된 부분만을 가진다.
    - CentOS + MySQL(CentOS) = CentOS + MySQL
  • Ship - 이미지를 공유하는 기능 
    - docker 이미지는 docker 레지스트리에서 공유할 수 있다 
    docker 공식 레지스트리인 docker hub에서는 CentOS나 Ubuntu 같은 Linux배포판의 기본 기능을 제공하는 베이스 이미지를 배포하고 있다 
    - 이러한 베이스 이미지에 독자적인 MySQL이라던지 Jupyter 같은 독자적인 docker 이미지를 만들어 가는 것이다 
    - docker hub는 git과 연계할 수 있다. git hub 상에서 Docker file을 관리하고 거기서 Docker 이미지를 자동으로 생성하여 Docker Hub에서 공개하는 것도 가능하다 ( Automated Build )
  • Run - 컨테이너를 작동하는 기능
    - Docker의 경우 이미 움직이고 있는 OS 상에서 프로세스를 실행시키는 것과 거의 똑같은 속도로 빨리 실행시킬 수 있다 
    - Docker는 하나의 Linux 커널을 여러 개의 컨테이너에서 공유하고 있다 
    - 컨테이너 안에서 작동하는 프로세스를 하나의 그룹으로 관리하고 각 그룹마다 각각의 파일 시스템이나 호스트명, 네트워크를 할당하고 있다 
    - 그룹이 다르면 프로세스나 파일에 대한 액세스를 할 수 없다 
    - 위의 컨테이너의 독립을 위해 Linux의 커널 기능인 namespace, cgoups를 이용한다
    - docker component에는 Docker Engine, Docker Registry, Docker Compose, Docker Machine, Docker Swarm이 있다 각 기능은 추후 정리하겠다 

 4. Docker의 작동 구조 

  • 컨테이너를 구획화하는 장치 - namespace
    - 컨테이너를 구획화하는 장치는 Linux kernel의 namespace라는 기능을 사용한다 
    - 한 덩어리의 데이터에 이름을 붙여 분할함으로써 충돌 가능성을 줄이고, 쉽게 참조할 수 있게 하는 개념, 이름과 연결된 실체는 그 이름이 어떤 namespace에 속해 있는지 고유하게 정해진다 - namespace가 다르면 동일한 이름이라도 다른 실체로 처리된다 

    - namespace의 주된 기능 
    • PID namespace :
      Linux에서 각 프로세스에 할당된 고유한 PID(process ID)를 격리한다 - namespace가 다른 프로세스끼리는 서로 액세스 할 수 없다 
    • Network namespace :
      네트워크 디바이스, IP 주소, 포트 번호, 라우팅 테이블, 필터링 테이블 등과 같은 네트워크 리소스를 격리된 namespace마다 독립적으로 가질 수 있다 -
      - 호스트 OS상에 사용 중인 포트가 있더라도 컨테이너 안에서 동일한 번호의 포트를 사용할 수 있다 
    • UID namespace : 
      사용자 ID와 그룹 ID를 namespace 별로 독립적으로 가질 수 있다 
      - 컨테이너 안의 UID/GID가 0인 root 사용자를 호스트 OS 상에서는 일반 사용자로서 취급할 수 있다 
      - namespace 안의 root 계정은 호스트 OS에 대해서는 관리 권한을 일절 갖지 않는다 - 보안적 요소
    • MOUNT namespace :
      MOUNT namespace에 격리된 파일 시스템 트리를 만든다 마찬가지로 namespace 안에서 수행한 마운트는 호스트 OS나 다른 namespace에 액세스 할 수 없다 
    • UTS namespace : 
      namespace별로 호스트명이나 도메인명을 독자적으로 가질 수 있다 
    • IPC namespace : 
      프로세스 간의 통신(IPC - Inter-Process Communication - 공유 메모리, 세마포어/메시지 큐) 오브젝트를  namespace별로 독립적으로 가질 수 있다 ( 세마포어 - Semaphore - 자원관리에 이용되는 배타 제어장치 - 공유 자원의 개수 변수)
  • 릴리즈 관리 장치 - cgroups 
    - Docker는 물리 머신 상의 자원을 여러 컨테이너가 공유하며 작동함 이때 Linux kernel 기능인 control grouos 기능을 사용하여 자원의 할당 등을 관리함 
    • cgroups는 프로세스와 스레드를 그룹화하여 그 그룹 안에 존재하는 프로세스와 스레드에 대한 관리를 수행하기 위한 기능 
      - 호스트 OS의 CPU나 메모리와 같은 자원에 대해 그룹별로 제한을 둘 수 있음 
      - cgroups로 컨테이너 안의 프로세스에 대해 자원을 제한함으로써 예를 들면 어떤 컨테이너가 호스트 OS의 자원을 모두 사용해 버려서 동일한 호스트 OS상에서 가동되는 다른 컨테이너에 영향을 주는 일을 막을 수 있다 
      - 관리 가능한 영역 :
      1. cpu : CPU 사용량 제한
      2. cpuacct : CPU 사용량 통계 정보를 제공 
      3. cpuset : CPU나 메모리 배치를 제어
      4. memory : 메모리나 스왑 사용량을 제한 
      5. devices : 디바이스에 대한 액세스 허가/ 거부 
      6. freezer : 그룹에 속한 프로세스 정지/재개
      7. net_cls : 네트워크 제어 태그를 부가 
      8. blkio : 블록 디바이스 입출력량 제어 
    • cgroups는 부모 자식 관계에서는 자식이 부모의 제한을 물려받는다 
      - 자식이 부모의 제한을 초과하는 설정을 하더라도 부모 cgroups의 제한에 걸린다 
  • 네트워크 구성 
    - Linux는 Docker를 설치하면 서버의 물리 NIC가 docker0이라는 가상 브리지 네트워크로 연결된다 
    - 컨테이너가 실행되면 172,17.0.0/16이라는 서브넷 마스크를 가진 private IP 주소가 eth0로 자동으로 할당된다  OSI 2 계층인 네트워크 인터페이스로 pair인 NIC와 터널링 통신을 한다 
    - docker0이라는 가상 브리지 네트워크와 호스트 OS의 물리 NIC에서 패킷을 전송할 때는 NAPT기능을 사용한다 
    • NAPT - Network Address Port Translation
      - 하나의 IP주소를 여러 컴퓨터가 공유하는 기술 - IP주소와 포트 번호를 변환하는 기능 
      - TCP/IP의 포트 번호까지 동적으로 변환하기 때문에 하나의 글로벌 IP 주소로 여러 대의 머신이 동시에 연결할 수 있다 
      - Docker에서는 NAPT에 Linux의 iptables를 사용한다 
    • NAT(Network Address Translation)와 NAPT의 차이점 
      - NAT라우터는 클라이언트의 private IP를 NAT가 가지고 있는 public IP로 변환하여 요청을 송신한다 응답은 NAT라우터가 송신처를 클라이언트의 private IP 주소로 변환하여 송신한다 
      - 이러한 주소 변환은 public IP와 private IP를 1:1로 변환하기 때문에 동시에 여러 클라이언트가 액세스 할 수 없다 
      - NAPT는 private IP와 함께 포트 번호도 같이 변환한다 
      - private IP를 public IP로 변환할 때 private IP 별로 서로 다른 public IP:포트번호로 변환한다 
      - 201.xxx.xxx.xxx:1500 = A 가상 머신 , 201.xxx.xxx.xxx:1600 = B 가상 머신 
      - 이로써 하나의 public IP와 여러 개의 private IP를 변환할 수 있다 
      - Linux에서 NAPT를 구축하는 것을 IP Masquerade라고 부른다 
  • Docker 이미지의 데이터 관리 장치 
    - 어떤 데이터를 복사할 필요가 생겼을 때 새로운 빈 영역을 확보하고 거기에 복사를 한다 
    하지만 만일 복사한 데이터에 변경이 없다면 A=B이면 그 복사는 쓸데없는 것이 된다 
    그래서 복사를 요구받아도 바로 복사하지 않고 원래의 데이터를 그대로 참조시켜 원본 또는 복사 어느 쪽에 수정이 가해진 시점에 비로소 새로운 빈 영역을 확보하고 데이터를 복사한다 
    이러한 장치를 Copy on Write라고 부른다 Docker에서는 Copy on Write 방식으로 컨테이너의 이미지를 관리한다 
    - Docker의 이미지를 관리하는 스토리지 디바이스로는 다음과 같은 것이 있다 
    1. AUFS : 다른 파일 시스템의 파일이나 디렉터리를 투과적으로 겹쳐서 하나의 파일 트리 구성, 표준 Linux kernel 아님 
    2. Btrfs : Linux용 Copy on Write 파일 시스템 - 롤백, snapshot 기능 
    3. Device Mapper : 파일 시스템의 블록 I/O와 디바이스의 mapping관계를 관리 - thin-provisioning, snapshot - Red Hat OS나 Ubuntu 등에서 Docker를 이용할 때 사용 
    4. OverlayFS : 파일 시스템에 다른 파일 시스템을 투과적으로 merging 하는 기능 
    5. ZFS : 볼륨 관리, snapshot, check sum, replication 등을 지원 

 

위의 개념들은 추후 각 기능을 사용할 때 어떤 방식으로 컨테이너가 생성되는지를 이해하기 위해 필요하다 

특히 docker run의 파라미터를 이해하는데 필요하다 

 

'infra > docker' 카테고리의 다른 글

(3) docker - 기본 명령어  (0) 2021.09.09
(1) docker - 인프라 기초  (0) 2021.08.25

+ Recent posts