Cloud 스터디 잼 코리아 Kubernetes Intm

2주차 - 02. 컨테이너 및 컨테이너 이미지

ziwookim 2022. 8. 26. 18:04

이미지 (Image)

애플리케이션과 종속항목을 '이미지' 라고 한다.

즉, 컨테이너는 실행 중인 '이미지 인스턴스' 이다.

소프트웨어를 컨테이너 이미지로 빌드하면 개발자는 손쉽게 애플리케이션을 패키징하고 제공할 수 있으며, 앱이 실행될 시스템에 대해서는 신경 쓰지 않아도 된다.

 

컨테이너

이미지를 빌드하고 실행하는데 필요한 소프트웨어

워크로드를 격리하는 기능을 제공한다.

대표적으로 Docker와 Kubernetes가 있다.

 

컨테이너는 다양한 리눅스 기술들을 이용한다.

  • Process - Linux 프로세스마다 서로 분리된 고유의 가상 메모리 주소 공간이 있고, Linux 프로세스는 빠르게 생성하고 삭제할 수 있다.
  • Linux namespaces - Linux 네임 스페이스를 사용하여 애플리케이션에 제공할 항목인 프로세스 ID 번호, 디렉토리 트리, IP 주소 등을 제어한다. (* 단, Linux 네임 스페이스와  Kubernetes 네임 스페이스는 동일하지 않다.)
  • cgroups - Linux cgrouop으로 애플리케이션이 사용할 수 있는 CPU 시간, 메모리, I/O 대역폭 기타 리소스의 최대 사용량을 제어한다.
  • Union file systems - 유니온 파일 시스템을 사용하여 애플리케이션가 종속 항목을 간결한 최소 레이어 모음으로 효율적으로 캡슐화한다.

 

컨테이너 이미지는 여러 레이어로 구조화 된다.

이미지 빌드에 사용하는 도구를 '컨테이너 매니페스트'(container manifest) 라는 파일에서 지침(instructions)을 읽어온다. Docker에서는 이를 'DockerFile' 이라고 한다. Dockerfile의 지침(instructions)에 따라 컨테이너 이미지 내부 레이어가 지정 된다.

각 레이어는 읽기 전용이다.

이 이미지에서 컨테이너를 실행하는 경우 쓰기 가능한 임시 최상위 레이어도 생성된다.

 

Dockerfile 살펴보기

1. FROM 문으로 기본 레이어를 공개 저장소에서 가져와 생성한다. (예시 그림에서는 특정 버전의 Ubuntu Linux 런타임 환경이 사용됨.)

 

02. COPY 명령어로 새 레이어를 추가한다. (예시 그림에서는 빌드 도구의 현재 디렉토리에서 복사한 파일이 포함되어 있다.)

 

03. RUN 명령어는 make 명령어를 사용하여 애플리케이션을 빌드하고, 빌드 결과를 3번째 레이어에 배치한다.

 

04. 마지막 레이어는 실행 시 컨테이너 내에 실행할 명령어를 지정한다.

 

Dockerfile을 작성할 때는 변경할 가능성이 가장 낮은 레이어 ~ 변경할 가능성이 가장 높은 레이어로 구성해야 한다.

최근에는 애플리케이션 패키징에서 다단계 빌드 프로세스를 이용하는데, 이 경우에 한 컨테이너에서 최종 실행 가능한 이미지를 빌드하고 다른 컨테이너에는 애플리케이션 실행에 필요한 항목만 포함한다. 

이미지에서 새 컨테이너를 만들면 컨테이너 런타임에서는 쓰기 가능한 레이어를 기본 레이어 위에 추가하는데, 이 레이어를 보통 '컨테이너 레이어' 라고 한다.

추가된 컨테이너 레이어

컨테이너 레이어 (Container Layer)

실행 중인 컨테이너에 대한 새 파일 쓰기, 기존 파일 수정 및 파일 삭제와 같은 모든 변경사항은 쓰기 가능하고 얇은 컨테이너 레이어에 기록된다. 이는 모두 임시 변경사항으로, 컨테이너가 삭제되면 컨테이너 레이어의 내용도 영구 삭제 된다. 반면에 기본 컨테이너(Base Image Layers) 이미지 자체는 변경되지 않은 상태로 유지된다. 즉, 데이터를 영구적으로 저장하고 싶다면 실행 중인 컨테이너 이미지가 아닌 다른 곳에서 작업해야 한다. 애플리케이션 설계 시, 이러한 컨테이너의 특징을 고려해야 한다.

 

컨테이너는 공유된 이미지들이 더 작아지게 한다. (Containers promote smaller shared images)

각 컨테이너에는 쓰기 가능한 고유의 컨테이너 레이어가 있고, 모든 변경사항이 이 레이어에 저장되므로 여러 컨테이너가 동일한 기본 이미지에 액세스 권한을 공유하면서도 자체 데이터 상태를 보유한다.

이 다이어그램은 여러 컨테이너에서 동일한 ubuntu 15.04 이미지를 공유하는 것을 보여준다. 각 레이어에는 이전의 레이어와는 다른 항목만 모여 있으므로, 이미지 크기가 더 작아진다. 

전체 이미지를 복사하는 대신 컨테이너를 빌드하는 경우, 다른 부분만 포함된 레이어를 생성한다. 컨테이너를 실행하면 컨테이너 런타임에서 필요한 레이어를 가져온다. 업데이트를 할 때는 다른 부분이 포함된 항목만 복사하면 된다. 그렇기 때문에, 가상 머신을 실행하는 것보다 훨씬 빠르다.

 

컨테이너를 어떻게 사용할 수 있을까?

Ubuntu 컨테이너 이미지는 컨테이너 내에서 Ubuntu Linux 환경을 제공한다.

자주 사용되는 컨테이너 내 Linux 환경으로는 Alpine이 매우 작은 크기로 널리 쓰인다.

NginX 웹 서버는 컨테이너 패키징에 자주 사용된다.

 

Google은 Container Registry인 gcr.io를 유지 관리 한다. 이 레지스트리에는 공개 오픈소스 이미지가 다수 포함되어 있으며, Google Cloud 고객도 이를 사용하여 비공개 이미지를 Cloud IAM과 잘 통합되므로, 공개되지 않은 이미지를 저장하는 데 사용할 수 있다. 이러한 이미지는 프로젝트 전용 비공개 이미지가 된다.

 

Docker 명령어는 고유 컨테이너 이미지 빌드 시 자주 쓰는 방법으로 널리 알려져 있고, 광범위하게 사용된다. Docker 명령어를 이용한 컨테이너 빌드 실행 시 단점으로는 꼭 신뢰할 수 있는 컴퓨터에서 빌드 해야한다는 점이다.

 

Cloud Build는 빌드에 필요한 소스 코드를 다양한 스토리지 위치에서 검색할 수 있다. Cloud Source Repositories Google Cloud의 객체 스토리지 서비스인 Cloud Storage 또는 Github, Bitbucket같은 Git 호환 저장소가 있다.  Cloud Build로 빌드를 생성하려면 일련의 '단계'를 정의해야 한다. 예를 들어, '종속 항목 가져오기 -> 소스 코드 컴파일 -> 통합 테스트 실행 or Docker Gradle and Maven 같은 툴을 사용하기' 와 같이 빌드 '단계'를 구성할 수 있다. 

Cloud Build의 각 빌드 단계는 Docker 컨테이너에서 실행된 후, Cloud Build 에서 새로 빌드한 이미지를 다양한 실행 환경에 제공할 수 있다. 이는 GKE는 물론, App Engine, Cloud Functions도 가능하다.