Docker란? (도커의 특징)

고리·2022년 8월 7일
0

Docker

목록 보기
2/8
post-thumbnail

운영 환경

이전 포스트에서는 서버의 관점에서 Docker의 등장을 지켜봤다. 이번 포스트 에서는 어플리케이션의 관점에서 Docker의 등장을 지켜보자.

우리가 어플리케이션을 구성해서 운영하는 환경은 기본적으로 3가지다.

  1. BareMetal: 물리 서버를 사내에 두고 사용하는 방식
  2. Vitualization: 가상화 기술, 가상머신을 사용하는 방식
  3. Container: 컨테이너 기술을 사용하는 방식

베어메탈? 베어메탈!

BareMetal 방식도 하드웨어 자원이 받쳐준다면 굳이 Vitualization을 사용하지 않고도 여러 어플리케이션을 운영할 수 있을까?

가능하다.

하지만 그렇게 하지 않았다. 왜 그럴까?

OS입장에서 우리가 구동하는 앱은 하나의 프로세스다. 만약 하나의 프로세스에 문제가 생기면? 모든 프로세스가 한정된 자원을 공유해서 사용하기 때문에 다른 프로세스에도 영향이 간다.
(가끔 작동안되는 프로그램을 강제 종료하려고 작업관리자를 키면 CPU 대부분을 점유하는 것을 확인할 수 있다)

하지만 가상화 환경에서는 문제가 생긴 OS에서 모든 일이 끝난다. 때문에 다른 OS에는 영향을 주지 않는 것이다. 그렇기에 가상머신이 각광받게 되었다.


가상머신? 가상머신!

하지만 가상머신도 여러 문제가 있었다.


위에는 방금 캡처한 작업 관리자 화면인데 크롭앱 하나만 실행하고 싶어도 기본적으로 백그라운드 프로세스가 60개를 훌쩍 넘는다. 대부분은 OS를 잘 실행하기 위한 것들인데 이러한 프로세스들이 하드웨어 자원을 차지해 많은 오버헤드가 생긴다.

OS실행은 HOST에게 맡기고 나는 프로세스만 독립적으로(다른 프로세스에게 영향을 안주고) 실행하고 싶은데 어떻게 가능할까?

바로 Docker를 통해서 가능하다.


컨테이너? 컨테이너!

도커 엔진만 깔려 있다면 어디든 OK!

어플리케이션을 구동하는데 필요한 런타임 환경만 컨테이너 안에 있으면 동작하기 때문에 불필요한 프로세스들이 하드웨어 자원을 잡아먹지 않는다.

뿐만아니라 개발환경에서 운영환경으로 운영환경을 확장한다면? 필요하다면 TA가 들어와 인프라를 구성하고 아키텍트가 들어와 서버 세팅을 해야한다. 여러 환경의 구성이 다 끝나야지 어플리케이션 배포를 할 수 있었지만 도커가 등장하면서 이미지파일 하나로 배포가 끝나버리는 황홀한 일이 생겨났다.


Docker의 특징

Docker is an open source platform for building, deploying, and managing containerized applications.

도커(Docker) 란 리눅스의 응용 프로그램들을 프로세스 격리 기술들을 사용해 컨테이너로 실행하고 관리하는 오픈소스 프로젝트이다.

도커는 다음과 같은 3가지 특징을 갖는다.

  1. 애플리케이션의 이미지화
  2. 프로세스간 격리
  3. 확장성/이식성.

이미지를 이해하기 전에 컨테이너(Container)에 대해 알 필요가 있다. 도커 공식 홈페이지는 Container를 다음과 같이 정의하고 있다.

Simply put, a container is a sandboxed process on your machine that is isolated from all other processes on the host machine.
That isolation leverages kernel namespaces and cgroups, features that have been in Linux for a long time.

Container는 host machine의 다른 모든 프로세스와 격리된 프로세스이며 이러한 격리는 Linux의 kernel 기능을 사용한다.

~~컨테이너에 대해서는 뒤에서 자세히 설명하겠다.
~~


격리(Isolation)

도커는 내부적으로 리눅스의 LXC 라이브러리를 사용하는데, LXC는 내부적으로 chroot, cgroup, namespace등 리눅스 API를 사용한다.

chroot (change root directory)

chroot는 파일 시스템을 격리해주는 기술이다. 컨테이너 별로 파일 시스템을 다르게 해 실행 가능한 명령어, 기능을 다르게 할 수 있다.

리눅스의 파일 시스템에는 / 라고 불리는 root directory가 존재한다. 파일 시스템의 최상위 디렉토리이며, 모든 디렉토리와 파일은 이 루트 디렉토리 아래에 존재한다.

root directory아래에 A, B, C파일이 있고 디렉토리A 안에는 다시 D, E 파일이 있다.

여기서 파일E를 찾기 위해서는 루트 디렉토리인 /를 기준으로 파일을 찾아야 한다.

/bin/bash 라는 프로세스를 /가 아닌 그 밑의 특정 디렉토리 /tmp/new를 루트디렉토리로 가지게 만들면 /bin/bash 프로세스는 /를 root로 가지는 다른 파일에 접근할 수 없게된다.

$ chroot /tmp/new /bin/bash
# /tmp/new_root 라는 루트 디렉토리를 사용해 /bin/bash 명령어를 실행

위와 같이 사용 되는데 docker 명령어도 비슷한 구조로 이루어져 있다.

$ docker run -i -t ubuntu /bin/bash
# ubuntu 이미지를 가져와 컨테이너를 시작하고 /bin/bash 명령어를 실행

/bin/bash는 보는 그대로 루트 디렉토리인 /bin/bash에 위치하기 때문에 다음의 명령어는 실행이 되지 않는다.

$ chroot /tmp/new /bin/bash

실행하기 위해서는 다음의 명령어로 /bin/bash를 /tmp/new/bin/bash로 복사하고 그에 필요한 의존성을 전부 가져올 필요가 있다.

$ mkdir -p /tmp/new/bin/
$  cp /bin/bash /tmp/new/bin/

ref


cgroup(control group)

cgroup은 프로세스에 대한 리소스의 제어를 가능하게 해주는 기능이다.
다음과 같이 프로세스 그룹 단위로 리소스 사용량을 제한하고 격리시킨다.


다음의 글을 kakao Tech팀의 프로세스 그룹과 컨테이너에 대한 설명이다.

_위의 예제는 Container와 Cgroup의 관계를 나타내고 있습니다. Container가 생성된다면 생성된 Container의 Process들을 담당하는 Container Cgroup이 생성됩니다.

모든 process가 Container Cgroup에 소속되기 때문에 Container의 Resource를 제어하기 위해서는 Container Cgroup을 제어하면 된다.


namespace

namespace는 chroot가 격리하지 않은 나머지를 격리해 준다.

  • mount: 호스트 파일 시스템에 구애받지 않고 독립적으로 파일 시스템을 마운트 하거나 언마운트 가능하게 한다. namespace안에서 수행한 마운트는 호스트 OS나 다른 namespace에서 엑세스 할 수 없다.

  • pid: 독립적인 프로세스 공간을 할당한다. namespace가 다른 프로세스끼리는 서로 엑세스할 수 없다.

  • net: namespace간에 network 충돌을 방지한다. 네트워크 디바이스, IP주소, 포트 번호, 라우팅 테이블, 필터링 테이블 등과 같은 네트워크 리소스를 격리된 namespace마다 독립적으로 가질 수 있다.

  • ipc: 프로세스 간의 독립적인 통신 통로를 할당한다.

  • uts: 독립적인 hostname 혹은 Domain name을 할당한다.

  • uid: 독립적인 사용자를 할당한다. UID, GID를 namespace별로 독립적으로 가질 수 있게 된다. 따라서 namespace안의 관리자 계정은 호스트 OS에 대해서는 관리 권한을 일절 갖지 않게 된다.

이렇게 Linux API를 활용해서 Container Isolation를 구현한다.


Container

도커의 공식 홈페이지에는 다음과 같이 적혀있다.

Container is a runnable instance of an image. You can create, start, stop, move, or delete a container using the DockerAPI or CLI.

image에 대한 실행가능 한 인스턴스란다..!

Container는 Image로 만들어 지는걸까?

지금부터 이미지에 대해 알아보자

공식 홈페이지가 가장 설명이 명확한 것 같다.

When running a container, it uses an isolated filesystem. This custom filesystem is provided by a container image. Since the image contains the container’s filesystem, it must contain everything needed to run an application - all dependencies, configuration, scripts, binaries, etc.

The image also contains other configuration for the container, such as environment variables, a default command to run, and other metadata.

이미지는 컨테이너의 파일 시스템이다. 애플리케이션 실행에 필요한 라이브러리와 바이너리, 기타 구성파일을 빌드한 단위로 컨테이너를 생성하고 실행하기 위한 모든 것이 들어있다.

바로 여기서 도커의 중요한 특징이 나온다. 도커는 Immutable Infrastructure Paradigm이란 개념을 기반으로 하는데, 명령어로 서버의 상태를 관리했던 이전과는 안정성, 확장성, 이식성 이 매우 높다.


안정성, 확장성, 이식성

서버는 시간이 지남에 따라 내용이나 설정이 수시로 변한다. 이전에는 변경, 추가, 삭제등 서버 상태에 변화가 필요하면 현재 서버에 직접 새로운 코드를 배포했다Mutable. 만약 100대의 서버를 명령어를 통해 작업한다면 서버의 환경이나 리소스 등의 차이로 몇대는 실패할 수 있다.

이러한 결과는 서비스의 안정성에 큰 영향을 미치며, 언제 누가 어떻게 변경했는지에 대한 관리가 어렵기 때문에 문제 발생시 추적이 굉장히 힘들다.

이러한 문제를 해결하기 위해 서버가 배포된 이후에는 수정이 절대 불가능한 Immutable한 인프라가 등장했다.

이러한 Immutable infrastructure 특징 때문에 서버의 안정성이 좋아졌고, 더 많은 리소스가 필요하다면 그때그때 정확히 동일한 서버를 배포할 수 있게 되어 확장성이 높아졌다. 뿐만 아니라 개발, 테스트, 운영 단계의 환경을 도커로 통일할 수 있고 어떤 환경이든 도커가 설치 되어 있다면 어디서든 컨테이너 실행이 가능해져 높은 이식성을 갖추게 되었다.

이렇게 도커가 너무 편리하다보니 많은 컨테이너를 운영하게 되고 각각의 컨테이너 하나가 하나의 서버를 운영하는 것과 동일한 비용이 들게 되었다. 따라서 유지보수 비용이 높아졌고 각각의 컨테이너를 따로 관리하는 것에 많은 제약이 붙이 시작했다.


이때 등장한게 도커의 짝꿍 쿠버네티스(KuberNetes)다.
쿠버네티스에 대해서는 이곳에 아주 간단히 정리해 두었다.

정리

  • 도커는 프로세스를 격리하는 기술이다.
  • 도커의 컨테이너는 도커 이미지를 사용해 chroot, cgroup, namespace 등 리눅스 커널의 격리 기술을 사용해 만들어진다.
  • 도커 이미지는 Dockerfile이라는 파일로 만들어 진다.
  • 도커 컨테이너가 많아지면 쉬운 관리를 위해 컨테이너 오케스트레이션 도구를 사용한다.

ref

https://docs.docker.com/get-started/
https://www.digitalocean.com/community/tutorials/what-is-immutable-infrastructure
https://tech.ssut.me/what-even-is-a-container/
https://medium.com/@paccattam/drooling-over-docker-1-the-genesis-d4e01ab8c6cf
https://tech.kakao.com/2020/06/29/cgroup-driver/
https://velog.io/@sa1341/Docker-등장-배경-및-명령어-정리
https://velog.io/@ragnarok_code/도커-컨테이너Container와-이미지Image란
https://velog.io/@gwak2837/chroot-실습
https://kubernetes.io/docs/home/

profile
Back-End Developer

0개의 댓글