컨테이너화된 웹 애플리케이션 배포

이 가이드에서는 웹 애플리케이션을 Docker 컨테이너 이미지에 패키징하고 Google Kubernetes Engine(GKE) 클러스터에서 이 컨테이너 이미지를 실행하는 방법을 설명합니다. 웹 애플리케이션을 사용자 니즈에 따라 확장 가능한 부하 분산된 복제본 세트로 배포합니다.

목표

  • 샘플 웹 애플리케이션을 Docker 이미지로 패키징합니다.
  • Container Registry에 Docker 이미지를 업로드합니다.
  • GKE 클러스터를 만듭니다.
  • 샘플 앱을 클러스터에 배포합니다.
  • 배포의 자동 확장을 관리합니다.
  • 샘플 앱을 인터넷에 노출합니다.
  • 샘플 앱의 새 버전을 배포합니다.

시작하기 전에

다음 단계에 따라 Kubernetes Engine API를 사용 설정합니다.
  1. Google Cloud Console에서 Kubernetes Engine 페이지로 이동합니다.
  2. 프로젝트를 만들거나 선택합니다.
  3. API 및 관련 서비스가 사용 설정될 때까지 기다립니다. 몇 분 정도 걸릴 수 있습니다.
  4. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다. 프로젝트에 결제가 사용 설정되어 있는지 확인하는 방법을 알아보세요.

옵션 A: Cloud Shell 사용

이 가이드에 사용되는 gcloud, docker, kubectl 명령줄 도구가 사전 설치되어 있는 Cloud Shell을 사용하여 이 가이드를 따르면 됩니다. Cloud Shell을 사용하는 경우 이러한 명령줄 도구를 워크스테이션에 설치할 필요가 없습니다.

Cloud Shell을 사용하려면 다음 안내를 따르세요.

  1. Google Cloud Console로 이동합니다.
  2. Cloud Console 창 상단의 Cloud Shell 활성화 셸 활성화 버튼 버튼을 클릭합니다.

    Cloud Console 하단의 새로운 프레임에서 Cloud Shell 세션이 열리고 명령줄 프롬프트가 표시됩니다.

    Cloud Shell 세션

옵션 B: 로컬에서 명령줄 도구 사용

워크스테이션에서 이 가이드를 수행하려면 다음 도구를 설치해야 합니다.

  1. gcloud 명령줄 도구가 포함된 Google Cloud SDK를 설치합니다.
  2. gcloud 명령줄 도구를 사용하여 Kubernetes 명령줄 도구를 설치합니다. kubectl은 GKE 클러스터의 클러스터 조정 시스템인 Kubernetes와 통신하는 데 사용됩니다.

    gcloud components install kubectl
  3. Docker Community Edition(CE)을 워크스테이션에 설치합니다. 이것은 애플리케이션의 컨테이너 이미지를 빌드하는 데 사용됩니다.

  4. Git 소스 제어 도구를 설치하여 GitHub에서 샘플 애플리케이션을 가져옵니다.

1단계: 컨테이너 이미지 빌드

이 가이드에서는 샘플 웹 애플리케이션hello-app을 배포합니다. 이 애플리케이션은 Go로 작성된 웹 서버로, 모든 요청에 대해 포트 8080에서 Hello, World!로 응답합니다.

GKE는 Docker 이미지를 애플리케이션 배포 형식으로 허용합니다. hello-app을 GKE에 배포하기 전에 먼저 hello-app 소스 코드를 Docker 이미지로 패키징해야 합니다.

Docker 이미지를 빌드하려면 소스 코드와 Dockerfile이 있어야 합니다. Dockerfile에는 이미지 빌드 방법에 대한 안내가 포함되어 있습니다.

  1. 다음 명령어를 실행하여 hello-app 소스 코드와 Dockerfile을 다운로드합니다.

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    cd kubernetes-engine-samples/hello-app
    
  2. PROJECT_ID 환경 변수를 Google Cloud 프로젝트 ID(project-id)로 설정합니다. PROJECT_ID 변수는 컨테이너 이미지를 프로젝트의 Container Registry와 연결하는 데 사용됩니다.

    export PROJECT_ID=project-id
    
  3. hello-app의 Docker 이미지를 빌드하고 태그를 지정합니다.

    docker build -t gcr.io/${PROJECT_ID}/hello-app:v1 .
    

    이 명령어는 현재 디렉터리에서 Dockerfile을 사용하여 이미지를 빌드하고 gcr.io/my-project/hello-app:v1과 같은 이름으로 태그를 지정하도록 Docker에 지시합니다. gcr.io 프리픽스는 이미지가 호스팅되는 Container Registry를 나타냅니다. 이 명령어를 실행해도 이미지는 아직 업로드되지 않습니다.

  4. docker images 명령어를 실행하여 빌드가 성공했는지 확인합니다.

    docker images
    
    출력:
    REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
    gcr.io/my-project/hello-app    v1                  25cfadb1bf28        10 seconds ago      54 MB
    

2단계: 컨테이너를 로컬로 실행(선택사항)

  1. 로컬 Docker 엔진을 사용하여 컨테이너 이미지를 테스트합니다.

    docker run --rm -p 8080:8080 gcr.io/${PROJECT_ID}/hello-app:v1
    
  2. Cloud Shell을 사용할 경우 웹 미리보기 버튼 웹 미리보기 버튼을 클릭한 후 8080 포트 번호를 선택합니다. GKE의 새로운 브라우저 창이 열리고 프록시 서비스의 미리보기 URL이 표시됩니다.

  3. 그렇지 않으면 새 터미널 창(또는 Cloud Shell 탭)을 열고 실행하여 컨테이너가 작동하고 'Hello, World!'로 요청에 응답하는지 확인합니다.

    curl http://localhost:8080

    성공적인 응답을 확인하면 docker run 명령어가 실행 중인 탭에서 Ctrl+C 키를 눌러 컨테이너를 종료할 수 있습니다.

3단계: Docker 이미지를 Container Registry로 푸시

GKE 클러스터가 컨테이너 이미지를 다운로드하고 실행할 수 있도록 레지스트리에 컨테이너 이미지를 업로드해야 합니다.

  1. Container Registry에 인증하도록 Docker 명령줄 도구를 구성합니다.

    gcloud auth configure-docker
    
  2. 방금 빌드한 Docker 이미지를 Container Registry로 푸시합니다.

    docker push gcr.io/${PROJECT_ID}/hello-app:v1
    

4단계: GKE 클러스터 만들기

이제 Docker 이미지가 Container Registry에 저장되었으므로 hello-app을 실행하려면 GKE 클러스터를 만들어야 합니다. GKE 클러스터는 GKE를 구동하는 오픈소스 클러스터 조정 시스템인 Kubernetes를 실행하는 Compute Engine VM 인스턴스의 풀로 구성됩니다.

Cloud Shell

  1. gcloud 도구의 프로젝트 IDCompute Engine 영역 옵션을 설정합니다.

    gcloud config set project $PROJECT_ID
    gcloud config set compute/zone compute-zone
  2. hello-cluster라는 클러스터를 만듭니다.

    gcloud container clusters create hello-cluster
    

    GKE 클러스터를 만들고 상태를 확인하는 데 몇 분 정도 걸립니다.

  3. 명령어가 완료된 후 다음 명령어를 실행하여 클러스터의 3개 작업자 VM 인스턴스를 확인합니다.

    gcloud compute instances list
    
    출력:
    NAME                                           ZONE        MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
    gke-hello-cluster-default-pool-d8b498d3-0d6r  us-east1-b   e2-medium                   10.142.0.4   35.237.4.149   RUNNING
    gke-hello-cluster-default-pool-d8b498d3-k29m  us-east1-b   e2-medium                   10.142.0.3   34.75.248.193  RUNNING
    gke-hello-cluster-default-pool-d8b498d3-vcrj  us-east1-b   e2-medium                   10.142.0.2   35.196.51.235  RUNNING
    

Console

  1. Cloud Console에서 Google Kubernetes Engine 메뉴로 이동합니다.

    Google Kubernetes Engine 메뉴로 이동

  2. 클러스터 만들기 버튼을 클릭합니다.

  3. 클러스터 기본사항 섹션에 hello-cluster라는 이름을 입력합니다.

  4. 드롭다운 메뉴에서 Compute Engine 영역을 선택하여 영역을 설정합니다.

  5. 만들기를 클릭합니다. 그러면 노드가 3개인 GKE 클러스터가 생성됩니다.

  6. 클러스터가 생성될 때까지 기다립니다. 클러스터가 준비되면 클러스터 이름 옆에 녹색 체크표시가 나타납니다.

5단계: 샘플 앱을 GKE에 배포

이제 빌드한 Docker 이미지를 GKE 클러스터에 배포할 준비가 되었습니다.

Kubernetes는 애플리케이션을 하나 이상의 컨테이너를 포함하는 확장 가능한 단위인 Pod로 나타냅니다. Pod는 Kubernetes에서 배포 가능한 최소 단위입니다. 일반적으로 Pod를 클러스터 전체에 걸쳐 함께 확장하고 배포할 수 있는 복제본 집합으로 배포합니다. 복제본 세트를 배포하는 한 가지 방법은 Kubernetes 배포를 사용하는 것입니다.

클러스터에서 hello-app을 실행하기 위한 Kubernetes 배포를 만듭니다. 이 배포에는 3개의 복제본(Pod)이 있습니다. 하나의 배포 Pod에는 하나의 컨테이너(hello-app Docker 이미지)만 포함됩니다. 또한 CPU 부하에 따라 Pod 수를 3개에서 1~5개로 확장하는 HorizontalPodAutoscaler 리소스를 만듭니다.

Cloud Shell

  1. hello-app Docker 이미지의 Kubernetes 배포를 만듭니다.

    kubectl create deployment hello-app --image=gcr.io/${PROJECT_ID}/hello-app:v1
    
  2. 배포 복제본의 기준 수를 3으로 설정합니다.

    kubectl scale deployment hello-app --replicas=3
    
  3. 배포에 대한 HorizontalPodAutoscaler 리소스를 만듭니다.

    kubectl autoscale deployment hello-app --cpu-percent=80 --min=1 --max=5
    
  4. 생성된 Pod를 보려면 다음 명령어를 실행합니다.

    kubectl get pods
    
    출력:
    NAME                         READY   STATUS    RESTARTS   AGE
    hello-app-784d7569bc-hgmpx   1/1     Running   0          10s
    hello-app-784d7569bc-jfkz5   1/1     Running   0          10s
    hello-app-784d7569bc-mnrrl   1/1     Running   0          15s
    

Console

  1. Cloud Console에서 Google Kubernetes Engine 워크로드 메뉴로 이동합니다.

    워크로드 메뉴로 이동

  2. 워크로드 메뉴에서 배포를 클릭합니다.

  3. 배포 만들기 창이 나타나면 기존 컨테이너 이미지를 클릭합니다.

  4. 드롭다운 메뉴를 사용하여 Container Registry로 푸시한 hello-app 이미지를 클릭합니다.

  5. YAML보기를 클릭합니다. 그러면 클러스터에 배포할 2개의 Kubernetes API 리소스를 나타내는 YAML 구성 파일(배포 1개, 해당 배포의 HorizontalPodAutoscaler 1개)이 열립니다.

  6. 배포를 클릭합니다.

  7. 배포 Pod가 준비될 때까지 기다립니다. GKE 클러스터가 3개의 hello-app Pod를 배포하면 파란색 바퀴가 돌아가고 Pod가 성공적으로 배포되면 녹색 체크표시가 나타납니다.

  8. Kubernetes Engine으로 이동한 후 워크로드로 이동하여 Pod가 준비될 때까지 기다립니다. hello-app을 클릭하고 관리형 Pod 섹션까지 아래로 스크롤합니다. 3개의 hello-app Pod가 표시됩니다.

6단계: 샘플 앱을 인터넷에 노출

Pod에는 개별적으로 할당된 IP 주소가 있지만 클러스터 내에서만 이러한 IP에 연결할 수 있습니다. 또한 GKE Pod는 확장 필요에 따라 임시 상태 유지, 가동을 증가 또는 축소하도록 설계되었습니다. 또한 오류로 인해 Pod가 다운되면 GKE는 해당 Pod를 자동으로 다시 배포하여 매번 새 Pod IP 주소를 할당합니다.

즉, 모든 배포에서 활성 Pod 집합에 해당하는 IP 주소 집합은 동적입니다. 1) Pod를 하나의 정적 호스트 이름으로 그룹화하고 2) 클러스터 외부의 Pod 그룹을 인터넷에 노출하는 방법이 필요합니다.

Kubernetes 서비스는 이 두 가지 문제를 해결합니다. 서비스 그룹 Pod는 클러스터 내의 모든 Pod에서 연결할 수 있는 하나의 고정 IP 주소로 그룹화됩니다. 또한 GKE는 고정 IP에 DNS 호스트 이름을 할당합니다(예: hello-app.default.svc.cluster.local).

GKE의 기본 서비스 유형을 ClusterIP라고 하며, 여기서 서비스는 클러스터 내부에서만 연결할 수 있는 IP 주소를 가져옵니다. 클러스터 외부에서 Kubernetes 서비스를 노출하려면 LoadBalancer 유형의 서비스를 만듭니다. 이 유형의 서비스는 인터넷을 통해 연결할 수 있는 Pod 집합의 외부 부하 분산기 IP를 생성합니다.

이제 LoadBalancer 유형의 서비스를 사용하여 hello-app 배포를 인터넷에 노출합니다.

Cloud Shell

  1. kubectl expose 명령어를 사용하여 hello-app 배포를 위한 Kubernetes 서비스를 생성합니다.

    kubectl expose deployment hello-app --name=hello-app-service --type=LoadBalancer --port 80 --target-port 8080
    

    여기에서 --port 플래그는 부하 분산기에 구성된 포트 번호를 지정하고 --target-port 플래그는 hello-app 컨테이너가 리슨하는 포트 번호를 지정합니다.

  2. 다음 명령어를 실행하여 hello-app-service의 서비스 세부정보를 가져옵니다.

    kubectl get service
    
    출력:
    NAME                 CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE
    hello-app-service    10.3.251.122    203.0.113.0     80:30877/TCP     10s
    
  3. EXTERNAL_IP 주소를 클립보드에 복사합니다(예: 203.0.113.0).

Console

  1. Cloud Console에서 Google Kubernetes Engine 워크로드 메뉴로 이동합니다.

    워크로드 메뉴로 이동

  2. hello-app을 클릭합니다.

  3. 배포 세부정보 페이지에서 노출을 클릭합니다.

  4. 배포 노출 메뉴에서 대상 포트8080으로 설정합니다. hello-app 컨테이너가 리슨하는 포트입니다.

  5. 노출을 클릭하여 hello-app-service라는 hello-app용 Kubernetes 서비스를 생성합니다.

  6. 외부 부하 분산기가 생성될 때까지 기다립니다. Google Cloud Console에 파란색 바퀴가 돌아가고 부하 분산기가 준비되면 hello-app-service의 서비스 세부정보 페이지로 리디렉션됩니다.

  7. 외부 엔드포인트 필드까지 아래로 스크롤하여 주소를 클립보드에 복사합니다.

이제 hello-app Pod가 Kubernetes 서비스를 통해 인터넷에 노출되었으므로 새 브라우저 탭을 열고 클립보드에 복사한 서비스 IP 주소로 이동할 수 있습니다. Hostname 필드와 함께 Hello, World! 메시지가 표시됩니다. Hostname은 브라우저에 HTTP 요청을 제공하는 3개의 hello-app Pod 중 하나에 해당합니다.

7단계: 새 버전의 샘플 앱 배포

이 섹션에서는 새 Docker 이미지를 빌드하고 GKE 클러스터에 배포하여 hello-app을 새 버전으로 업그레이드합니다.

GKE의 순차적 업데이트 기능을 사용하면 다운타임없이 배포를 업데이트할 수 있습니다. 순차적 업데이트 중에 GKE 클러스터는 기존 hello-app Pod를 새 버전의 Docker 이미지가 포함된 Pod로 점진적으로 대체합니다. 업데이트하는 동안 부하 분산기 서비스는 트래픽을 사용 가능한 Pod로만 라우팅합니다.

  1. hello 앱 소스 코드와 Dockerfile을 클론한 Cloud Shell로 돌아갑니다. main.go를 업데이트하여 새 버전의 hello-app 소스 코드를 만들고 새 버전인 2.0.0을 보고합니다.

  2. hello-app Docker 이미지를 빌드하고 태그를 지정합니다.

    docker build -t gcr.io/${PROJECT_ID}/hello-app:v2 .
    
  3. 이미지를 Container Registry로 내보내기

    docker push gcr.io/${PROJECT_ID}/hello-app:v2
    

이제 새 Docker 이미지를 사용하도록 hello-app Kubernetes 배포를 업데이트할 준비가 되었습니다.

Cloud Shell

  1. 이미지 업데이트로 순차적 업데이트를 기존 배포에 적용합니다.

    kubectl set image deployment/hello-app hello-app=gcr.io/${PROJECT_ID}/hello-app:v2
    
  2. v1 이미지를 실행하는 실행 중인 pod가 중지되고 v2 이미지를 실행하는 새 pod가 가동됩니다.

    watch kubectl get pods
    
    출력:
    NAME                        READY   STATUS    RESTARTS   AGE
    hello-app-89dc45f48-5bzqp   1/1     Running   0          2m42s
    hello-app-89dc45f48-scm66   1/1     Running   0          2m40s
    
  3. 별도의 탭에서 hello-app-service 외부 IP로 다시 이동합니다. 이제 Version2.0.0.로 설정됩니다.

Console

  1. Cloud Console에서 Google Kubernetes Engine 워크로드 메뉴로 이동합니다.

    워크로드 메뉴로 이동

  2. hello-app을 클릭합니다.

  3. 작업에서 순차적 업데이트를 클릭합니다.

  4. 표시되는 창에서 이미지 필드를 gcr.io/[YOUR_PROJECT_ID]/hello-app:v2로 설정합니다.

  5. 업데이트를 클릭하여 순차적 업데이트를 시작합니다.

  6. hello-app의 배포 보기로 돌아가서 활성 버전까지 아래로 스크롤합니다. 이제 두 가지 버전인 1과 2가 표시됩니다. 버전 1은 앞서 만든 초기 배포에 해당하며, 버전 2는 방금 시작한 순차적 업데이트입니다.

  7. 잠시 후 페이지를 새로고침합니다. 관리형 Pod에서 이제 hello-app의 모든 복제본이 버전 2에 해당합니다.

  8. 별도의 탭에서 hello-app-service 외부 IP로 다시 이동합니다. 이제 Version2.0.0.로 설정됩니다.

삭제

이 가이드에서 사용한 리소스 비용이 Google Cloud Platform 계정에 청구되지 않도록 하려면 다음 안내를 따르세요.

  1. 서비스 삭제: 서비스용으로 생성된 Cloud 부하 분산기를 할당 해제합니다.

    kubectl delete service hello-app-service
  2. 클러스터 삭제: 컴퓨팅 인스턴스, 디스크, 네트워크 리소스와 같이 클러스터를 구성하는 리소스를 삭제합니다.

    gcloud container clusters delete hello-cluster
  3. 컨테이너 이미지 삭제: Container Registry에 푸시한 Docker 이미지를 삭제합니다.

     gcloud container images delete gcr.io/${PROJECT_ID}/hello-app:v1  --force-delete-tags --quiet
    

다음 단계