이 가이드에서는 널리 사용되는 GitOps 방법론을 사용하여 Terraform과 Jenkins로 코드형 인프라를 관리하는 방법을 설명합니다. 이 가이드는 소프트웨어 애플리케이션을 관리하는 방식으로 인프라를 관리하는 권장사항을 찾고 있는 개발자와 운영자를 대상으로 합니다. 이 문서에서는 개발자가 Terraform, Jenkins, GitHub, Google Kubernetes Engine(GKE), Google Cloud에 익숙하다고 가정합니다.
아키텍처
이 가이드에서 사용하는 아키텍처는 dev
및 prod
라는 GitHub 분기를 사용하여 실제 개발 환경과 프로덕션 환경을 나타냅니다. dev
및 prod
라는 Google Cloud 프로젝트의 Virtual Private Cloud(VPC) 네트워크에서 이러한 환경을 정의합니다.
인프라 제안
다음 아키텍처 다이어그램과 같이 개발자나 운영자가 GitHub 비보호 분기(일반적으로 기능 분기)에 인프라를 제안하면 프로세스가 시작됩니다. 해당되는 경우 이 기능 분기는 dev
분기에 대한 pull 요청(PR)을 통해 개발 환경으로 승격될 수 있습니다. 그러면 Jenkins가 자동으로 작업을 트리거하여 유효성 검사 파이프라인을 실행합니다. 이 작업은 terraform plan
명령어를 실행하여 유효성 검사 결과를 GitHub에 다시 보고합니다. 이 작업에는 자세한 인프라 변경 보고서에 대한 링크가 포함됩니다. 이 단계를 통해 공동작업자와 함께 잠재적 변경사항을 검토하고 변경사항이 dev
분기에 병합되기 전에 후속 커밋을 추가할 수 있으므로 이 단계가 중요합니다.
Dev
배포
검증 프로세스가 성공하고 제안된 인프라 변경사항을 승인하는 경우 pull 요청을 dev
분기에 병합할 수 있습니다. 다음 다이어그램에서 이 프로세스를 볼 수 있습니다.
병합이 완료되면 Jenkins는 다른 작업을 트리거하여 배포 파이프라인을 실행합니다. 이 시나리오에서 작업은 개발자가 원하는 상태를 얻을 수 있도록 Terraform 매니페스트를 개발 환경에 적용합니다. 이 단계를 통해 프로덕션으로 승격되기 전에 Terraform 코드를 테스트할 수 있으므로 이 단계가 중요합니다.
Prod
배포
테스트를 완료하고 프로덕션 변경사항을 승격할 준비가 되면 dev
분기를 prod
분기로 병합하여 프로덕션 환경에 대한 인프라 설치를 트리거해야 합니다. 다음 다이어그램에서 이 프로세스를 볼 수 있습니다.
pull 요청을 만들면 동일한 유효성 검사 프로세스가 실행됩니다. 이 프로세스를 통해 운영팀이 제안된 변경사항을 검토하고 프로덕션에 승인할 수 있습니다.
목표
- GitHub 저장소를 설정합니다.
- Terraform 원격 상태 스토리지를 만듭니다.
- GKE 클러스터를 만들고 Jenkins를 설치합니다.
- 기능 분기에서 환경 구성을 변경합니다.
- 변경사항을 개발 환경으로 승격합니다.
- 변경사항을 프로덕션 환경으로 승격합니다.
비용
이 가이드에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.
프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요. Google Cloud를 처음 사용하는 사용자는 무료 체험판을 사용할 수 있습니다.
이 가이드를 마치면 만든 리소스를 삭제하여 비용이 계속 청구되지 않게 할 수 있습니다. 자세한 내용은 삭제를 참조하세요.
시작하기 전에
- Google Cloud 계정에 로그인합니다. Google Cloud를 처음 사용하는 경우 계정을 만들고 Google 제품의 실제 성능을 평가해 보세요. 신규 고객에게는 워크로드를 실행, 테스트, 배포하는 데 사용할 수 있는 $300의 무료 크레딧이 제공됩니다.
-
Google Cloud Console의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.
-
Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다. 프로젝트에 결제가 사용 설정되어 있는지 확인하는 방법을 알아보세요.
-
Cloud Console에서 Cloud Shell을 활성화합니다.
Cloud Console 하단에 Cloud Shell 세션이 시작되고 명령줄 프롬프트가 표시됩니다. Cloud Shell은
gcloud
명령줄 도구가 포함되고 Cloud SDK가 사전 설치된 셸 환경으로, 현재 프로젝트의 값이 이미 설정되어 있습니다. 세션이 초기화되는 데 몇 초 정도 걸릴 수 있습니다. - Cloud Shell에서 프로젝트 ID를 구성하고 GitHub 사용자 이름과 이메일 주소를 설정합니다.
PROJECT_ID=PROJECT_ID GITHUB_USER=YOUR_GITHUB_USER GITHUB_EMAIL=YOUR_EMAIL_ADDRESS gcloud config set project $PROJECT_ID
Cloud Shell에서 GitHub에 액세스한 적이 없으면 사용자 이름과 이메일 주소를 사용하여 구성할 수 있습니다.
git config --global user.email "$GITHUB_EMAIL" git config --global user.name "$GITHUB_USER"
GitHub는 이 정보를 사용하여 Cloud Shell에서 만드는 커밋의 작성자를 식별합니다.
GitHub 저장소 설정
이 가이드에서는 단일 GitHub 저장소를 사용하여 클라우드 인프라를 정의합니다. 서로 다른 환경에 해당하는 각각의 분기를 사용하여 이 인프라를 조정합니다.
dev
분기에는 개발 환경에 적용되는 최신 변경사항이 포함됩니다.prod
분기에는 프로덕션 환경에 적용되는 최신 변경사항이 포함됩니다.
이 인프라를 사용하면 언제든지 저장소를 참조하여 각 환경에 필요한 구성을 파악하고 먼저 이를 dev
환경에 병합해 새로운 변경사항을 제안할 수 있습니다. 그런 다음 dev
분기를 prod
분기에 병합하여 변경사항을 승격합니다.
시작하려면 solutions-terraform-jenkins-gitops
저장소를 포크해야 합니다.
- GitHub에서
solutions-terraform-jenkins-gitops
저장소로 이동합니다. 포크를 클릭합니다.
이제 소스 파일이 있는
solutions-terraform-jenkins-gitops
저장소의 복사본이 준비되었습니다.Cloud Shell에서 포크된 이 저장소를 클론합니다.
cd ~ git clone https://github.com/$GITHUB_USER/solutions-terraform-jenkins-gitops.git cd ~/solutions-terraform-jenkins-gitops
이 저장소의 코드는 다음과 같이 구성됩니다.
example-pipelines/
폴더: 이 가이드에서 사용된 예시 파이프라인이 있는 하위 폴더가 포함되어 있습니다.example-create/
: 환경에 가상 머신을 만들기 위한 Terraform 코드가 포함되어 있습니다.environments/
: 백엔드 구성 및example-create/
폴더의 파일에 대한 링크와 함께dev
및prod
환경 폴더가 포함되어 있습니다.jenkins-gke/
폴더: 새 GKE 클러스터에 Jenkins를 배포하는 데 필요한 스크립트가 포함되어 있습니다.tf-gke/
: GKE에 배포하고 Jenkins 및 종속 항목 리소스를 설치하는 Terraform 코드를 포함합니다.
Terraform 원격 상태 스토리지 만들기
Terraform 상태는 기본적으로 로컬에 저장됩니다. 그러나 상태를 모든 시스템에서 액세스할 수 있는 원격 중앙 스토리지에 저장하는 것이 좋습니다. 이 방식을 사용하면 서로 다른 시스템에서 복사본을 여러 개 만들지 않게 하여 인프라 구성과 상태의 불일치를 방지할 수 있습니다.
이 섹션에서는 Terraform의 원격 상태를 저장하는 Cloud Storage 버킷을 구성합니다.
Cloud Shell에서 Cloud Storage 버킷을 만듭니다.
gsutil mb gs://${PROJECT_ID}-tfstate
객체 버전 관리를 사용 설정하여 상태 기록을 유지합니다.
gsutil versioning set on gs://${PROJECT_ID}-tfstate
terraform.tfvars
과backend.tf
파일 모두에서 PROJECT_ID 자리표시자를 프로젝트 ID로 바꿉니다.sed -i.bak "s/PROJECT_ID/${PROJECT_ID}/g" ./example-pipelines/environments/*/terraform.tfvars sed -i.bak "s/PROJECT_ID/${PROJECT_ID}/g" ./example-pipelines/environments/*/backend.tf sed -i.bak "s/PROJECT_ID/${PROJECT_ID}/g" ./jenkins-gke/tf-gke/terraform.tfvars sed -i.bak "s/PROJECT_ID/${PROJECT_ID}/g" ./jenkins-gke/tf-gke/backend.tf
모든 파일이 업데이트되었는지 확인합니다.
git status
출력은 다음과 같이 표시됩니다.
On branch dev Your branch is up-to-date with 'origin/dev'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: example-pipelines/environments/dev/backend.tf modified: example-pipelines/environments/dev/terraform.tfvars modified: example-pipelines/environments/prod/backend.tf modified: example-pipelines/environments/prod/terraform.tfvars modified: jenkins-gke/tf-gke/backend.tf modified: jenkins-gke/tf-gke/terraform.tfvars
변경사항을 커밋하고 푸시합니다.
git add --all git commit -m "Update project IDs and buckets" git push origin dev
GitHub 구성에 따라서 이전 변경사항을 푸시하기 위해 인증해야 할 수도 있습니다.
GKE 클러스터 만들기 및 Jenkins 설치
이 섹션에서는 Terraform과 Helm을 사용하여 코드형 인프라를 관리할 수 있는 환경을 설정합니다. 먼저 Terraform과 Cloud Foundations Toolkit을 사용하여 Virtual Private Cloud, GKE 클러스터, 워크로드 아이덴티티를 구성합니다. 그런 다음 Helm을 사용하여 이 환경 최상단에 Jenkins를 설치합니다.
Terraform 명령어를 실행하기 전에 GitHub 개인 액세스 토큰을 만들어야 합니다. Jenkins가 포크된 저장소에 액세스하도록 허용하려면 이 토큰이 필요합니다.
GitHub 개인 액세스 토큰 만들기
- GitHub에 로그인합니다.
- 프로필 사진을 클릭한 다음 설정를 클릭합니다.
- 개발자 설정을 클릭한 후 개인 액세스 토큰을 클릭합니다.
- 새 토큰 생성을 클릭하고 메모 필드에 토큰에 대한 설명을 지정하고 저장소 범위를 선택합니다.
토큰 생성을 클릭하고 새로 만든 토큰을 클립보드에 복사합니다.
Cloud Shell에서 토큰을
GITHUB_TOKEN
변수에 저장합니다. 이 변수 콘텐츠는 나중에 GKE 클러스터의 보안 비밀로 저장됩니다.GITHUB_TOKEN="NEWLY_CREATED_TOKEN"
GKE 클러스터 만들기 및 Jenkins 설치
이제 GKE 클러스터를 만듭니다. 이 클러스터에는 Cloud Console의 서비스 계정 페이지에 필요한 권한을 Jenkins에 부여할 수 있는 워크로드 아이덴티티(jenkins-wi-jenkins@PROJECT_ID.iam.gserviceaccount.com
)가 포함됩니다.
향상된 보안 속성과 관리 효율성으로 인해 워크로드 아이덴티티를 사용하여 GKE 내에서 Google Cloud 서비스에 액세스하는 것이 좋습니다.
Google Cloud 인프라형 코드를 관리하려면 Jenkins에서 Google Cloud APIs를 사용하도록 인증해야 합니다. 다음 단계에서 Terraform은 Jenkins에서 사용하는 Kubernetes 서비스 계정(KSA)을 Google 서비스 계정(GSA) 역할을 수행하도록 구성합니다. 이 구성을 사용하면 Jenkins가 Google Cloud APIs에 액세스할 때 GSA로 자동 인증할 수 있습니다.
편의를 위해 이 가이드에서는 프로젝트 편집자 액세스 권한을 부여합니다. 그러나 이 역할에 광범위한 권한 집합이 있으므로 프로덕션 환경에서는 일반적으로 최소 권한 액세스 권한을 제공하는 회사의 IT 보안 권장사항을 따라야 합니다.
Cloud Shell에서 Terraform을 설치합니다.
wget https://releases.hashicorp.com/terraform/0.12.24/terraform_0.12.24_linux_amd64.zip unzip terraform_0.12.24_linux_amd64.zip sudo mv terraform /usr/local/bin/ rm terraform_0.12.24_linux_amd64.zip
GKE 클러스터를 만들고 Jenkins를 설치합니다.
cd jenkins-gke/tf-gke/ terraform init terraform plan --var "github_username=$GITHUB_USER" --var "github_token=$GITHUB_TOKEN" terraform apply --auto-approve --var "github_username=$GITHUB_USER" --var "github_token=$GITHUB_TOKEN"
이 프로세스를 완료하는 데 몇 분 정도 걸릴 수 있습니다. 출력은 다음과 비슷합니다.
Apply complete! Resources: 28 added, 0 changed, 0 destroyed. Outputs: ca_certificate = LS0tLS1CRU.. client_token = <sensitive> cluster_name = jenkins gcp_service_account_email = jenkins-wi-jenkins@PROJECT_ID.iam.gserviceaccount.com jenkins_k8s_config_secrets = jenkins-k8s-config jenkins_project_id = PROJECT_ID k8s_service_account_name = jenkins-wi-jenkins kubernetes_endpoint = <sensitive> service_account = tf-gke-jenkins-k253@PROJECT_ID.iam.gserviceaccount.com zone = us-east4-a
Jenkins가 새로 생성된 GKE 클러스터에 배포되면 Jenkins 홈 디렉터리는 Helm 차트 문서에 따라 영구적인 볼륨에 저장됩니다. 이 배포는 pull 요청에서 트리거되고
dev
및prod
분기에 합병된example-pipelines/environments/Jenkinsfile
와 함께 사전 구성된 여러 분기 파이프라인이 동반됩니다.기본 폴더로 돌아갑니다.
cd ../..
방금 만든 클러스터 사용자 인증 정보를 검색합니다.
gcloud container clusters get-credentials jenkins --zone=us-east4-a --project=${PROJECT_ID}
Jenkins URL과 사용자 인증 정보를 검색합니다.
JENKINS_IP=$(kubectl get service jenkins -o jsonpath='{.status.loadBalancer.ingress[0].ip}') JENKINS_PASSWORD=$(kubectl get secret jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo printf "Jenkins url: http://$JENKINS_IP\nJenkins user: admin\nJenkins password: $JENKINS_PASSWORD\n"
이전 단계의 출력 정보를 사용하여 Jenkins에 로그인합니다.
GitHub가 빌드에 직접 연결되는 링크를 만들 수 있도록 Jenkins 위치를 구성합니다. Jenkins 관리 > 시스템 구성을 클릭하고 Jenkins URL 필드에 Jenkins URL을 설정합니다.
새 기능 분기에서 환경 구성 변경
현재 대부분의 환경이 구성되었습니다. 이제 몇 가지 코드를 변경할 차례입니다.
Cloud Shell에서 팀의 다른 기능에 영향을 미치지 않고 작업할 수 있는 새로운 기능 분기를 만듭니다.
git checkout -b change-vm-name
가상 머신 이름을 변경합니다.
cd example-pipelines/example-create sed -i.bak "s/\${var.environment}-001/\${var.environment}-new/g" main.tf
example-create
폴더에서main.tf
파일을 변경하고 있습니다. 이 파일은dev
및prod
환경 폴더에 연결되어 있습니다. 즉, 변경사항이 두 환경 모두에 전파됩니다.코드 변경사항을 GitHub 기능 분기로 푸시합니다.
git commit -am "change vm name" git push --set-upstream origin change-vm-name
GitHub에서 포크된 저장소의 기본 페이지로 이동합니다.
저장소의 pull 요청 탭을 클릭한 후 새 pull 요청을 클릭합니다.
기본 저장소에 포크한 저장소를 선택합니다.
기본에서
dev
를 선택하고 비교에서change-vm-name
를 선택합니다.pull 요청 만들기를 클릭합니다.
pull 요청이 열리면 Jenkins 작업이 자동으로 시작됩니다. Jenkins에서 새로운 pull 요청을 확인하는 데 1분 정도 걸릴 수 있습니다. 모든 검사 표시를 클릭하고 체크 표시가 녹색이 될 때까지 기다립니다.
세부정보를 클릭하여
terraform plan
명령어 출력을 포함한 자세한 정보를 확인합니다.
Jenkins 작업은 Jenkinsfile
에서 정의된 파이프라인을 실행했습니다.
이 파이프라인은 가져오는 분기에 따라 다르게 동작합니다. 빌드는 TARGET_ENV
변수가 모든 환경 폴더와 일치하는지 검사합니다. 일치하면 Jenkins가 해당 환경에 terraform plan
을 실행합니다. 그렇지 않으면 Jenkins가 모든 환경에 terraform plan
을 실행하여 제안된 변경사항이 모든 환경에 적용되도록 합니다. 이러한 요금제 중 하나라도 실행에 실패하면 빌드가 실패합니다.
모든 example-pipelines/environments
하위 폴더에 대해 terraform plan
가 실행되는 이유는 제안되는 변경사항이 모든 환경에 적용되도록 하기 위해서입니다. 이렇게 하면 pull 요청을 병합하기 전에 계획을 검토하여 예를 들면 승인되지 않은 항목에 액세스 권한을 부여하지 않도록 할 수 있습니다.
다음은 JENKINSFILE
의 terraform plan
코드입니다.
마찬가지로 terraform apply
명령어는 환경 분기에 대해 실행되지만 다른 경우에는 무시됩니다. 이 섹션에서는 새 분기에 대한 코드 변경사항을 제출했으므로 인프라 배포가 Cloud 프로젝트에 적용되지 않았습니다.
다음은 JENKINSFILE
의 terraform apply
코드입니다.
분기 병합 전에 Jenkins 실행 성공
Jenkins 작업 실행이 성공하는 경우에만 병합이 적용되도록 할 수 있습니다.
- GitHub에서 포크된 저장소의 기본 페이지로 이동합니다.
- 저장소 이름을 위해 설정을 클릭합니다.
- 분기를 클릭합니다.
- 분기 보호 규칙에서 규칙 추가를 클릭합니다.
- 분기 이름 패턴에
dev
를 입력합니다. 일치하는 분기 보호에서 병합 전에 상태 검사를 통과해야 함을 선택한 다음
continuous-integration/jenkins/pr-merge
를 선택합니다.(선택사항) 검토 및 승인되지 않은 pull 요청이 프로덕션에 병합되는 것을 방지하려면 병합 전에 pull 요청 검토 필요 및 관리자 포함 옵션을 사용 설정하는 것을 고려하세요.
만들기를 클릭합니다.
4~7단계를 반복하여 분기 이름 패턴을
prod
로 설정합니다.
이 구성은 dev
분기와 prod
분기를 보호하는 데 중요합니다. 즉, 먼저 커밋을 다른 분기로 푸시한 후 보호된 분기에만 병합해야 합니다. 이 가이드의 보호에서는 Jenkins 실행이 성공해야만 병합이 허용됩니다. 새로 만든 pull 요청에 구성이 적용되었는지 확인할 수 있습니다. 녹색 체크표시를 찾습니다.
개발 환경으로 변경사항 승격
병합 대기 중인 pull 요청이 있습니다. 이제 dev
환경에 원하는 상태를 적용할 수 있습니다.
- GitHub에서 포크된 저장소의 기본 페이지로 이동합니다.
- 저장소 이름을 위해 pull 요청을 클릭합니다.
- 만든 pull 요청을 클릭합니다.
pull 요청 병합을 클릭한 후 병합 확인을 클릭합니다.
Jenkins에서 Open Blue Ocean을 클릭합니다. 그런 다음
terraform-jenkins-create-demo
멀티 분기 프로젝트의 분기 탭에서 상태 아이콘을 확인하여 새 dev 작업이 트리거되었는지 확인합니다. 시작하는 데 1분 정도 걸릴 수 있습니다.Cloud Console에서 VM 인스턴스 페이지로 이동하고 새 이름의 VM이 있는지 확인합니다.
프로덕션 환경으로 변경사항 승격
이제 개발 환경을 테스트했으므로 인프라 코드를 프로덕션으로 승격할 수 있습니다.
- GitHub에서 포크된 저장소의 기본 페이지로 이동합니다.
- 새 pull 요청을 클릭합니다.
기본 저장소에 포크한 저장소를 선택합니다.
기본에서
prod
를 선택하고 비교에서dev
를 선택합니다.pull 요청 만들기를 클릭합니다.
Promoting vm name change
와 같은 제목을 입력한 후 pull 요청 만들기를 클릭합니다.검사기가 녹색으로 전환될 때까지 1~2분 정도 기다린 후
continuous-integration/jenkins/pr-merge
옆에 있는 세부정보 링크를 클릭합니다.Jenkins에서
TF Plan
을 선택하고 로그에서 제안된 변경사항을 검토합니다.제안된 변경사항이 올바르면 GitHub에서 pull 요청 병합을 클릭한 후 병합 확인을 클릭합니다.
Cloud Console에서 VM 인스턴스 페이지를 열고 프로덕션 VM이 배포되었는지 확인합니다.
Jenkins에서 코드형 인프라 파이프라인을 구성했습니다. 앞으로 다음을 해볼 수 있습니다.
- 별도의 사용 사례에 배포를 추가합니다.
- 필요에 맞게 추가 환경을 만듭니다.
- 환경별로 VPC를 사용하는 대신 환경별로 프로젝트를 사용합니다.
삭제
이 가이드에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.
프로젝트 삭제
- Cloud Console에서 리소스 관리 페이지로 이동합니다.
- 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제를 클릭합니다.
- 대화상자에서 프로젝트 ID를 입력한 후 종료를 클릭하여 프로젝트를 삭제합니다.
다음 단계
- 인하우스 Jenkins에서 Google Cloud에 대한 보안 액세스를 배포하고 승인하는 방법에 대한 자세한 내용은 Google Cloud의 Jenkins를 참조하세요.
- 워크로드 아이덴티티 소개: GKE 애플리케이션 인증 개선을 참조하세요.
- Terraform 및 Cloud Build로 코드형 인프라 관리에서 코드형 인프라를 관리하는 방법을 알아봅니다.
- Cloud Foundation Toolkit 템플릿을 사용하여 Google Cloud에서 반복 가능한 기업용 기본 환경을 빠르게 구축하세요.
- Cloud Build를 사용한 GitOps 스타일 지속적 배포를 확인하세요.
- 고급 Cloud Build 기능을 사용해 봅니다.
- 다른 Google Cloud 기능을 직접 사용해보세요. 가이드 살펴보기.