본문 바로가기
Google Cloud Platform

GKE(Google Kubernetes Engine)로 애플리케이션 관리하기 - 1부

by Roy Lee 2020. 6. 18.

컨테이너 이미지 빌드

GKE가 허용하는 배포 형식은 Docker 이미지이다.

그래서 GKE에 애플리케이션을 배포하려면 우선 애플리케이션을 Docker 이미지 형태로 만들어야 한다.

Docker 이미지를 빌드하려면 애플리케이션과 Dockerfile이 필요하다.

Dockerfile 부터 작성하자.

 

이 글에서는 Spring Boot 기반의 "Hello World"를 출력하는 RESTful API 서버 애플리케이션을 예시로 다루려고 한다. 해당 코드는 이곳에서 clone 받을 수 있다.

https://github.com/yongwoonyo/docker-springboot-hello-world

git clone https://github.com/yongwoonyo/docker-springboot-hello-world.git

git clone git@github.com:yongwoonyo/docker-springboot-hello-world.git

 

아래는 빌드는 maven으로 하고 Openjdk 8 버전에서 동작하는 애플리케이션이라는 가정으로 Dockerfile을 작성한 예이다.

FROM maven:3.5.2-jdk-8-alpine AS maven_build
COPY pom.xml /tmp/
COPY src /tmp/src/
WORKDIR /tmp/
RUN mvn package

FROM openjdk:8-jdk-alpine

CMD java -jar /data/docker-test-0.0.1-SAMPLE.jar
COPY --from=maven_build /tmp/target/docker-test-0.0.1-SAMPLE.jar /data/docker-test-0.0.1-SAMPLE.jar

EXPOSE 8080


MAINTAINER Roy Lee yongwoonyo@gmail.com

 

Google Kubernetes Engine은 이름에서 알 수 있듯이 Google Cloud Platform 상에 존재하는 서비스 이름이다. GCP 프로젝트 아이디는 커맨드라인에서 자주 사용하게 될 예정이므로 터미널에서 아래 커맨드를 수행하여 환경변수화 해두자.

export PROJECT_ID="당신의 GCP 프로젝트 아이디"

 

Dockerfile을 작성했으니 이제 Docker 이미지를 빌드할 수 있다.

docker build -t "gcr.io/$PROJECT_ID/docker-springboot-hello-world:v0.0.1" .

 

빌드한 이미지 목록은 다음 명령어로 확인할 수 있다. 정상적으로 빌드가 완료되었다면 위에서 빌드한 이름의 이미지가 목록에 보일 것이다. 

docker images -a

 

이제 만들어진 이미지를 Docker로 실행할 수 있다.

docker run -p 8080:8080 -it --rm gcr.io/$PROJECT_ID/docker-springboot-hello-world:v0.0.1

 

샘플 코드에는 root context의 “/” URL에 Get method type으로 “Hello World!” 문구를 리턴하는 RESTful API가 구현되어 있다. 간단하게 curl 명령어로 API가 동작하는지 확인해보자.

curl localhost:8080

컨테이너 이미지 업로드

이전 단계에서 빌드한 컨테이너 이미지를 레지스트리에 업로드해야 GKE가 다운로드 & 실행할 수 있다.

 

Docker config (/Users/roy/.docker/config.json) 파일에 인증 정보를 기록해서 추후 GCP 컨테이너 레지스트리에 인증할 때 사용할 수 있도록 한다.

gcloud auth configure-docker

 

자 그럼 인증할 수 있게 되었으니 컨테이너 레지스트리에 업로드 해보자.

docker push gcr.io/$PROJECT_ID/docker-springboot-hello-world:v0.0.1

컨테이너 클러스터 만들기

컨테이너 이미지를 실행할 클러스터를 만들자

여기서 말하는 클러스터는 GCE VM 인스턴스들로 이루어진 묶음을 말한다.

쿠버네티스를 통해 이 클러스터에 애플리케이션을 배포, 관리할 수 있다.

 

GCP Console에서 UI로도 할 수 있지만 CLI로 클러스터를 생성해보겠다.

 

클러스터를 이루는 GCE VM 인스턴스들에 대한 옵션을 먼저 설정하자.

gcloud config set project $PROJECT_ID

gcloud config set compute/zone asia-southeast1-c

 

hello-cluster 이름의, GCE 인스턴스 노드 2개로 구성된 클러스터를 만들자.

gcloud container clusters create hello-cluster --num-nodes=2

이 커맨드를 수행하면 GCE VM 인스턴스, 네트워크, pod 등을 구성한다.

애플리케이션 배포

컨테이너 클러스터가 완성되었다면 이제 클러스터에 애플리케이션을 배포해보자.

앞서 이야기했듯이 클러스터에 애플리케이션을 배포하는 것은 쿠버네티스를 통해서 수행한다.

 

앞서 만든 클러스터에 배포할 때는 다음 커맨드로 배포할 수 있다.

kubectl create deployment hello-world --image=gcr.io/${PROJECT_ID}/docker-springboot-hello-world:v0.0.1

 

실제 배포는 클러스터 내 pod 라는 공간에 배포된다. 보통 pod of blah 라고 하면 blah가 모여 있는 그룹을 의미한다. 여기서는 blah를 컨테이너라고 생각하면 쉽다. 즉, pod는 하나 이상의 컨테이너 그룹이라고 할 수 있다. 이 그룹은 스토리지와 네트워크를 공유한다. 컨테이너들은 IP주소와 포트 공간을 공유하고 서로를 localhost로 찾을 수 있다는 말이다. 요약해서 정리해보면, pod는 쿠버네티스에서 생성, 관리되는 그리고 배포 가능한 최소 컴퓨팅 단위이다. pod는 쿠버네티스 애플리케이션의 기본 실행 단위로, 배포의 단위가 된다.

그리고 도커는 쿠버네티스 파드에서 사용되는 대표적인 컨테이너 런타임이라고 생각하면 된다.

 

배포가 완료되면 다음 커맨드로 pod에 이미지가 잘 배포된 것을 알 수 있다. 

kubectl get pods

커맨드를 두번 수행했는데 위에서는 아직 컨테이너 생성 중이라 ready 되지 않은 것을, 그리고 아래에서는 컨테이너 생성을 마치고 running 중인 것을 즉, pod의 상태도 함께 알 수 있다.

pod에 배포가 잘 된 것까지 확인했으니 이제 애플리케이션을 인터넷에 노출시켜보자. 인터넷에 노출시켜서 동작 중인 것은 서비스라고 부른다.

kubectl expose deployment hello-world --type=LoadBalancer --port 8080 --target-port 8080

 

노출시킨 서비스는 kubectl get service 커맨드로 확인할 수 있다. external ip가 할당되기까지 시간이 좀 걸리는데 할당되기 전에는 pending 문구가 external ip 란에 출력된다.

 

external ip까지 할당이 되면 해당 ip 및 port 정보로 서비스가 동작하고 있는지 확인할 수 있다.

 

애플리케이션이 GKE pod에 정상적으로 올라갔음을 확인했다.

헌데 만약, 동일 클러스터에 애플리케이션을 추가로 띄워야 할 경우가 있을 수 있다.

클러스터에 여러 개의 애플리케이션을 배포하기

배포할 두번째 애플리케이션이 필요하다. 

두번째 애플리케이션은 다음과 같이 리턴하는 문자열만 바꾸는 수준으로 준비했다.

 

앞서 만든 클러스터에 두번째 애플리케이션을 배포하는 과정은 거의 대부분 선행한 것과 같다.

 

다른 애플리케이션에 대한 도커 이미지를 빌드하고

docker build -t "gcr.io/ss-tp-dev/docker-springboot-hello-world2:v0.0.1" .

 

빌드한 이미지를 컨테이너 레지스트리에 업로드한 다음

docker push gcr.io/$PROJECT_ID/docker-springboot-hello-world2:v0.0.1

 

클러스터는 만들어 놨으니 클러스터 생성 단계는 스킵하고 바로 배포를 진행한다.

kubectl create deployment hello-world2 --image=gcr.io/${PROJECT_ID}/docker-springboot-hello-world2:v0.0.1

 

그리고 웹 서비스로 노출시켜 주면

kubectl expose deployment hello-world2 --type=LoadBalancer --port 8080 --target-port 8080

 

다음과 같이 배포된 것을 알 수 있다.

kubectl get service

 

그리고 해당 서비스들에 접근해보면 애플리케이션1, 애플리케이션2 모두 정상 동작하고 있음을 확인할 수 있다.

그리고 pod 목록을 확인해보면 hello-world, hello-world2가 각기 다른 pod에 떠서 동작 중임을 알 수 있다.

kubectl get pods