일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 배포자동화
- redis
- 자동화
- aws
- yarn-berry
- 도커
- 인프라
- 백엔드
- Atomic Design
- styled-components
- Kubernetes
- 예제
- backend
- 디렉토리이동
- methodreference
- Atomic Design 패턴으로 페이지 만들기
- 개발
- deployment
- GHCR
- 롱 폴링
- docker
- 스타일 컴포넌트
- Infra
- 리액트
- 캐시
- 쿠버네티스
- react
- 소켓IO
- 배포
- git-hooks
- Today
- Total
SLASH 기술 블로그
쿠버네티스로 배포하기 1 - 어플리케이션 컨테이너화 본문
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도 많이 쓰는 듯 하다.
이미지 목록을 보면 같은 버전인데도 태그가 많이 달려있는 걸 볼 수 있는데, 어플리케이션 개발을 하는 입장에서는 크게 중요한 건 아니다. 간단하게 설명을 하면, 버전 뒤에 붙은 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 커맨드로 윤곽을 잡아보도록 하자.
도커에서 앱을 실행하기 위해서 필요한 건 다음의 세 가지다.
- 포트 설정
- 작업 디렉토리 설정
- 환경 변수 설정
포트 설정은 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 프로필의 패키지 탭을 보면 이미지가 잘 배포되어 있는 것을 확인할 수 있다.
무척 기초적인 부분인데 도커를 배우다보면 실제로 적용해보지 않는 이상 이미지를 제작하는 과정을 제대로 이해하기 어렵다. 그래서 처음 앱을 컨테이너화했을 때 삽질을 많이 했다. 이 글을 읽는 여러분도 글을 읽으면서 궁금한 점들이 많이 떠오를텐데, 이 글에서 소개하는 단계들를 축으로 삼아 본인에게 필요한 것들을 하나하나 습득해가면 좋을 것 같다.
'인프라 > 쿠버네티스' 카테고리의 다른 글
Helm - 쿠버네티스의 패키지 매니저 (0) | 2021.06.21 |
---|---|
쿠버네티스로 배포하기 3 - 서비스 노출하기 (Ingress) (0) | 2021.05.30 |
쿠버네티스로 배포하기 2 - 쿠버네티스에 이미지 올리기 (0) | 2021.05.19 |
Kubernetes에서 GitHub Container Registry 사용 시 주의점 (0) | 2021.05.10 |
Kubernetes 개념 파악하기 (0) | 2021.04.30 |