개발/클라우드 엔지니어

2 컨테이너의 이해

새벽감성개발자 2024. 1. 16. 09:00
반응형

2.0 쿠버네티스를 위해 꼭 알아야 하는 지식

  • 개발 생산성이 좋아지는 대신에 application sotfware의 안정성을 유지하기 어려워진 것
  • 라이브러리의 버전이 바뀌면 API의 호환성이 깨지거나 새로운 버그가 잠재할 수도 있음
  • 도커는 이러한 문제를 컨테이너를 통해 해결
  • 오픈 소스를 사용한 개발 생산성 향상과 aplication 안정성 두가지를 잡음
  • 컨테이너화된 aplication을 운영하는 플랫폼 쿠버네티스도 일부 모듈이 컨테이너로 되어 있음
  • 도커와 관련된 기초 지식 중에서 쿠버네티스를 위해 필요한 부분을 중점적으로 살핌

2.1 컨테이너를 사용하는 이유

  1. 인프라의 사용률 향상
    • 하나의 물리 서버나 가상 서버 위에서 여러 개의 컨테이너를 돌릴 수 있음
    • CPU와 메모리 사용률을 높여 하드웨어를 효율적으로 이용
  2. 빠른 기동 시간
    • 컨테이너의 기동 시간은 가상 서버나 물리 서버의 기동 시간보다 훨씬 빠름
    • 운영체제, application, 미들웨어 등 다양한 이미지를 쉽게 얻음
    • 설치 작업이나 설정 작업이 줄어듦
    • 네트워크, 볼륨을 소프트웨어 정의 오브젝트로 작성 가능
  3. 불변 실행 환경(Immutable Infrastructure)
    • application 실행에 필요한 소프트웨어를 모두 포함하여 컨테이너를 작성할 수 있음
    • 컨테이너를 조합하여 시스템을 구성함으로서 특정 서버 환경에 대한 종속성을 배제할 수 있음
    • 개발 환경과 운영 환경의 차이를 줄일 수 있음

- 컨테이너는 가상 서버보다 우수한 application 실행 환경이라 여겨짐

2.2 가상 서버와 컨테이너의 차이점

  • 가상 서버 : 가상화 소프트웨어를 사용하여 하드웨어를 공유하는 형태,
    • 한대의 전용 서버가 있는 것 처럼 이용할 수 있게 해줌
    • 한 대의 머신에서도 여러 대의 가상 서버를 가동할 수 있어서, 하드웨어 구입이나 설치 관리 비용을 줄임
    • 하이퍼바이저(Hypervisor)라 부르며, VMware, Xen, KVM, 버추얼박스(VirtualBox), Hyper-V
  • 컨테이너 : 하나의 리눅스 프로세스가 전용 서버에서 동작하고 있는 것 같은 분리 상태
    • 리눅스 커널의 네임스페이스와 컨트롤 그룹(cgroup)이라는 기술을 기반으로 함

▲ 그림 1. 가상 서버와 컨테이너의 차이

  • 개발자들이 주로 사용하는 windows나 mac에서 컨테이너를 돌리려면 리눅스 커널을 위해 가상 서버가 필요함
    • Docker CE를 mac에나 windows에 설치하면 각각의 하이퍼바이저 위에서 linuxkit가 기동하여 컨테이너의 런타임인 containerd가 가동
    • linuxkit은 컨테이너를 실행하기 위한 경량의 리눅스 서브 시스템으로 도커(Docker), IBM. 리눅스 파운데이션, 마이크로소프트, ARM, 휴렛 패커드, 인텔과 같은 회사가 만듦

▲ 그림 2. 가상 서버와 컨테이너를 함께 사용하는 경우

 

2.3 도커의 아키텍처

  • 리눅스 커널이 제공하는 기능을 활용하면 도커가 아니라 자체적으로 컨테이너를 만드는 것도 가능
  • 도커는 소프트웨어 개발자가 컨테이너를 이용해 개발 생산성을 높일 수 있도록 BUILD/SHIP/RUN 기능 지원
    • Build(작성), Ship(이동), Run(실행)
  • 도커는 도커 데몬 서버와 클라이언트인 도커 커맨드, 이미지의 보관소인 레지스트리로 구성됨

▲ 그림 3. 도커의 아키텍처

1) 도커 데몬

  • 클라이언트인 도커 커맨드의 명령을 받아들여서 도커 오브젝트인 이미지, 컨테이너, 볼륨 네트워크 관리
  • 네트워크 너머에 있는 원격 클라이언트로 요청을 받는 것도 가능

2) 도커 클라이언트

  • 도커 커맨드는 컨테이너를 조작하는 커맨드 라인 유저 인터페이스
  • 도커 API를 사용하여 도커 데몬에 요청을 보냄
    • docker build : 베이스 이미지에 기능을 추가해 새로운 이미지를 만듦
    • docker pull : 레지스트리에서 이미지를 로컬에 다운로드할 때 사용
    • docker run : 이미지를 바탕으로 컨테이너를 실행
### 실행 중인 도커 컨테이너의 목록을 얻는 방법

docker ps
## 예전부터 있던 서브 커맨드
docker container ls
## 최신화가 되면서 대상이 되는 오브젝트 종류를 지정하고 동사를 배치하게 되었다.

3) 이미지

  • 이미지는 읽기 전용인 컨테이너의 템플릿(실행 파일과 설정 파일의 묶음)
  • 컨테이너를 실행하면 이미지에 담긴 미들웨어나 application 설정에 따라 기동
  • 도커 허브 : database, web server, applicaion 등의 이미지 등록
  • CI/CD도구인 젠킨스(Jenkins)도 도커 허브에 등록되어 있어 이미지를 다운받으면 특별한 설치 없이 젠킨스 서버로 바로 기동 가능

▲ 그림 4. 이미지의 이동과 실행

  • 대부분의 이미지는 다른 이미지에 기반하여 만들어짐
  • 웹서버인 Nginx의 컨테이너는 리눅스 배포판 중 데비안(Debian)에 기반하여 만들어짐
  • 이미지 만들 때 : 기반 이미지 + 설치 스크립트를 Dockerfile에 기재하여 빌드

▲ 그림 5. 도커 이미지를 빌드하는 순서

4) 컨테이너

  • 컨테이너는 하나의 프로세스
  • 리눅스의 네임스페이스나 컨트롤 그룹(cgroup)을 통해 다른 프로세스와 완전히 분리되어 실행되는 프로세스
  • 정지된 상태로도 관리되기 대문에 '실행 가능한 이미지의 인스턴스'
    • docker run : 이미지는 컨테이너로 변환되어 하나의 인스턴스가 됨
    • 실행상태의 컨테이너는 IP주소를 가지는 하나의 독립된 서버처럼 동작
    • 컨테이너의 IP주소와 포트번호로 온 요청은 컨테이너 내의 프로세스 로 연결
    • docker run 실행 시 다양한 옵션을 줄 수 있음
    • docker stop / docker kill 명령어를 통해 종료시킬 수 있다
    • docker start 명령어로 정지된 컨테이너를 시작하는 경우 IP주소가 할당되는데, 정지하기 이전의 IP주소는 아니다

▲ 그림6. 이미지와 컨테이너의 관계

5) 도커 레지스트리

  • 컨테이너의 이미지가 보관되는 곳
  • 도커는 기본적으로 도커 허브에 있는 이미지를 찾도록 석정
# 공개 레지스트리인 도커 허브에 등록된 이미지 hello-world를 다운받아서 컨테이너로 실행
docker run hello-world
  • 레지스트리 : 리포지스터리를 여러개 가지는 보관 서비스
  • 리포지스터리 : 하나의 이미지에 대해 태그를 사용해 다양한 출시 버전을 함께 보관

① 퍼블릭 레지스트리

  • 누구나 이용가능한 공개된 레지스트리
  • 도커 허브의 경우, 무료로 공개 리포지터리를 사용할 수 있음
  • git에 있는 Dockerfile이나 소스코드를 편집하여 push하면 자동으로 이미지를 빌드하고 리포지터리에 등록해주는 자동화 서비스도 있음
  • 컨테이너의 취약성을 검사하여 보고서를 제공하는 기능을 갖춘 레지스트리도 있음
  • 대표적인 공개 레지스트리
    • Docker Hub
    • Quay

② 클라우드 레지스트리

  • public cloud가 제공하는 레지스트리 서비스
  • 접근 가능한 계정을 제한하여 비공개로 운영가능 / 인터넷에 공개도 가능
  • 대표적인 클라우드 레지스트리
    • Amazon Elastic Container Registry
    • Azure Container Registry
    • Google Container Registry
    • IBM Colud container Registry

③ 비공개 레지스트리

  • 회사나 팀 전용으로 레지스트리를 구축하여 운영하는 경우
  • 오픈 소스로 이용할 수 잇는 레지스트리 소프트웨어
    • Harbor
    • GitLab
    • registry

 

2.4 레지스트리와 쿠버네티스의 관계

  • 쿠버네티스에서도 레지스트리에서 이미지를 다운로드 받아 컨테이너를 실행함
  • 동작 흐름
    1. docker build로 이미지를 빌드
    2. docker push로 이미지를 registry에 등록
    3. kubectl로 manifest에 기재한 오브젝트의 생성을 요청
    4. manifest에 기재된 repository에서 컨테이너의 이미지를 다운로드
    5. 컨테이너를 pod위에서 기동한다
  • registry는 쿠버네티스를 사용할 때 반드시 필요한 서비스

▲ 그림 7. 도커와 쿠버네티스를 연결하는 레지스트리의 역할

2.5 도커와 쿠버네티스의 연동

  • 쿠버네티스는 도커를 컨테이너의 런타임 환경으로 사용하기 때문에 쿠버네티스를 설치할 때 docker를 먼저 설치함
  • 도커 데몬 프로세스인 dockerd와 연동하여 동작하는 containerd 프로세스는 원래 도커 기업이 개발
  • 런타임 표준화를 위해 도커에서부터 CNCF(Cloud Native Computing Foundation)로 기증되어 개발
  • containerd는 다양한 플랫폼 위에서 동작하는 업계 표준 코어 컨테이너 런타임으로 간결하고 이식성을 목표로 개발
    • Docker CE 17.3에서 containerd 0.2.3이 도입
    • Docker CD 17.2에서 containerd 1.1 이 도입
  • [이미지 보관 및 전송, 컨테이너 실행, 볼륨과 같은 네트워크 연결] 컨테이너의 라이프 사이클을 호스트에서 전부 관리
  • conainerd 1.1 부터 CRI(Container Runtime Interface)에 대응하여 네이티브 kubelet 도 연동 가능

▲ 그림 8. 도커와 쿠버네티스의 연동

  • containerd는 OCI(Open Conatiner Initiative)의 표준 사양에 준하는 컨테이너 런타임(runC)를 사용
  • CRI를 통해 컨테이너 실행 요청을 받으면 containerd는 containerd-shim을 만든다
    •  shim이란? 틈을 메워서 높이나 수평을 맞추기 위한 끼움쇠를 의미, 여기서는 containerd와 runC의 틈을 메움
  • runC는 컨테이너를 띄운 후 바로 종료하며, 이어서 container-shim이 프로세스로 남음

 

  • 내부 표준화가 진행됨에 따라 쿠버네티스의 컨테이너 실행 환경은 도커 설치를 필수로 하지 않게 되어 심플하고 경량 고속화를 중점으로 발전해 나가고 있다.
  • 퍼블릭 클라우드의 쿠버네티스 관리 서비스와 상용 제품에서도 containerd와 kubelet이 직접 연계하는 방향으로 진행
  • IBM Cloud Kubernetes Service에서도 버전 1.11 이후에 도커를 이용하지 않음

 

2.6 컨테이너를 위한 기술과 표준

컨테이너를 구성하는 기반 기술

  1. 리눅스 표준 규격과 리눅스 ABI (Application Binary Interface)
    • 도커를 사용하면 다양한 리눅스 배포판을 기반으로 한 컨테이너 실행이 가능
    • ubuntu 18.04는 4.15[24, 25, 26]을 사용
    • docker CE(v16.01.0-ce)에서 리눅스 배포판을 실행하면 container의 커널은 4.9.93-linuxkit-aufs가 사용
    • 리눅스 배포판과 커널 버전이 달라도, LBS(Linux Base standard)는 소스코드를 컴파일한 시점에서 호환성 있는 머신코드를 생성하도록 ISO 규격으로 표준화됨
    • 리눅스 ABI에 인해 리눅스 커널의 버전이 올라가도 유저 공간에서 동작하는 바이너리(머신 코드) 레벨의 호환성이 유지됨
  2. 리눅스 커널 기술
    1. 네임스페이스( Namespace)
      • 리눅스 커널에 사용된 기술로 컨테이너가 하나의 독립된 서버와 같이 동작
      • 특정 프로세스를 다른 프로세스로부터 분리시켜 같은 네임스페이스 내에서만 접근 가능하게 제한
        • pid (Process ID) : 리눅스 커널의 프로세스 ID 분리
        • net (Networking) : 네트워크 인터페이스(NET) 관리
        • ipc (Inter Process Communication) : 프로세스 간 통신(IPC) 접근 관리
        • mnt (Mount) : 파일 시스템의 마운트 관리
        • uts (Unix Timesharing System) : 커널과 버전 식별자 분리
    2. 컨트롤 그룹(cgroup)
      • 도커는 리눅스 커널의 cgroup을 사용
      • 프로세스별로 CPU 시간이나 메모리 사용량과 같은 자원을 감시하고 제한
  3. 유니온 파일 시스템(UnionFS)
    • 다른 파일 시스템에서 파일이나 디렉터리를 투과적으로 겹쳐서 하나의 일관적인 파일 시스템으로 사용
    • 도커에서는 여러 구현체(aufs, burfs, overlay2) 중 하나를 선택
    • Docker CE 17.12부터는 overlay2가 사용됨
  4. OCI(Open Container Initiative)
    • 컨테이너의 표준 사양을 책정하기 위해 만들어진 단체

 

반응형