SLASH 기술 블로그

쿠버네티스로 배포하기 1 - 어플리케이션 컨테이너화 본문

인프라/쿠버네티스

쿠버네티스로 배포하기 1 - 어플리케이션 컨테이너화

SLASH 2021. 5. 9. 18:03
반응형

1. How to containerize your app - 앱을 컨테이너화하는 방법에 대해 알아보자.

2. Running on Kubernetes Cluster - 쿠버네티스 클러스터에서 이미지 실행하기

3. Exposing the service - 서비스를 외부에 공개하기

4. Simplifying deployment process - 배포 과정 단순화하기

 

도커나 쿠버네티스를 배우고 실제로 활용을 하려고 할 때, 도커나 쿠버네티스의 개념이나 사용법 때문에 막히기보다, 실제로는 기존 어플리케이션을 어떻게 컨테이너화시켜야 하는지, 그리고 기존에 개발 환경 / 운영 환경을 나누어서 처리했던 방법들을 쿠버네티스로는 어떻게 관리해야하는지... 이렇게 놓치기 쉬운 부분들 때문에 막히는 것 같다.

 

튜토리얼과 문서를 따라하면서 이러한 부분 - 실무에서 쿠버네티스를 통해 어플리케이션을 배포할 때 신경써야할 것들 - 이 많이 다루어지지 않은 것 같아 개인적으로 조금 아쉬웠는데, 시리즈를 통해서 한 번 정리해보려고 한다.

 

우선 첫 번째로, 배포를 하기 위해 컨테이너화되어 있지 않은 앱을 컨테이너 위에 올릴 수 있게 만드는 방법에 대해 소개한다.

 

1단계: 도커 이미지 찾기

가장 먼저 필요한 작업은, 지금 내가 작업하고 있는 환경과 동일한 이미지(혹은 적어도 비슷한 이미지)를 찾는 일이다.

 

대개 Nodejs docker image, Python docker image 이런 식으로 개발 런타임 + docker image와 같은 식으로 검색하면 쉽게 찾을 수 있다. 대부분은 Docker Hub에서 찾을 수 있고, 요새는 GitHub Container Repository도 많이 쓰는 듯 하다.

 

도커 허브에 올라와있는 공식 Node 도커 이미지

 

이미지 목록을 보면 같은 버전인데도 태그가 많이 달려있는 걸 볼 수 있는데, 어플리케이션 개발을 하는 입장에서는 크게 중요한 건 아니다. 간단하게 설명을 하면, 버전 뒤에 붙은 alpine이라는 태그는 Alpine Linux를 지칭하는 말로, 우리가 잘 아는 Ubuntu나 CentOS같은 리눅스 배포판에 비해 용량이 작고 가벼워 컨테이너용 운영 체제로 많이 쓰인다고 한다.

 

같은 버전의 서로 다른 수 많은 태그들

 

나는 타입스크립트를 기반으로 하는 새로운 런타임인 Deno를 좀 써보고 싶어서 deno의 도커 이미지를 가져왔다. 이미지를 가져올 때는 docker pull 명령어를 사용한다. 알파인 리눅스에 Deno 1.9.2 버전이 설치되어 있는 이미지인 것 같다. 각자 환경에 따라 필요한 이미지를 내려받으면 된다.

docker pull hayd/alpine-deno:1.9.2

 

2단계: 도커에서 앱 실행하기

두 번째 단계는 자신의 운영체제에서 돌아가던 앱을 도커에서 돌리는 것이다. 이미지를 만들 때는 보통 Dockerfile을 사용하지만, 이미지를 만들기 전에 먼저 docker run 커맨드로 윤곽을 잡아보도록 하자.

 

도커에서 앱을 실행하기 위해서 필요한 건 다음의 세 가지다.

 

  1. 포트 설정
  2. 작업 디렉토리 설정
  3. 환경 변수 설정

포트 설정은 docker run-p 옵션을 통해서 줄 수 있다. 보통은 앱에서 사용할 포트를 지정할 때, 환경 변수를 통해 설정하는 경우가 많은데, 환경 변수는 마찬가지로 docker run-e 옵션을 통해 설정한다. 작업 디렉토리같은 경우 --volume 옵션을 통해 설정할 수 있다.

$ export PORT=8080
$ docker run --init -it \
  -p $PORT:$PORT \
  -e PORT=$PORT \
  --volume $PWD:/app
  hayd/alpine-deno:1.9.2 \
  run --allow-env --allow-net /app/app.ts

 

아래와 같이 함수를 만들어서 사용하면 훨씬 편하다. 마치 일반적인 명령어를 실행하는 것 같지만, 실제로는 도커 컨테이너를 띄우고 그 위에서 런타임을 실행하게 된다. 로컬에 개발 환경이 설정되어있지 않아도 곧바로 실행이 가능하다. (다만 이렇게 함수를 작성했을 때 포트를 설정할 수 없다는 문제가 있기는 함)

denod() {
  docker run \
    --init \               # init 프로세스를 컨테이너 내부에서 실행
    --interctive \         # 컨테이너의 STDIN을 열어둔다
    --tty \                # TTY 할당
    --rm \                 # 컨테이너가 존재할 경우 삭제
    --volume $PWD:/app \   # 현재 디렉토리를 컨테이너의 /app 디렉토리에 마운트
    --workdir /app \       # 컨테이너의 /app 디렉토리를 작업 디렉토리로 설정
    hayd/alpine-deno:1.9.2 # 사용할 이미지
    "$@"
}

 

3단계: Dockerfile 작성하기

컨테이너에서 앱을 돌려봤다면, 이제 이걸 이미지로 만들 차례다. docker run 명령어로 만든 컨테이너의 상태를 이미지로 저장하는 것도 가능하지만, 매 번 docker run을 통해서 컨테이너를 생성하는 것보다는 파일로 관리하는게 훨씬 편하니 Dockerfile을 작성해보자.

 

이전에 사용했던 명령들 대부분을 Dockerfile에서 사용할 수 있다. 간단하게 Dockerfile을 작성해보았다.

# 사용할 이미지 지정
FROM hayd/alpine-deno:1.9.2

# 빌드 시에 port를 인자로 받는다 (기본값: 80)
ARG port=80

# 환경 변수 설정
ENV PORT=$port

# 컨테이너 포트 개방 (문서화 용도로, 쓰지 않아도 문제 없다)
EXPOSE 8080
EXPOSE $port # 이런 식으로도 쓸 수 있다

# 작업 디렉토리 설정
WORKDIR /app

ADD . .

# 실행할 명령어를 리스트 형태로 기술
CMD ["run", "--allow-net", "--allow-env", "app.ts"]
CMD ["npm", "run", "start"] # Node라면 이런 형태

 

Dockerfile을 작성했다면 docker build 명령을 통해서 이미지를 만들 수 있다. 만든 이미지는 내려받았던 런타임 이미지와 동일하게 사용한다. 다만 이번에는 볼륨, 작업 디렉토리, 명령 등을 지정할 필요는 없다. (-p 옵션은 여전히 필요한데, 이 옵션은 포트 포워딩 옵션이기 때문에 컨테이너를 외부에서 접근하려면 반드시 필요하다)

$ export PORT=8080
$ docker build -t deno-app --build-arg port=$PORT .
$ docker run -it --init --rm -p $PORT:$PORT deno-app

 

사용하지 않는 컨테이너 / 이미지 삭제하기

이미지와 컨테이너를 여러 개 만들다보면, 사용하지 않는 컨테이너와 이미지가 남아있는 경우가 생긴다. 이럴 때는 prune 명령을 사용해서 사용하지 않는 리소스를 정리할 수 있다.

$ docker container prune
$ docker image prune

 

4단계: 이미지 배포하기

성공적으로 이미지를 생성했다! 이제 이미지를 허브나 레지스트리에 올려 쿠버네티스에서 사용할 수 있도록 해보자. 이미지를 업로드할 때 도커 허브나 GCR, GHCR 등을 사용할 수 있는데, 나는 GitHub Container Registry(GHCR)를 사용해보기로 했다.

 

GItHub 컨테이너 레지스트리를 설정하는 방법에 대한 내용은 44bits 블로그의 글을 참고하면 좋을 것 같다. 도커 이미지를 저장소에 올릴 때는 태그 앞에 저장소와 이름을 붙이면 된다.

$ docker tag deno-app ghcr.io/turastory/deno-app-test
$ docker push !$ # 이전 명령어의 마지막 인자 전달

 

GitHub 프로필의 패키지 탭을 보면 이미지가 잘 배포되어 있는 것을 확인할 수 있다.

 

성공적으로 배포가 되었다!


무척 기초적인 부분인데 도커를 배우다보면 실제로 적용해보지 않는 이상 이미지를 제작하는 과정을 제대로 이해하기 어렵다. 그래서 처음 앱을 컨테이너화했을 때 삽질을 많이 했다. 이 글을 읽는 여러분도 글을 읽으면서 궁금한 점들이 많이 떠오를텐데, 이 글에서 소개하는 단계들를 축으로 삼아 본인에게 필요한 것들을 하나하나 습득해가면 좋을 것 같다.

 

@turastory

반응형
Comments