本教學課程說明如何使用熱門的 GitOps 方法,透過 Terraform 和 Cloud Build 管理基礎架構式程式碼。「GitOps」GitOps一詞是由 Weaveworks 首先提出,其主要概念是使用 Git 存放區來儲存您所要的環境狀態。Terraform 是 HashiCorp 開發的工具,可讓您透過程式碼,以可預測的方式建立、變更及改善雲端基礎架構。在本教學課程中,您將使用 Cloud Build (持續整合服務) 將 Terraform 資訊清單自動套用至您的環境。 Google Cloud
本教學課程適用於正在尋找一流的策略,以便以可預測的方式變更基礎架構的開發人員和操作人員。本文假設您已熟悉 Google Cloud、Linux 和 GitHub。
開發運作現狀報告指出,有幾項能力可提升軟體推送成效。本教學課程將說明下列功能:
架構
為了說明本教學課程如何將 GitOps 做法應用於管理 Terraform 的執行作業,請參考以下架構圖。請注意,其中使用了 GitHub 分支版本 (dev
和 prod
) 來代表實際環境。這些環境分別由虛擬私有雲 (VPC) 網路 (dev
和 prod
) 定義至 Google Cloud 專案中。
將 Terraform 程式碼推送至 dev
或 prod
分支版本時,這個程序便會開始。在這種情況下,Cloud Build 會觸發並套用 Terraform 資訊清單,以在個別環境中實現您所要的狀態。另一方面,當您將 Terraform 程式碼推送至任何其他分支版本 (例如功能分支版本) 時,Cloud Build 會運作以執行 terraform plan
,但不會將任何內容套用至任何環境。
在理想情況下,開發人員或操作人員必須向未受保護的分支版本提出基礎架構建議,然後透過提取要求提交那些建議。Cloud Build GitHub 應用程式 (本教學課程稍後會討論) 會自動觸發建構工作,並將 terraform plan
報告連結至這些提取要求。如此一來,您就可以在系統將變更合併至基本分支版本之前先和協作者討論及審查可能的變更,以及加入後續修訂版本。
如果沒有任何疑慮,您必須先將變更合併至 dev
分支版本。這項合併作業會觸發將基礎架構部署至 dev
環境,讓您能夠測試這個環境。在經過測試並對所部署的內容有信心後,您必須將 dev
分支版本合併至 prod
分支版本,以觸發將基礎架構安裝至實際工作環境。
目標
- 設定您的 GitHub 存放區。
- 設定 Terraform 以將狀態儲存在 Cloud Storage 值區中。
- 將權限授予您的 Cloud Build 服務帳戶。
- 將 Cloud Build 連線至您的 GitHub 存放區。
- 在功能分支版本中變更您的環境設定。
- 將變更推行至開發環境。
- 將變更推行至實際工作環境。
費用
在本文件中,您會使用 Google Cloud的下列計費元件:
如要根據預測用量估算費用,請使用 Pricing Calculator。
完成本文所述工作後,您可以刪除已建立的資源,避免繼續計費。詳情請參閱清除所用資源一節。
必要條件
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
- 在 Cloud Shell 中,取得您剛剛選取的專案的 ID:
如果此指令未傳回專案 ID,請將 Cloud Shell 設定為使用您的專案,然後將gcloud config get-value project
PROJECT_ID
改成您的專案 ID。gcloud config set project PROJECT_ID
- 啟用所需的 API:
這個步驟可能需要幾分鐘才能完成。gcloud services enable cloudbuild.googleapis.com compute.googleapis.com
- 如果您從未在 Cloud Shell 中使用過 Git,請使用您的姓名和電子郵件地址進行設定:
Git 會使用這項資訊識別您在 Cloud Shell 中建立的修訂版本的作者身分。git config --global user.email "YOUR_EMAIL_ADDRESS" git config --global user.name "YOUR_NAME"
dev
分支版本包含套用至開發環境的最新變更。prod
分支版本包含套用至實際工作環境的最新變更。- 在 GitHub 中,前往 https://github.com/GoogleCloudPlatform/solutions-terraform-cloudbuild-gitops.git。
按一下頁面右上角的 [Fork] (分支)。
您現在已取得內含來源檔案的
solutions-terraform-cloudbuild-gitops
存放區副本。在 Cloud Shell 中,複製這個分支的存放區,將
YOUR_GITHUB_USERNAME
改成您的 GitHub 使用者名稱:cd ~ git clone https://github.com/YOUR_GITHUB_USERNAME/solutions-terraform-cloudbuild-gitops.git cd ~/solutions-terraform-cloudbuild-gitops
environments/
資料夾包含代表環境 (例如dev
和prod
) 的子資料夾,可分別為處於不同成熟度階段 (開發和實際工作) 的工作負載之間提供邏輯隔離。雖然讓這些環境儘量類似是很好的做法,但每個子資料夾應有自己的 Terraform 設定,以確保它們可以視需要具有專屬的設定。modules/
資料夾包含內嵌 Terraform 模組。這些模組代表相關資源的邏輯群組,可用於跨不同環境共用程式碼。cloudbuild.yaml
檔案是建構設定檔,其中包含 Cloud Build 的操作說明,例如如何根據一組步驟來執行工作。這個檔案會根據 Cloud Build 擷取程式碼的來源分支版本來指定條件式執行作業,例如:如果是
dev
和prod
分支版本,系統會執行以下步驟:terraform init
terraform plan
terraform apply
如果是任何其他分支版本,系統會執行以下步驟:
- 針對所有
environments
子資料夾執行terraform init
- 針對所有
environments
子資料夾執行terraform plan
- 針對所有
在 Cloud Shell 中,建立 Cloud Storage 值區:
1. 啟用物件版本管理功能,以保留部署的記錄:PROJECT_ID=$(gcloud config get-value project) gcloud storage buckets create gs://${PROJECT_ID}-tfstate
```sh gcloud storage buckets update gs://${PROJECT_ID}-tfstate --versioning ``` Enabling Object Versioning increases [storage costs](/storage/pricing){: track-type="tutorial" track-name="internalLink" track-metadata-position="body" }, which you can mitigate by configuring [Object Lifecycle Management](/storage/docs/lifecycle){: track-type="tutorial" track-name="internalLink" track-metadata-position="body" } to delete old state versions.
在
terraform.tfvars
和backend.tf
檔案中,將PROJECT_ID
預留位置改成專案 ID:cd ~/solutions-terraform-cloudbuild-gitops sed -i s/PROJECT_ID/$PROJECT_ID/g environments/*/terraform.tfvars sed -i s/PROJECT_ID/$PROJECT_ID/g environments/*/backend.tf
在 OS X/macOS 上,您可能需要在
sed -i
後方加上兩個引號 (""
),如下所示:cd ~/solutions-terraform-cloudbuild-gitops sed -i "" s/PROJECT_ID/$PROJECT_ID/g environments/*/terraform.tfvars sed -i "" s/PROJECT_ID/$PROJECT_ID/g environments/*/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: environments/dev/backend.tf modified: environments/dev/terraform.tfvars modified: environments/prod/backend.tf modified: environments/prod/terraform.tfvars no changes added to commit (use "git add" and/or "git commit -a")
修訂並推送您的變更:
git add --all git commit -m "Update project IDs and buckets" git push origin dev
視您的 GitHub 設定而定,您將必須進行驗證才能推送上述變更。
將權限授予您的 Cloud Build 服務帳戶
如要讓 Cloud Build 服務帳戶以管理 Google Cloud 資源的目標執行 Terraform 指令碼,您必須為其授予對專案的適當存取權。為簡單起見,在本教學課程中會授予專案編輯者存取權。但是,當專案編輯者角色擁有廣泛的權限時,在實際工作環境中,您必須遵循貴公司的 IT 安全性最佳做法,通常是提供最低存取權限。如要瞭解保護資料安全的最佳做法,請參閱「明確驗證每次存取嘗試」。
在 Cloud Shell 中,擷取專案的 Cloud Build 服務帳戶的電子郵件:
CLOUDBUILD_SA="$(gcloud projects describe $PROJECT_ID \ --format 'value(projectNumber)')@cloudbuild.gserviceaccount.com"
將所需的存取權授予您的 Cloud Build 服務帳戶:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:$CLOUDBUILD_SA --role roles/editor
將 Cloud Build 直接連線至您的 GitHub 存放區
本節說明如何安裝 Cloud Build GitHub 應用程式。這項安裝作業可讓您將 GitHub 存放區與Google Cloud 專案連線,以便 Cloud Build 可以在您每次建立新的分支版本或將程式碼推送至 GitHub 時自動套用 Terraform 資訊清單。
以下步驟提供了僅針對
solutions-terraform-cloudbuild-gitops
存放區安裝應用程式的操作說明,但您可以選擇為更多或所有存放區安裝應用程式。前往 Cloud Build 應用程式的「GitHub Marketplace」(GitHub 市集) 頁面:
- 如果這是您第一次在 GitHub 中設定應用程式,請按一下頁面底部的「以 Google Cloud Build 設定」。然後按一下「Grant this app access to your GitHub account」。
- 如果這不是您第一次在 GitHub 中設定應用程式:請按一下「設定存取權」。個人帳戶的「應用程式」頁面隨即開啟。
按一下 Cloud Build 列中的「設定」。
選取「Only select repositories」,然後選取
solutions-terraform-cloudbuild-gitops
連結至存放區。按一下「儲存」或「安裝」,按鈕標籤會根據您的工作流程而有所不同。系統會將您重新導向至 Google Cloud ,繼續安裝程序。
登入 Google Cloud 帳戶。如果系統要求,請授權 Cloud Build 與 GitHub 整合。
在「Cloud Build」頁面中,選取您的專案。系統會顯示精靈。
在「Select repository」(選取存放區) 專區中,選取 GitHub 帳戶和
solutions-terraform-cloudbuild-gitops
存放區。如果您同意條款及細則,請選取核取方塊,然後按一下「連線」。
在「建立觸發條件」部分,按一下「建立觸發條件」:
- 新增觸發條件名稱,例如
push-to-branch
。請記下這個觸發條件名稱,後續步驟會用到。 - 在「事件」部分中,選取「推送至分支版本」。
- 在「來源」部分中,選取「Branch」(分支) 欄位中的「
.*
」。 - 點選「建立」。
- 新增觸發條件名稱,例如
Cloud Build GitHub 應用程式現在已設定完畢,您的 GitHub 存放區也已連結至您的 Google Cloud 專案。從現在開始,對 GitHub 存放區所做的變更都會觸發 Cloud Build 執行作業,而該作業會使用 GitHub 檢查功能將結果回報給 GitHub。
在新的功能分支版本中變更您的環境設定
到目前為止,您已完成了大部分的環境設定。現在請在您的開發環境中進行一些程式碼變更。
在 GitHub 中,前往分支的存放區的主頁面。
https://github.com/YOUR_GITHUB_USERNAME/solutions-terraform-cloudbuild-gitops
確認您位於
dev
分支版本中。如要開啟檔案以進行編輯,請前往
modules/firewall/main.tf
檔案,然後按一下鉛筆圖示。在第 30 行中,修正
target_tags
欄位中的"http-server2"
錯字。此值必須是
"http-server"
。在頁面底部新增一個修訂訊息,例如「修正 http 防火牆目標」,然後選取「Create a new branch for this commit and start a pull request」(針對這個修訂版本建立新的分支版本,並開始提取要求)。
按一下「提議變更」。
在下一頁中,按一下 [Create pull request] (建立提取要求) 以開啟包含您的變更的新提取要求。
開啟提取要求後,系統就會自動啟動 Cloud Build 工作。
按一下 [Show all checks] (顯示所有檢查結果),然後等待檢查作業變成綠色。
按一下「詳細資料」,即可查看更多資訊,包括「查看有關 Google Cloud Build 的更多詳細資料」連結中的
terraform plan
輸出內容。
請勿合併提取要求。
請注意,Cloud Build 工作會執行在
cloudbuild.yaml
檔案中定義的管道。如先前所述,這個管道會根據要擷取的分支版本而有不同的行為。該版本會檢查$BRANCH_NAME
變數是否與任何環境資料夾相符。如果相符的話,Cloud Build 會針對該環境執行terraform plan
。否則,Cloud Build 會針對所有環境執行terraform plan
,以確保建議的變更適用於所有環境。如果這些計畫中有任何一個無法執行,則該版本會失敗。同樣地,
terraform apply
指令會針對環境分支版本執行,但是在任何其他情況下,它都會完全遭到忽略。在本節中,您已將程式碼變更提交至新的分支版本,因此系統未將任何基礎架構部署套用至您的 Google Cloud 專案。在合併分支版本之前先強制 Cloud Build 成功執行
如要確保只有在個別 Cloud Build 作業成功執行時才能進行合併,請繼續執行以下步驟:
在 GitHub 中,前往分支的存放區的主頁面。
https://github.com/YOUR_GITHUB_USERNAME/solutions-terraform-cloudbuild-gitops
在您的存放區名稱之下,按一下 [Settings] (設定)。
在左側選單中,按一下 [Branches] (分支版本)。
在「Branch protection rules」(分支版本保護規則) 之下,按一下 [Add rule] (新增規則)。
在「Branch name pattern」(分支版本名稱模式) 中,輸入
dev
。在「Protect matching branches」(保護相符分支版本) 區段中,選取「Require status checks to pass before merging」(必須通過狀態檢查才能合併)。
搜尋您先前建立的 Cloud Build 觸發條件名稱。
點選「建立」。
重複執行步驟 3 至 7,將「Branch name pattern」(分支版本名稱模式) 設為「
prod
」。
這項設定對於保護
dev
和prod
分支版本很重要。也就是說,必須先將修訂版本推送至另一個分支版本,然後才能將它們合併至受保護的分支版本。在本教學課程中,保護措施規定 Cloud Build 作業必須成功執行後才能進行合併。將變更推行至開發環境
您有一個正在等待合併的提取要求。現在可以將您想要的狀態套用至您的
dev
環境了。在 GitHub 中,前往分支的存放區的主頁面。
https://github.com/YOUR_GITHUB_USERNAME/solutions-terraform-cloudbuild-gitops
在您的存放區名稱之下,按一下 [Pull requests] (提取要求)。
按一下您剛剛建立的提取要求。
按一下 [Merge pull request] (合併提取要求),然後按一下 [Confirm merge] (確認合併)。
檢查是否已觸發新的 Cloud Build:
開啟版本並檢查記錄檔。
當該版本完成後,您會看到如下的內容:
Step #3 - "tf apply": external_ip = EXTERNAL_IP_VALUE Step #3 - "tf apply": firewall_rule = dev-allow-http Step #3 - "tf apply": instance_name = dev-apache2-instance Step #3 - "tf apply": network = dev Step #3 - "tf apply": subnet = dev-subnet-01
複製
EXTERNAL_IP_VALUE
並在網路瀏覽器中開啟該網址。http://EXTERNAL_IP_VALUE
這項佈建可能需要幾秒鐘的時間來啟動 VM 和傳播防火牆規則。最後,您會在網路瀏覽器中看到「Environment: dev」(環境:dev)。
前往 Cloud Storage bucket 中的 Terraform 狀態檔案。
https://storage.cloud.google.com/PROJECT_ID-tfstate/env/dev/default.tfstate
將變更推行至實際工作環境
現在您的開發環境已經過全面測試,接下來便可以將基礎架構程式碼推行至實際工作環境了。
在 GitHub 中,前往分支的存放區的主頁面。
https://github.com/YOUR_GITHUB_USERNAME/solutions-terraform-cloudbuild-gitops
在您的存放區名稱之下,按一下 [Pull requests] (提取要求)。
按一下 [New pull request] (新的提取要求)。
針對「base repository」(基本存放區) 選取您剛剛分支的存放區。
在「base」中,從自己的基本存放區選取
prod
。如要比較,請選取dev
。按一下 [Create pull request]。
針對「title」(標題) 輸入標題 (例如
Promoting networking changes
),然後按一下「Create pull request」(建立提取要求)。查看建議的變更,包括 Cloud Build 中的
terraform plan
詳細資料,然後按一下「Merge pull request」(合併提取要求)。按一下 [Confirm merge] (確認合併)。
在 Google Cloud 控制台中,開啟「Build History」(版本記錄) 頁面,以查看正在套用至實際工作環境的變更:
等待版本完成,然後檢查記錄檔。
在記錄檔的末尾,您會看到如下的內容:
Step #3 - "tf apply": external_ip = EXTERNAL_IP_VALUE Step #3 - "tf apply": firewall_rule = prod-allow-http Step #3 - "tf apply": instance_name = prod-apache2-instance Step #3 - "tf apply": network = prod Step #3 - "tf apply": subnet = prod-subnet-01
複製
EXTERNAL_IP_VALUE
並在網路瀏覽器中開啟該網址。http://EXTERNAL_IP_VALUE
這項佈建可能需要幾秒鐘的時間來啟動 VM 和傳播防火牆規則。最後,您會在網路瀏覽器中看到「Environment: prod」(環境:prod)。
前往 Cloud Storage bucket 中的 Terraform 狀態檔案。
https://storage.cloud.google.com/PROJECT_ID-tfstate/env/prod/default.tfstate
您已成功在 Cloud Build 中設定無伺服器基礎架構即程式碼管道。日後,您可以嘗試以下做法:
- 針對不同的用途新增部署。
- 建立其他環境以反映您的需求。
- 針對每個環境使用一個專案,而不是針對每個環境使用一個虛擬私人雲端。
清除所用資源
完成本教學課程後,請清除您在Google Cloud 上建立的資源,這樣日後就不需再為這些資源付費。
刪除專案
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
刪除 GitHub 存放區
如要避免 GitHub 存放區封鎖新的提取要求,可以刪除分支版本保護規則:
- 在 GitHub 中,前往分支的存放區的主頁面。
- 在您的存放區名稱之下,按一下 [Settings] (設定)。
- 在左側選單中,按一下 [Branches] (分支版本)。
- 在「Branch protection rules」(分支版本保護規則) 部分下方,按一下
dev
和prod
列的「Delete」(刪除) 按鈕。
您也可以選擇從 GitHub 完全解除安裝 Cloud Build 應用程式:
前往 GitHub 的「應用程式」設定。
在「Installed GitHub Apps」分頁中,按一下「Cloud Build」列中的「Configure」。然後在「危險區域」部分,按一下「解除安裝 Google Cloud Builder」列中的「解除安裝」按鈕。
頁面頂端會顯示「一切就緒。系統已將解除安裝 Google Cloud Build 的工作加入佇列。
在「已授權的 GitHub 應用程式」分頁中,按一下「Google Cloud Build」列的「撤銷」按鈕,然後在彈出式視窗中點選「我瞭解,要撤銷存取權」。
如要刪除 GitHub 存放區,請按照下列步驟操作:
- 在 GitHub 中,前往分支的存放區的主頁面。
- 在您的存放區名稱之下,按一下 [Settings] (設定)。
- 向下捲動至「危險區域」。
- 按一下「Delete this repository」(刪除這個存放區),然後按照確認步驟操作。
後續步驟
- 考慮使用 Cloud Foundation Toolkit 範本,在Google Cloud中快速打造出可重複使用的企業級基礎環境。
- 觀看 2019 年 Next 大會的將 Cloud Build 基礎架構即程式碼管道大規模應用於可重複使用的環境 Google Cloud 影片,以瞭解本教學課程中所述的 GitOps 工作流程。
- 查看使用 Cloud Build 以 Git 運作方式持續推送軟體更新教學課程。
- 查看更進階的 Cloud Build 功能:設定建構步驟的順序、建構、測試和部署構件以及建立自訂建構步驟。
- 請參閱這篇網誌,瞭解如何使用 Cloud Build 確保 Terraform 部署作業的規模和法規遵循。
- 參閱DevOps相關資源。
- 進一步瞭解與本教學課程相關的開發運作能力:
- 進行開發運作快速檢驗,瞭解貴機構在業界的表現排名。
設定您的 GitHub 存放區
在本教學課程中,您將使用單一 Git 存放區來定義您的雲端基礎架構。您可以讓不同的分支版本對應至不同的環境,藉此來自動化調度管理這個基礎架構:
有了這個基礎架構,您隨時可以參考存放區,以瞭解每個環境中的預期設定,並透過先將變更合併至 dev
環境的方式來提出新的變更。然後,您可以透過將 dev
分支版本合併至後續的 prod
分支版本中來推行變更。
如要開始操作,請建立 solutions-terraform-cloudbuild-gitops 存放區的分支。
這個存放區中的程式碼結構如下:
為確保提議的變更適用於所有環境,系統會針對所有 environments
子資料夾執行 terraform init
和 terraform plan
。合併提取要求之前,您可以先查看計畫,確保不會將存取權授予未經授權的實體。
設定 Terraform 以將狀態儲存在 Cloud Storage 值區中
根據預設,Terraform 會將狀態儲存在名為 terraform.tfstate
的本機檔案中。這個預設設定會使得團隊難以使用 Terraform,尤其是當有許多使用者同時執行 Terraform,且每部機器對於目前的基礎架構都有自己的理解時。
為了協助您避免這類問題,本節會設定指向 Cloud Storage 值區的遠端狀態。遠端狀態是後端的一項功能,在本教學課程中會在 backend.tf
檔案中進行設定,例如:
在以下步驟中,您將建立一個 Cloud Storage bucket,並變更一些檔案以指向您的新 bucket 和 Google Cloud 專案。