Concourse를 사용하여 Kubernetes Engine에서 Helm 차트를 지속적으로 배포

이 가이드에서는 GKE, Helm, Concourse를 사용하여 소프트웨어 출시 프로세스를 만드는 방법을 보여줍니다. Helm은 Kubernetes 매니페스트를 관리하는 데 유용한 도구입니다. Concourse는 Helm을 활용해 지속적으로 애플리케이션을 배포합니다.

이 가이드를 따르면 다음과 같은 결과를 얻을 수 있습니다.

  • 애플리케이션 소스 코드 한 개와 Helm 차트를 위한 코드 한 개 등 소스 코드 저장소 두 개
  • Docker 컨테이너로 패키지화되고 클러스터에서 Helm 차트로 설치 및 구성된 애플리케이션

두 저장소 중 하나로 Git 태그를 푸시해 출시를 시작할 수 있습니다.

아키텍처

다음 다이어그램은 높은 수준의 시스템 아키텍처를 대략적으로 보여줍니다.

고수준 아키텍처

Concourse는 프로세스를 빌드, 테스트, 출시하는 단계를 코드화하는 데 사용할 수 있는 지속적 배포 파이프라인을 어셈블합니다. Concourse에서 파이프라인의 단계를 작업이라 합니다. 각 작업은 입력으로 리소스를 취하고, 출력으로 리소스를 만들 수 있습니다.

이 가이드에서는 다음과 같은 Concourse 리소스 유형을 사용합니다.

Helm을 사용하여 Kubernetes 매니페스트를 템플릿으로 만든 후 하나의 단위로 구성, 설치, 업그레이드할 수 있습니다. 애플리케이션을 설치하기 위해서는 애플리케이션을 Helm 차트로 정의해야 합니다. 각 Helm 차트에는 매니페스트를 매개변수화하는 데 사용할 수 있는 값 파일이 있습니다. 예를 들어, 애플리케이션 배포에 사용할 Docker 이미지를 정의하는 값이 있을 수 있습니다. 이 값은 차트를 설치 또는 업그레이드할 때마다 변경될 수 있습니다. 각 차트 설치출시라고 합니다. 출시를 사용하여 애플리케이션의 인스턴스를 업그레이드 또는 롤백합니다.

저장소를 사용하여 차트를 공유할 수 있습니다. 이 가이드에서는 Cloud Storage를 사용하여 비공개 차트 저장소를 만듭니다.

다음 다이어그램에서는 차트, 저장소, 출시 간의 관계를 보여줍니다.

차트, 저장소, 출시 상호 관계

이 가이드에서는 Concourse에서 다음 스크린샷에 표시된 지속적 배포 파이프라인을 빌드합니다. 입력과 출력은 어두운 상자 안에 표시됩니다. 파이프라인 작업은 녹색 상자 안에 표시됩니다.

지속적 배포 파이프라인

스크린샷에서 볼 수 있듯이 build-image 작업은 애플리케이션 소스 코드(app-source)를 입력으로 취합니다. 애플리케이션 소스 코드에 새 태그가 푸시되면 Concourse에서 build-image 작업을 실행합니다. 빌드 프로세스가 노드를 체크아웃하고 Docker 빌드를 수행한 후에 Container Registry에 이미지를 푸시하여 app-image라는 파이프라인의 출력으로 레이블을 지정합니다. 애플리케이션 Docker 이미지는 파이프라인의 다음 작업인 deploy-chart에 대한 입력입니다. deploy-chart 작업도 차트 소스 코드(chart-source)를 입력으로 취합니다.

애플리케이션 이미지와 차트 소스 코드 모두 사용할 수 있으면 deploy-chart 작업이 시작되고 다음을 수행합니다.

  • 저장소 및 태그와 같은 애플리케이션 이미지의 정보를 가져옵니다.
  • Cloud Source Repositories에서 차트 소스 코드를 체크아웃합니다.
  • Helm 클라이언트를 사용하여 차트를 패키지화합니다.
  • Cloud Storage용 Helm 플러그인을 사용하여 Cloud Storage의 비공개 파트 저장소로 패키지화된 차트를 업로드합니다.
  • 이전 스크린샷에서 dev-site라고 하는 Concourse Helm 리소스를 사용하여 GKE 클러스터에 차트를 설치합니다.

목표

  • Cloud Shell을 열고 GKE 클러스터를 만든 후 ID 및 사용자 관리 체계를 구성합니다.
  • 샘플 애플리케이션을 다운로드한 후 Git 저장소를 만들고 Cloud Source Repositories에 업로드합니다.
  • Helm을 사용하여 GKE에 Concourse를 배포합니다.
  • 애플리케이션을 설치하고 업데이트하도록 Concourse 파이프라인을 구성합니다.
  • 애플리케이션에 코드 변경사항을 배포하여 파이프라인을 트리거합니다.
  • Helm 차트에 변경사항을 배포하여 클러스터에 롤아웃합니다.

비용

이 가이드에서는 비용이 청구될 수 있는 다음과 같은 GCP 구성요소를 사용합니다.

  • GKE
  • Cloud Storage

가격 계산기를 사용하면 예상 사용량을 기준으로 예상 비용을 산출할 수 있습니다.

시작하기 전에

  1. Select or create a Google Cloud Platform project.

    Go to the Manage resources page

  2. 프로젝트에 결제가 사용 설정되어 있는지 확인하세요.

    결제 사용 설정 방법 알아보기

  3. GKE, Cloud Source Repositories, Compute Engine APIs를 사용 설정합니다.

    APIs 사용 설정

환경 설정

가이드를 완료하기 위해 필요한 인프라와 ID를 구성합니다.

Cloud Shell 인스턴스 시작

Google Cloud Platform Console에서 Cloud Shell을 시작합니다. Cloud Shell 내에서 가이드의 나머지 내용을 실행합니다.

Cloud Shell 열기

GKE 클러스터 만들기

Concourse 포드에서 소스 코드를 다운로드하고, 이미지를 푸시하고, 차트를 Cloud Storage 차트 저장소에 업로드할 수 있도록 cloud-source-repos-rostorage-full 범위의 클러스터가 필요합니다.

다음 명령어를 사용하여 Concourse 및 샘플 Helm 차트를 배포할 GKE 클러스터를 만듭니다.

gcloud container clusters create concourse --image-type ubuntu \
    --machine-type n1-standard-2 --zone us-central1-f \
    --scopes cloud-source-repos-ro,storage-full

샘플 코드 다운로드

이 가이드에서는 기존 애플리케이션, Helm 차트, 파이프라인을 사용합니다. 이 가이드를 위해 만든 Cloud Storage 버킷에서 샘플 코드를 다운로드한 후 Cloud Shell에 압축을 푸세요.

wget https://gke-concourse.storage.googleapis.com/sample-app-v4.zip
unzip sample-app-v4.zip
cd concourse-continuous-delivery-master

Helm을 사용하여 Concourse 배포

Helm을 사용하여 Charts 저장소에서 Concourse를 배포할 수 있습니다.

Helm 설치

  1. Cloud Shell에서 Helm 바이너리를 다운로드 및 설치합니다.

    wget https://storage.googleapis.com/kubernetes-helm/helm-v2.6.2-linux-amd64.tar.gz
  2. 파일 압축을 풉니다.

    tar zxfv helm-v2.6.2-linux-amd64.tar.gz
    cp linux-amd64/helm .
    
  3. 사용자 계정에서 클러스터에 cluster-admin 역할이 있는지 확인합니다.

    kubectl create clusterrolebinding user-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account)
  4. Helm의 서버 측 Tiller에서 차트 배포에 사용할 수 있는 서비스 계정을 만듭니다.

    kubectl create serviceaccount tiller --namespace kube-system
  5. Tiller 서비스 계정에 클러스터의 cluster-admin 역할을 부여합니다.

    kubectl create clusterrolebinding tiller-admin-binding --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
  6. 모든 네임스페이스에서 리소스를 배포할 수 있도록 Concourse의 서비스 계정에 cluster-admin 역할을 부여합니다.

    kubectl create clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:default concourse-admin
  7. Helm을 초기화하여 클러스터에 Tiller를 설치합니다.

    ./helm init --service-account=tiller
    ./helm update
    
  8. Helm 플러그인을 설치하고 Cloud Storage 버킷에서 비공개 차트 저장소를 초기화합니다. 첫 번째 명령어는 환경 변수에 현재 프로젝트 ID를 저장합니다. 두 번째 명령어는 프로젝트 ID를 사용하여 고유한 버킷 이름을 만듭니다. 그런 다음 이 이름은 후속 명령어에서 사용될 수 있도록 다른 환경 변수에 저장됩니다.

    export PROJECT=$(gcloud info --format='value(config.project)')
    export BUCKET=$PROJECT-helm-repo
    ./helm plugin install https://github.com/viglesiasce/helm-gcs.git --version v0.1.1
    gsutil mb -l us-central1 gs://$BUCKET
    ./helm gcs init gs://$BUCKET
    
  9. Helm이 제대로 설치되었는지 확인합니다.

    ./helm version

    다음과 비슷한 출력이 표시됩니다. Helm이 올바르게 설치되었으면 클라이언트와 서버에 v2.6.2가 표시됩니다.

    Client: &version.Version{SemVer:"v2.6.2",
    GitCommit:"012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6",
    GitTreeState:"clean"}Server: &version.Version{SemVer:"v2.6.2",
    GitCommit:"012cb0ac1a1b2f888144ef5a67b8dab6c2d45be6",
    GitTreeState:"clean"}
    

    Helm에서 Tiller 프로세스에 접근할 수 없다는 메시지가 표시되면 잠시 기다렸다가 다시 시도하세요. Tiller가 초기화될 때까지 최대 2분이 소요될 수 있습니다.

Concourse 배포

  1. Cloud Shell에서 Concourse 설치에 전달할 구성 값으로 파일을 만듭니다. 첫 번째 명령어는 openssl 명령어를 사용하여 Concourse 관리자의 비밀번호로 사용되는 임의의 문자열을 생성합니다.

    export PASSWORD=$(openssl rand -base64 15)
    cat > concourse.yaml <<EOF
    concourse:
      password: $PASSWORD
      baggageclaimDriver: overlay
    web:
      service:
        type: LoadBalancer
    EOF
    
  2. Helm을 사용하여 Concourse 차트를 배포합니다.

    ./helm install stable/concourse --name concourse -f concourse.yaml --version 0.10.0
  3. 3~4분 기다린 후 concourse-web 포드가 실행 중이고 준비되었는지 확인합니다.

    kubectl get pods -l app=concourse-web

    포드가 준비되면 다음과 비슷한 출력이 표시됩니다.

    NAME                             READY     STATUS    RESTARTS   AGE
    concourse-web-2711520304-483vw   1/1       Running   0          3m
  4. Concourse 명령줄 도구인 fly를 다운로드합니다.

    export SERVICE_IP=$(kubectl get svc \
        --namespace default concourse-web \
        -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    wget -O fly "http://$SERVICE_IP:8080/api/v1/cli?arch=amd64&platform=linux"
    chmod +x fly
    
  5. Concourse 설치에 fly CLI를 인증합니다.

    ./fly -t local login -u concourse -p $PASSWORD -c http://$SERVICE_IP:8080
  6. Concourse 사용자 인터페이스의 URL을 가져옵니다.

    export SERVICE_IP=$(kubectl get svc \
        --namespace default concourse-web \
        -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    printf "Concourse URL: [http://$SERVICE_IP:8080]\nUsername: concourse\nPassword: $PASSWORD\n"

    이 명령어는 URL, 사용자 이름, 비밀번호를 출력합니다.

  7. 브라우저에서 이전 명령어의 URL로 이동합니다. 그러면 Concourse로 이동합니다.

  8. Concourse에서 오른쪽 상단에 있는 로그인 버튼을 클릭한 후 기본을 클릭합니다.

  9. 이전 명령어의 사용자 이름과 비밀번호로 로그인합니다.

ID 및 액세스 관리 구성

Cloud Identity Access Management(Cloud IAM) 서비스 계정을 만들어 Concourse가 Container Registry로 이미지를 푸시할 수 있도록 허용합니다.

  1. Cloud Shell에서 서비스 계정을 만듭니다.

    gcloud iam service-accounts create concourse --display-name concourse
  2. 이후에 명령어에서 사용할 수 있도록 서비스 계정 이메일 주소 및 현재 프로젝트 ID를 환경 변수에 저장합니다.

    export SA_EMAIL=$(gcloud iam service-accounts list \
        --filter="displayName:concourse" --format='value(email)')
    export PROJECT=$(gcloud info --format='value(config.project)')
    
  3. 서비스 계정에 storage.admin 역할을 부여합니다.

    gcloud projects add-iam-policy-binding $PROJECT \
        --role roles/storage.admin --member serviceAccount:$SA_EMAIL
    
  4. 서비스 계정 키를 다운로드합니다. 이후 단계에서 Concourse를 설치하고 이 키를 GKE에 업로드합니다.

    gcloud iam service-accounts keys create concourse-sa.json \
        --iam-account $SA_EMAIL
    

애플리케이션 배포

이 섹션에서는 소스 코드 저장소를 만들고, 파이프라인을 구성하고 만들고, 애플리케이션을 배포하고 변경한 후에 다시 배포합니다.

소스 코드 저장소 만들기

이 가이드에서는 애플리케이션 소스 코드 처리를 위한 저장소와 Helm 차트를 정의하는 소스 코드를 위한 저장소로 이루어진 두 개의 소스 코드 저장소를 사용합니다. 이 저장소 중 하나라도 변경하면 배포가 업데이트됩니다.

  1. 저장소를 만듭니다.

    gcloud source repos create chart-source
    gcloud source repos create app-source
    
  2. 이 저장소에서 Git 커밋에 대한 사용자 이름과 이메일 주소를 설정합니다. [EMAIL_ADDRESS]를 Git 이메일 주소로, [USERNAME]을 Git 사용자 이름으로 바꿉니다.

    git config --global user.email "[EMAIL_ADDRESS]"
    git config --global user.name "[USERNAME]"
    
  3. 로컬 저장소에서 Cloud Source Repositories로 차트 및 애플리케이션 소스 코드를 푸시합니다.

    export PROJECT=$(gcloud info --format='value(config.project)')
    for repo in app-source chart-source; do
    cd $repo
    git init && git add . && git commit -m 'Initial commit'
    git config credential.helper gcloud.sh
    git remote add google \
        https://source.developers.google.com/p/$PROJECT/r/$repo
        git push --all google
    cd ..
    done
    

파이프라인 구성 및 만들기

Concourse에서는 파이프라인에 매개변수를 보간할 수 있습니다. 이 기능을 사용하여 파이프라인을 매개변수화하고 소스 코드 저장소에 체크인하지 않으려는 비밀을 삽입합니다.

  1. Cloud Shell에서 구성 파일을 만듭니다.

    export PROJECT=$(gcloud info --format='value(config.project)')
    export BUCKET=$PROJECT-helm-repo
    export TOKEN_SECRET=$(kubectl get serviceaccount default -o jsonpath="{.secrets[0].name}")
    export CLUSTER_CA=$(kubectl get secret $TOKEN_SECRET -o jsonpath='{.data.ca\.crt}')
    export TOKEN=$(kubectl get secret $TOKEN_SECRET -o jsonpath='{.data.token}' | base64 --decode)
    
    cat > params.yaml <<EOF
    chart_name: nginx
    release_name: dev-site
    bucket: $BUCKET
    cluster_ca: $CLUSTER_CA
    token: $TOKEN
    project: $PROJECT
    service_account_json: '$(cat concourse-sa.json)'
    EOF
    
  2. Cloud Shell에서 fly CLI를 사용하여 파이프라인 파일을 업로드합니다.

    ./fly -t local set-pipeline -p dev-site-deploy \
        -c pipeline.yaml -l params.yaml -n
    
  3. 파이프라인의 일시중지를 해제해 사용 설정합니다.

    ./fly -t local unpause-pipeline -p dev-site-deploy
  4. 브라우저에서 Concourse를 새로 고칩니다.

    파이프라인이 표시됩니다.

    새로 고친 파이프라인

처음 애플리케이션 배포

파이프라인은 애플리케이션 또는 차트 소스 코드 저장소로 Git 태그를 푸시할 때 트리거되도록 구성됩니다. 애플리케이션을 처음 배포하려면 각 저장소의 첫 번째 태그를 푸시하세요.

  1. Cloud Shell에서 Git 태그를 만들고 푸시합니다.

    for repo in app-source chart-source; do
        cd $repo
        git tag v1.0.0
        git push google --tags
        cd ..
    done
    
  2. 브라우저에서 Concourse로 이동합니다. 1~2분 후에 build-image 작업 주위의 노란색 원이 깜박이면 파이프라인이 시작된 것을 확인할 수 있습니다.

    실행 중인 파이프라인

애플리케이션에 변경사항 배포

  1. 파이프라인이 완료된 후에 컨테이너에 로컬 포트를 전달하고 버전을 가져와 현재 배포된 웹 서버의 버전을 확인합니다.

    export POD_NAME=$(kubectl get pods --namespace default \
        -l "app=nginx,release=dev-site" \
        -o jsonpath="{.items[0].metadata.name}")
    kubectl port-forward $POD_NAME 8080:80 &
    curl -is localhost:8080 | grep 'Server\|color'
    

    웹 서버에서 nginx의 안정적 버전이 실행되고 있고 색상이 파란색으로 설정되어 있는 것을 확인할 수 있습니다.

    Server: nginx/1.14.0
    <h1 style="color:blue;">Welcome to the sample app!</h1>
    
  2. 포트 전달을 중지합니다.

    killall kubectl
  3. 애플리케이션 하위 디렉토리로 변경합니다.

    cd app-source
  4. Dockerfile에 사용된 웹 서버 버전을 stable에서 latest로 변경합니다.

    sed -i s/stable/latest/ Dockerfile
  5. 소스를 커밋하고 태그를 지정합니다.

    git add Dockerfile
    git commit -m 'Use latest NGINX'
    git tag v2.0.0
    
  6. Cloud Source Repositories로 코드를 푸시합니다.

    git push google --mirror
  7. Cloud Shell의 fly CLI를 사용하여 Concourse에서 소스 코드에 새 태그가 있는지 즉시 확인하게 만듭니다.

    ../fly -t local check-resource -r dev-site-deploy/app-source

    파이프라인이 다시 시작됩니다.

  8. 파이프라인이 완료되면 다음 명령어를 다시 실행하여 nginx 버전을 확인합니다.

    export POD_NAME=$(kubectl get pods --namespace default \
        -l "app=nginx,release=dev-site" \
        -o jsonpath="{.items[0].metadata.name}")
    kubectl port-forward $POD_NAME 8080:80 &
    curl -is localhost:8080 | grep 'Server\|color'
    

    nginx 버전이 최신 버전으로 업그레이드됩니다.

    Server: nginx/1.15.0
    <h1 style="color:blue;">Welcome to the sample app!</h1>
    
  9. 포트 전달을 중지합니다.

    killall kubectl

다음으로 차트 구성을 변경해 업데이트를 트리거합니다.

차트에 변경사항 배포

차트 정의에는 애플리케이션의 기본 페이지를 정의하는 Kubernetes 구성 맵이 있습니다. 해당 구성 맵을 업데이트하여 애플리케이션의 색인 페이지를 변경합니다.

  1. Cloud Shell에서 차트 하위 디렉토리로 이동합니다.

    cd ../chart-source/
  2. 구성 맵의 색상 문자열을 바꿔 제목 색상을 파란색에서 녹색으로 변경합니다.

    sed -i s/blue/green/ templates/config-map.yaml
  3. Git을 사용하여 소스 코드를 커밋하고 태그를 지정합니다.

    git add templates/config-map.yaml
    git commit -m 'Use green for page heading'
    
  4. 코드에 태그를 지정하고 푸시하여 파이프라인을 시작합니다.

    git tag v2.0.0
    git push google --mirror
    
  5. fly 명령어를 사용하여 Concourse에서 소스 코드에 새 태그가 있는지 즉시 확인하게 만듭니다.

    ../fly -t local check-resource -r dev-site-deploy/chart-source

    Concourse에서는 파이프라인이 차트 배포 작업에서 시작됩니다.

  6. Cloud Shell에서 애플리케이션의 출력을 확인합니다.

    export POD_NAME=$(kubectl get pods \
        -n default -l "app=nginx,release=dev-site" \
        -o jsonpath="{.items[0].metadata.name}")
    kubectl port-forward $POD_NAME 8080:80 &
    curl -is localhost:8080 | grep 'Server\|color'
    

    다음과 같은 출력이 표시됩니다. 이번에는 파란색이 아닌 녹색을 사용하는 마크업으로 서버가 응답합니다.

    Server: nginx/1.15.0
    <h1 style="color:green;">Welcome to the sample app!</h1>
    

삭제

다음 단계에서는 불필요한 요금이 발생하지 않도록 이 가이드에서 만든 모든 리소스를 삭제합니다.

  1. Concourse 설치를 삭제합니다.

    ../helm delete --purge concourse
  2. 서비스 계정을 삭제합니다.

    export SA_EMAIL=$(gcloud iam service-accounts list \
        --filter="displayName:concourse" \
        --format='value(email)')
    gcloud iam service-accounts delete $SA_EMAIL
    
  3. GKE 클러스터를 삭제합니다.

    gcloud container clusters delete concourse --zone us-central1-f
  4. 소스 코드 저장소를 삭제합니다.

    gcloud source repos delete app-source --quiet
    gcloud source repos delete chart-source --quiet
    
  5. 버킷을 삭제합니다.

    export PROJECT=$(gcloud info --format='value(config.project)')
    export BUCKET=$PROJECT-helm-repo
    gsutil -m rm -r gs://$BUCKET
    

다음 단계

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

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