Cloud Build를 사용한 GitOps 스타일 지속적 배포

이 페이지에서는 호스팅 제품 및 널리 사용되는 GitOps 방법론만 사용하여 Google Cloud Platform에 지속적 통합 및 배포(CI/CD) 파이프라인을 만드는 방법을 설명합니다.

오랫동안 Google의 엔지니어들은 구성 및 배포 파일을 Google의 기본 소스 코드 저장소에 보관해 왔습니다. 이 방법론은 Site Reliability Engineering, Chapter 8(Beyer et. al., 2016)에서 다루었으며 켈시 하이타워가 Google Cloud Next '17 키노트에서 시연한 바 있습니다. 'GitOps'라는 용어 자체는 Weaveworks에서 창안했습니다. GitOps의 핵심은 '코드로 표현한 환경', 즉 Git 저장소에 저장된 Kubernetes 매니페스트와 같은 파일을 사용하여 배포를 선언적으로 기술한다는 개념입니다.

이 가이드에서는 커밋된 코드로부터 컨테이너 이미지를 자동으로 빌드하는 CI/CD 파이프라인을 만들고, Container Registry에 이미지를 저장하고, Git 저장소의 Kubernetes 매니페스트를 업데이트하고, 이 매니페스트를 사용하여 애플리케이션을 Google Kubernetes Engine에 배포합니다.

CI/CD 파이프라인의 아키텍처

이 가이드에서는 두 개의 Git 저장소를 사용합니다.

  • app 저장소: 애플리케이션 자체의 소스 코드를 포함합니다.
  • env 저장소: Kubernetes 배포용 매니페스트를 포함합니다.

변경사항을 app 저장소에 푸시하면 Cloud Build 파이프라인이 테스트를 실행하고 컨테이너 이미지를 빌드하여 Container Registry에 푸시합니다. Cloud Build는 이미지를 푸시한 후 배포 매니페스트를 업데이트하여 env 저장소에 푸시합니다. 이때 다른 Cloud Build 파이프라인이 트리거되며, 이 파이프라인은 GKE 클러스터에 매니페스트를 적용하고 여기에 성공하면 env 저장소의 다른 브랜치에 매니페스트를 저장합니다.

appenv 저장소를 분리하는 이유는 수명 주기와 용도가 서로 다르기 때문입니다. app 저장소는 주 사용자가 실제 사람이며 특정 애플리케이션 전용입니다. env 저장소는 주 사용자가 Cloud Build 등의 자동화된 시스템이며 여러 애플리케이션에 공유될 수 있습니다. env 저장소는 각각 특정 환경에 매핑되는 여러 브랜치(이 가이드에서는 production만 사용)를 가질 수 있으며 특정 컨테이너 이미지를 참조하지만, app 저장소는 그렇지 않습니다.

이 가이드를 마치면 다음 작업을 손쉽게 처리할 수 있는 시스템이 구축됩니다.

  • Cloud Build 기록을 조회하여 배포 실패와 성공 구분
  • env 저장소의 production 브랜치를 조회하여 현재 사용 중인 매니페스트에 액세스
  • Cloud Build의 해당 빌드를 다시 실행하여 이전 버전으로 롤백

CI/CD 파이프라인의 흐름

이 가이드 정보

이 가이드에서는 Cloud Source Repositories를 사용하여 Git 저장소를 호스팅하지만 GitHub, Bitbucket, GitLab 등의 다른 타사 제품을 사용해도 같은 결과를 얻을 수 있습니다.

이 파이프라인은 배포 전 검증 메커니즘을 구현하지 않습니다. GitHub, Bitbucket 또는 GitLab을 사용하는 경우 파이프라인을 수정하여 pull 요청을 이 용도로 사용할 수 있습니다.

팀에서 Blue/Green, 카나리아 분석, 다중 클라우드 등의 고급 배포 패턴을 구현하려는 경우 Spinnaker가 권장되지만, 소규모 조직 및 프로젝트에서는 이러한 기능 세트 없이도 성공적으로 CI/CD 전략을 구현할 수 있습니다. 이 가이드에서는 간단한 도구와 함께 GKE에 호스팅된 애플리케이션에 적합한 CI/CD 파이프라인을 만드는 방법을 알아봅니다.

이 가이드에서는 편의상 env 저장소에서 단일 환경(production)만 사용하지만 필요한 경우 여러 환경으로 배포하도록 확장할 수 있습니다.

비용

시작하기 전에

  1. GCP 프로젝트를 선택하거나 만듭니다.

    리소스 관리 페이지로 이동

  2. 프로젝트에 결제를 사용 설정합니다.

    결제 사용 설정

  3. Cloud Shell을 열고 이 가이드에 나열된 명령어를 실행합니다.

    Cloud Shell로 이동

  4. gcloud config get-value project 명령어가 선택한 프로젝트의 ID를 반환하지 않는 경우 해당 프로젝트를 사용하도록 Cloud Shell을 구성합니다.

    gcloud config set project [PROJECT_ID]
    
  5. Cloud Shell에서 필요한 API를 사용 설정합니다.

    gcloud services enable container.googleapis.com \
        cloudbuild.googleapis.com \
        sourcerepo.googleapis.com \
        containeranalysis.googleapis.com
    
  6. Cloud Shell에서 이 가이드의 샘플 애플리케이션을 배포하는 데 사용할 GKE 클러스터를 만듭니다.

    gcloud container clusters create hello-cloudbuild \
        --num-nodes 1 --zone us-central1-b
    
  7. Cloud Shell에서 Git을 사용한 적이 없는 경우 내 이름과 이메일 주소를 사용하여 구성합니다. Git은 이러한 정보를 사용하여 Cloud Shell에서 만드는 커밋의 작성자를 식별합니다.

    git config --global user.email "[YOUR_EMAIL_ADDRESS]"
    git config --global user.name "[YOUR_NAME]"
    

이 가이드를 마치면 만든 리소스를 삭제하여 비용이 계속 청구되지 않도록 할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

Cloud Source Repositories에 Git 저장소 만들기

이 섹션에서는 이 가이드에 사용되는 두 개의 Git 저장소(appenv)를 만들고 app 저장소를 샘플 코드로 초기화합니다.

  1. Cloud Shell에서 두 개의 Git 저장소를 만듭니다.

    gcloud source repos create hello-cloudbuild-app
    gcloud source repos create hello-cloudbuild-env
    
  2. GitHub에서 샘플 코드를 복제합니다.

    cd ~
    git clone https://github.com/GoogleCloudPlatform/gke-gitops-tutorial-cloudbuild \
        hello-cloudbuild-app
    
  3. Cloud Source Repositories를 원격으로 구성합니다.

    cd ~/hello-cloudbuild-app
    PROJECT_ID=$(gcloud config get-value project)
    git remote add google \
        "https://source.developers.google.com/p/${PROJECT_ID}/r/hello-cloudbuild-app"
    

방금 복제한 코드는 간단한 'Hello World' 애플리케이션을 포함합니다.

from flask import Flask
app = Flask('hello-cloudbuild')

@app.route('/')
def hello():
  return "Hello World!\n"

if __name__ == '__main__':
  app.run(host = '0.0.0.0', port = 8080)

Cloud Build로 컨테이너 이미지 만들기

복제한 코드에는 다음 Dockerfile이 이미 포함되어 있습니다.

FROM python:3.7-slim
RUN pip install flask
WORKDIR /app
COPY app.py /app/app.py
ENTRYPOINT ["python"]
CMD ["/app/app.py"]

이 Dockerfile을 사용하면 Cloud Build로 컨테이너 이미지를 만들어 Container Registry에 저장할 수 있습니다.

  1. Cloud Shell에서 다음 명령어를 사용하여 최신 커밋에 따라 Cloud Build 빌드를 만듭니다.

    cd ~/hello-cloudbuild-app
    COMMIT_ID="$(git rev-parse --short=7 HEAD)"
    gcloud builds submit --tag="gcr.io/${PROJECT_ID}/hello-cloudbuild:${COMMIT_ID}" .
    

    이 명령어를 실행하면 Cloud Build는 컨테이너 이미지가 만들어질 때 생성되는 로그를 터미널에 스트리밍합니다.

  2. 빌드가 끝난 후 새 컨테이너 이미지를 Container Registry에서 사용할 수 있는지 확인합니다.

    Container Registry로 이동

    Container Registry의 hello-cloudbuild 이미지

지속적 통합 파이프라인

이 섹션에서는 소규모 단위 테스트를 자동으로 실행하고 컨테이너 이미지를 빌드하여 Container Registry에 푸시하도록 Cloud Build를 구성합니다. Cloud Source Repositories에 새 커밋을 푸시하면 이 파이프라인이 자동으로 트리거됩니다. 코드에 이미 포함된 cloudbuild.yaml 파일은 파이프라인의 구성입니다.

steps:
# This step runs the unit tests on the app
- name: 'python:3.7-slim'
  id: Test
  entrypoint: /bin/sh
  args:
  - -c
  - 'pip install flask && python test_app.py -v'

# This step builds the container image.
- name: 'gcr.io/cloud-builders/docker'
  id: Build
  args:
  - 'build'
  - '-t'
  - 'gcr.io/$PROJECT_ID/hello-cloudbuild:$SHORT_SHA'
  - '.'

# This step pushes the image to Container Registry
# The PROJECT_ID and SHORT_SHA variables are automatically
# replaced by Cloud Build.
- name: 'gcr.io/cloud-builders/docker'
  id: Push
  args:
  - 'push'
  - 'gcr.io/$PROJECT_ID/hello-cloudbuild:$SHORT_SHA'
  1. Cloud Build의 트리거 페이지를 엽니다.

    트리거로 이동

  2. 트리거 만들기를 클릭합니다.

  3. 'Cloud Source Repositories'를 소스로 선택하고 계속을 클릭합니다.

  4. hello-cloudbuild-app 저장소를 선택하고 계속을 클릭합니다.

  5. '트리거 설정' 화면에서 다음 매개변수를 입력합니다.

    • 이름: hello-cloudbuild
    • 브랜치(정규 표현식): master
    • 빌드 구성: cloudbuild.yaml
  6. 트리거 만들기를 클릭합니다.

    팁: 많은 프로젝트의 빌드 트리거를 만들어야 하는 경우에는 Build Triggers API를 사용하면 됩니다.

  7. Cloud Shell에서 애플리케이션 코드를 Cloud Source Repositories에 푸시하여 Cloud Build의 CI 파이프라인을 트리거합니다.

    cd ~/hello-cloudbuild-app
    git push google master
    
  8. Cloud Build 콘솔을 엽니다.

    Cloud Build로 이동

    빌드가 실행 중이거나 최근에 끝난 것으로 표시됩니다. 빌드를 클릭하면 실행 상태를 추적하고 로그를 조사할 수 있습니다.

지속적 배포 파이프라인 만들기

Cloud Build는 지속적 배포 파이프라인에도 사용됩니다. hello-cloudbuild-env 저장소의 candidate 브랜치에 커밋이 푸시될 때마다 파이프라인이 실행됩니다. 이 파이프라인은 Kubernetes 클러스터에 매니페스트의 새 버전을 적용하고, 여기에 성공하면 매니페스트를 production 브랜치에 복사합니다. 이 프로세스의 속성은 다음과 같습니다.

  • candidate 브랜치는 배포 시도 기록입니다.
  • production 브랜치는 배포 성공 기록입니다.
  • Cloud Build에서 배포 성공과 실패를 확인할 수 있습니다.
  • Cloud Build의 해당 빌드를 다시 실행하여 이전 배포로 롤백할 수 있습니다. 롤백하면 배포 기록을 정확히 반영하기 위해 production 브랜치도 업데이트됩니다.

이제 지속적 통합 파이프라인을 수정하여 hello-cloudbuild-env 저장소의 candidate 브랜치를 업데이트하고 지속적 배포 파이프라인을 트리거하겠습니다.

GKE에 Cloud Build 액세스 권한 부여

애플리케이션을 Kubernetes 클러스터에 배포하려면 Cloud Build에 Kubernetes Engine 개발자 IAM 역할이 필요합니다.

Shell

Cloud Shell에서 다음 명령어를 실행합니다.

PROJECT_NUMBER="$(gcloud projects describe ${PROJECT_ID} --format='get(projectNumber)')"
gcloud projects add-iam-policy-binding ${PROJECT_NUMBER} \
    --member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
    --role=roles/container.developer

Console

  1. Google Cloud Platform Console에서 Cloud Build 설정 페이지를 엽니다.

    Cloud Build 설정 페이지 열기

    서비스 계정 권한 페이지가 표시됩니다.

    서비스 계정 권한 페이지의 스크린샷

  2. Kubernetes Engine 개발자 역할의 상태를 사용 설정으로 설정합니다.

hello-cloudbuild-env 저장소 초기화

hello-cloudbuild-env 저장소를 두 개의 브랜치(productioncandidate) 및 배포 프로세스를 기술하는 Cloud Build 구성 파일로 초기화해야 합니다.

  1. Cloud Shell에서 hello-cloudbuild-env 저장소를 복제하고 production 브랜치를 만듭니다. 여전히 빈 상태입니다.

    cd ~
    gcloud source repos clone hello-cloudbuild-env
    cd ~/hello-cloudbuild-env
    git checkout -b production
    
  2. hello-cloudbuild-app 저장소에서 제공하는 cloudbuild-delivery.yaml 파일을 복사하고 변경사항을 커밋합니다.

    cd ~/hello-cloudbuild-env
    cp ~/hello-cloudbuild-app/cloudbuild-delivery.yaml ~/hello-cloudbuild-env/cloudbuild.yaml
    git add .
    git commit -m "Create cloudbuild.yaml for deployment"
    

    cloudbuild-delivery.yaml 파일은 Cloud Build에서 실행할 배포 프로세스를 기술합니다. 프로세스는 두 단계로 구성됩니다.

    1. Cloud Build가 GKE 클러스터에 매니페스트를 적용합니다.

    2. 여기에 성공하면 Cloud Build가 매니페스트를 production 브랜치에 복사합니다.

    steps:
    # This step deploys the new version of our container image
    # in the hello-cloudbuild Kubernetes Engine cluster.
    - name: 'gcr.io/cloud-builders/kubectl'
      id: Deploy
      args:
      - 'apply'
      - '-f'
      - 'kubernetes.yaml'
      env:
      - 'CLOUDSDK_COMPUTE_ZONE=us-central1-b'
      - 'CLOUDSDK_CONTAINER_CLUSTER=hello-cloudbuild'
    
    # This step copies the applied manifest to the production branch
    # The COMMIT_SHA variable is automatically
    # replaced by Cloud Build.
    - name: 'gcr.io/cloud-builders/git'
      id: Copy to production branch
      entrypoint: /bin/sh
      args:
      - '-c'
      - |
        set -x && \
        # Configure Git to create commits with Cloud Build's service account
        git config user.email $(gcloud auth list --filter=status:ACTIVE --format='value(account)') && \
        # Switch to the production branch and copy the kubernetes.yaml file from the candidate branch
        git fetch origin production && git checkout production && \
        git checkout $COMMIT_SHA kubernetes.yaml && \
        # Commit the kubernetes.yaml file with a descriptive commit message
        git commit -m "Manifest from commit $COMMIT_SHA
        $(git log --format=%B -n 1 $COMMIT_SHA)" && \
        # Push the changes back to Cloud Source Repository
        git push origin production

  3. candidate 브랜치를 만들고 두 브랜치를 푸시하여 Cloud Source Repositories에 제공합니다.

    git checkout -b candidate
    git push origin production
    git push origin candidate
    
  4. hello-cloudbuild-env 저장소의 Cloud Build 서비스 계정에 소스 저장소 작성자 IAM 역할을 부여합니다.

    PROJECT_NUMBER="$(gcloud projects describe ${PROJECT_ID} \
        --format='get(projectNumber)')"
    cat >/tmp/hello-cloudbuild-env-policy.yaml <<EOF
    bindings:
    - members:
      - serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com
      role: roles/source.writer
    EOF
    gcloud source repos set-iam-policy \
        hello-cloudbuild-env /tmp/hello-cloudbuild-env-policy.yaml
    

지속적 배포 파이프라인의 트리거 만들기

이 섹션에서는 hello-cloudbuild-env 저장소의 candidate 브랜치에 푸시할 때 Cloud Build가 트리거되도록 구성합니다.

  1. Cloud Build의 트리거 페이지를 엽니다.

    트리거로 이동

  2. 트리거 추가를 클릭합니다.

  3. 'Cloud Source Repositories'를 소스로 선택하고 계속을 클릭합니다.

  4. hello-cloudbuild-env 저장소를 선택하고 계속을 클릭합니다.

  5. '트리거 설정' 화면에서 다음 매개변수를 입력합니다.

    • 이름: hello-cloudbuild-deploy
    • 브랜치(정규 표현식): candidate
    • 빌드 구성: cloudbuild.yaml
  6. 트리거 만들기를 클릭합니다.

지속적 배포 파이프라인을 트리거하도록 지속적 통합 파이프라인 수정

이 섹션에서는 지속적 통합 파이프라인에 몇 단계를 추가하여 Kubernetes 매니페스트의 새 버전을 생성하고 hello-cloudbuild-env 저장소에 푸시하여 지속적 배포 파이프라인을 트리거합니다.

  1. 저장소에 대한 cloudbuild.yaml 파일의 확장된 버전을 복사합니다.

    cd ~/hello-cloudbuild-app
    cp cloudbuild-trigger-cd.yaml cloudbuild.yaml
    

    cloudbuild-trigger-cd.yamlcloudbuild.yaml 파일의 확장된 버전입니다. 이 파일은 새 Kubernetes 매니페스트를 생성하고 지속적 배포 파이프라인을 트리거하는 단계를 추가합니다.

    # This step clones the hello-cloudbuild-env repository
    - name: 'gcr.io/cloud-builders/gcloud'
      id: Clone env repository
      entrypoint: /bin/sh
      args:
      - '-c'
      - |
        gcloud source repos clone hello-cloudbuild-env && \
        cd hello-cloudbuild-env && \
        git checkout candidate && \
        git config user.email $(gcloud auth list --filter=status:ACTIVE --format='value(account)')
    
    # This step generates the new manifest
    - name: 'gcr.io/cloud-builders/gcloud'
      id: Generate manifest
      entrypoint: /bin/sh
      args:
      - '-c'
      - |
         sed "s/GOOGLE_CLOUD_PROJECT/${PROJECT_ID}/g" kubernetes.yaml.tpl | \
         sed "s/COMMIT_SHA/${SHORT_SHA}/g" > hello-cloudbuild-env/kubernetes.yaml
    
    # This step pushes the manifest back to hello-cloudbuild-env
    - name: 'gcr.io/cloud-builders/gcloud'
      id: Push manifest
      entrypoint: /bin/sh
      args:
      - '-c'
      - |
        set -x && \
        cd hello-cloudbuild-env && \
        git add kubernetes.yaml && \
        git commit -m "Deploying image gcr.io/${PROJECT_ID}/hello-cloudbuild:${SHORT_SHA}
        Built from commit ${COMMIT_SHA} of repository hello-cloudbuild-app
        Author: $(git log --format='%an <%ae>' -n 1 HEAD)" && \
        git push origin candidate
    

  2. 수정사항을 커밋하고 Cloud Source Repositories에 푸시합니다.

    cd ~/hello-cloudbuild-app
    git add cloudbuild.yaml
    git commit -m "Trigger CD pipeline"
    git push google master
    

    이렇게 하면 Cloud Build의 지속적 통합 파이프라인이 트리거됩니다.

  3. 지속적 통합 빌드를 조사합니다.

    Cloud Build로 이동

    hello-cloudbuild-app 저장소에서 빌드가 실행 중이거나 최근에 끝난 것으로 표시됩니다. 빌드를 클릭하면 실행 상태를 추적하고 로그를 조사할 수 있습니다. 이 파이프라인의 마지막 단계에서는 새 매니페스트를 hello-cloudbuild-env 저장소에 푸시하여 지속적 배포 파이프라인을 트리거합니다.

  4. 지속적 배포 빌드를 조사합니다.

    Cloud Build로 이동

    hello-cloudbuild-env 저장소에서 빌드가 실행 중이거나 최근에 끝난 것으로 표시됩니다. 빌드를 클릭하면 실행 상태를 추적하고 로그를 조사할 수 있습니다.

전체 파이프라인 테스트

이제 전체 CI/CD 파이프라인이 구성되었습니다. 이 섹션에서는 파이프라인을 처음부터 끝까지 테스트합니다.

  1. GKE 서비스 페이지로 이동합니다.

    Google Kubernetes Engine 서비스로 이동

    목록에 hello-cloudbuild라는 서비스 하나가 있어야 합니다. 이 서비스는 방금 실행된 지속적 배포 빌드에서 만든 것입니다.

  2. hello-cloudbuild 서비스의 엔드포인트를 클릭합니다. 'Hello World!'가 표시되어야 합니다. 엔드포인트가 없거나 부하 분산기 오류가 표시되는 경우 부하 분산기 초기화가 완료될 때까지 몇 분 정도 기다려야 할 수 있습니다. 필요한 경우 새로고침을 클릭하여 페이지를 업데이트합니다.

  3. Cloud Shell에서 애플리케이션 및 단위 테스트의 'Hello World'를 'Hello Cloud Build'로 바꿉니다.

    cd ~/hello-cloudbuild-app
    sed -i 's/Hello World/Hello Cloud Build/g' app.py
    sed -i 's/Hello World/Hello Cloud Build/g' test_app.py
    
  4. 변경사항을 커밋하고 Cloud Source Repositories에 푸시합니다.

    git add app.py test_app.py
    git commit -m "Hello Cloud Build"
    git push google master
    

    이렇게 하면 전체 CI/CD 파이프라인이 트리거됩니다.

  5. 몇 분 후에 브라우저에서 애플리케이션을 다시 로드합니다. 이제 'Hello Cloud Build!'가 표시됩니다.

롤백 테스트

이 섹션에서는 'Hello World!'를 표시하는 애플리케이션 버전으로 롤백합니다.

  1. hello-cloudbuild-env 저장소의 Cloud Build 콘솔을 엽니다.

    Cloud Build로 이동

  2. 사용 가능한 빌드 중에서 두 번째로 최신인 빌드를 클릭합니다.

  3. 다시 빌드를 클릭합니다.

  4. 빌드가 끝나면 브라우저에서 애플리케이션을 다시 로드합니다. 이제 'Hello World!'가 다시 표시됩니다.

삭제

이 가이드에서 사용한 리소스 비용이 Google Cloud Platform 계정에 청구되지 않도록 하는 방법은 다음과 같습니다.

  1. GCP Console에서 프로젝트 페이지로 이동합니다.

    프로젝트 페이지로 이동

  2. 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제 삭제를 클릭합니다.
  3. 대화상자에서 프로젝트 ID를 입력한 다음 종료를 클릭하여 프로젝트를 삭제합니다.

리소스 삭제

이 가이드에서 사용한 GCP 프로젝트를 보존하려는 경우 개별 리소스를 삭제합니다.

  1. 로컬 Git 저장소를 삭제합니다.

    cd ~
    rm -rf ~/hello-cloudbuild-app
    rm -rf ~/hello-cloudbuild-env
    
  2. Cloud Source Repositories의 Git 저장소를 삭제합니다.

    gcloud source repos delete hello-cloudbuild-app --quiet
    gcloud source repos delete hello-cloudbuild-env --quiet
    
  3. Cloud Build 트리거를 삭제합니다.

    1. Cloud Build의 트리거 페이지를 엽니다.

      트리거로 이동

    2. 각 트리거 옆의 세로로 나열된 세 개의 점을 클릭하고 삭제를 클릭합니다.

  4. Container Registry의 이미지를 삭제합니다.

    gcloud beta container images list-tags \
        gcr.io/${PROJECT_ID}/hello-cloudbuild \
        --format="value(tags)" | \
        xargs -I {} gcloud beta container images delete \
        --force-delete-tags --quiet \
        gcr.io/${PROJECT_ID}/hello-cloudbuild:{}
    
  5. GKE에 연결하도록 Cloud Build에 부여한 권한을 삭제합니다.

    PROJECT_NUMBER="$(gcloud projects describe ${PROJECT_ID} \
        --format='get(projectNumber)')"
    gcloud projects remove-iam-policy-binding ${PROJECT_NUMBER} \
        --member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
        --role=roles/container.developer
    
  6. GKE 클러스터를 삭제합니다.

    gcloud container clusters delete hello-cloudbuild \
        --zone us-central1-b
    

다음 단계

이 페이지가 도움이 되었나요? 평가를 부탁드립니다.

다음에 대한 의견 보내기...

Kubernetes Engine 가이드