本教學課程說明如何使用熱門的 GitOps 方法,透過 Terraform 和 Cloud Build 以程式碼的形式管理基礎架構。GitOps 一詞最初是由 Weaveworks 所提出,其主要概念是使用 Git 存放區儲存您想要的環境狀態。Terraform 是 HashiCorp 的工具,可讓您使用程式碼,以可預測的方式建立、變更及改善雲端基礎架構。在本教學課程中,您將使用 Cloud Build (持續整合服務 Google Cloud ) 自動將 Terraform 資訊清單套用至環境。
本教學課程適用於正在尋找一流的策略,以便以可預測的方式變更基礎架構的開發人員和操作人員。本文假設您熟悉 Google Cloud、Linux 和 GitHub。
《DevOps 現狀》報告指出,有幾項能力可提升軟體推送效能。本教學課程將協助您瞭解下列功能:
架構
為了說明本教學課程如何將 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 bucket 中。
- 將權限授予您的 Cloud Build 服務帳戶。
- 將 Cloud Build 連線至您的 GitHub 存放區。
- 在功能分支版本中變更您的環境設定。
- 將變更推行至開發環境。
- 將變更升級至正式環境。
費用
在本文件中,您將使用下列 Google Cloud計費元件:
如要根據預測用量估算費用,請使用 Pricing Calculator。
完成本文所述工作後,您可以刪除建立的資源,避免繼續計費,詳情請參閱「清除所用資源」一節。
必要條件
- 登入 Google Cloud 帳戶。如果您是 Google Cloud新手,歡迎 建立帳戶,親自體驗產品的實際應用成效。新客戶還能獲得價值 $300 美元的免費抵免額,能用於執行、測試及部署工作負載。
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify 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.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
-
在 Google Cloud 控制台中啟用 Cloud Shell。
Google Cloud 控制台底部會開啟 Cloud Shell 工作階段,並顯示指令列提示。Cloud Shell 是已安裝 Google Cloud CLI 的殼層環境,並已設定適用於您目前專案的值。工作階段可能要幾秒鐘的時間才能初始化。
- 在 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"
設定您的 GitHub 存放區
在本教學課程中,您將使用單一 Git 存放區來定義您的雲端基礎架構。您可以讓不同的分支版本對應至不同的環境,藉此來自動化調度管理這個基礎架構:
dev分支包含套用至開發環境的最新變更。prod分支包含套用至正式環境的最新變更。
有了這項基礎架構,您隨時可以參照存放區,瞭解每個環境中預期的設定,並先將變更合併至 dev 環境,然後提議新的變更。接著,將 dev 分支合併到後續的 prod 分支,即可升級變更。
如要開始使用,請分叉 solutions-terraform-cloudbuild-gitops 存放區。
- 在 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 initterraform planterraform apply
如果是任何其他分支版本,系統會執行以下步驟:
- 所有
environments子資料夾的terraform init - 所有
environments子資料夾的terraform plan
- 所有
為確保所提議的變更適用於所有環境,請針對所有 environments 子資料夾執行 terraform init 和 terraform plan。合併提取要求前,您可以查看方案,確保存取權不會授予未經授權的實體。
設定 Terraform,將狀態儲存在 Cloud Storage bucket 中
根據預設,Terraform 會將狀態儲存在名為 terraform.tfstate 的本機檔案中。這個預設設定會使得團隊難以使用 Terraform,尤其是當有許多使用者同時執行 Terraform,且每部機器對於目前的基礎架構都有自己的理解時。
為協助您避免這類問題,本節將設定指向 Cloud Storage bucket 的遠端狀態。遠端狀態是後端的功能,在本教學課程中,遠端狀態是在 backend.tf 檔案中設定,例如:
在後續步驟中,您將建立 Cloud Storage bucket,並變更幾個檔案,指向新的 bucket 和專案。 Google Cloud
在 Cloud Shell 中建立 Cloud Storage bucket:
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](https://cloud.google.com/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 服務帳戶執行 Terraform 指令碼來管理 Google Cloud 資源,請授予該帳戶專案的適當存取權。為簡化作業,本教學課程會授予專案編輯者存取權。但如果專案編輯者角色具有廣泛的權限,在正式環境中,您必須遵循貴公司的 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 專案,這樣每當您建立新分支或將程式碼推送至 GitHub 時,Cloud Build 就會自動套用 Terraform 資訊清單。
以下步驟說明如何只為
solutions-terraform-cloudbuild-gitops存放區安裝應用程式,但您也可以選擇為更多或所有存放區安裝應用程式。前往 Cloud Build 應用程式的「GitHub Marketplace」(GitHub 市集) 頁面:
- 如果是第一次在 GitHub 中設定應用程式,請按一下頁面底部的「Setup with Google Cloud Build」(使用 Google Cloud Build 設定)。然後按一下「Grant this app access to your GitHub account」(授予這個應用程式 GitHub 帳戶存取權)。
- 如果不是第一次在 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。請記下這個觸發條件名稱,後續步驟會用到。 - 在「事件」部分,選取「推送至分支版本」。
- 在「來源」部分,選取「分支」欄位中的
.*。 - 點選「建立」。
- 新增觸發條件名稱,例如
Cloud Build GitHub 應用程式已設定完成,GitHub 存放區也已連結至 Google Cloud 專案。從現在起,GitHub 存放區的變更會觸發 Cloud Build 執行作業,並使用 GitHub Checks 將結果回報給 GitHub。
在新的功能分支版本中變更您的環境設定
到目前為止,您已完成了大部分的環境設定。現在請在您的開發環境中進行一些程式碼變更。
在 GitHub 中,前往分支的存放區的主頁面。
https://github.com/YOUR_GITHUB_USERNAME/solutions-terraform-cloudbuild-gitops
確認您位於
dev分支。如要開啟檔案進行編輯,請前往
modules/firewall/main.tf檔案,然後按一下鉛筆圖示。在第 30 行,修正
target_tags欄位中的"http-server2"錯字。此值必須是
"http-server"。在頁面底部新增提交訊息,例如「Fixing http firewall target」,然後選取「Create a new branch for this commit and start a pull request」(為這次提交建立新分支並啟動提取要求)。
按一下「提議變更」。
在下一頁中,按一下 [Create pull request] (建立提取要求) 以開啟包含您的變更的新提取要求。
開啟提取要求後,系統會自動啟動 Cloud Build 工作。
按一下 [Show all checks] (顯示所有檢查結果),然後等待檢查作業變成綠色。
按一下「詳細資料」即可查看更多資訊,包括
terraform plan的輸出內容 (位於「在 Google Cloud Build 中查看更多詳細資料」連結)。
請勿合併提取要求。
請注意,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] (設定)。
按一下左選單中的「分店」。
在「Branch protection rules」(分支版本保護規則) 之下,按一下 [Add rule] (新增規則)。
在「Branch name pattern」(分支名稱模式) 中輸入
dev。在「保護相符分支版本」部分,選取「必須通過狀態檢查才能合併」。
搜尋先前建立的 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」。
前往 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。
按一下「建立提取要求」。
在「title」中輸入標題 (例如
Promoting networking changes),然後按一下「Create pull request」。查看建議的變更,包括 Cloud Build 的
terraform plan詳細資料,然後按一下「Merge pull request」(合併提取要求)。按一下 [Confirm merge] (確認合併)。
在 Google Cloud 控制台中開啟「建構記錄」頁面,查看變更是否已套用至正式環境:
等待版本完成,然後檢查記錄檔。
在記錄檔的末尾,您會看到如下的內容:
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」。
前往 Cloud Storage bucket 中的 Terraform 狀態檔案。
https://storage.cloud.google.com/PROJECT_ID-tfstate/env/prod/default.tfstate
您已成功在 Cloud Build 中設定無伺服器基礎架構即程式碼管道。日後,您可以嘗試以下做法:
- 針對不同的用途新增部署。
- 建立其他環境以反映您的需求。
- 針對每個環境使用一個專案,而不是針對每個環境使用一個虛擬私人雲端。
清除所用資源
完成本教學課程後,請清除您在Google Cloud 上建立的資源,以免日後產生相關費用。
刪除專案
- 前往 Google Cloud 控制台的「Manage resources」(管理資源) 頁面。
- 在專案清單中選取要刪除的專案,然後點選「Delete」(刪除)。
- 在對話方塊中輸入專案 ID,然後按一下 [Shut down] (關閉) 以刪除專案。
刪除 GitHub 存放區
如要避免封鎖 GitHub 存放區中的新提取要求,可以刪除分支保護規則:
- 在 GitHub 中,前往您建立分支的存放區主頁面。
- 在您的存放區名稱之下,按一下 [Settings] (設定)。
- 按一下左選單中的「分店」。
- 在「Branch protection rules」(分支保護規則) 部分下方,點選
dev和prod列的「Delete」(刪除) 按鈕。
您也可以從 GitHub 完全解除安裝 Cloud Build 應用程式:
前往 GitHub 的「Applications」設定。
在「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 大會的這部影片 Google Cloud ,瞭解如何運用 Cloud Build 基礎架構即程式碼管道,大規模建立可重複使用的環境,並參考本教學課程中說明的 GitOps 工作流程。
- 請參閱「使用 Cloud Build,以 GitOps 模式持續推送軟體更新」教學課程。
- 進一步瞭解 Cloud Build 進階功能:設定建構步驟的順序、建構、測試及部署構件,以及建立自訂建構步驟。
- 請參閱「使用 Cloud Build 確保 Terraform 部署作業的規模和法規遵循」這篇網誌。
- 參閱DevOps相關資源。
- 進一步瞭解本教學課程相關的開發運作能力:
- 進行開發運作快速檢驗,瞭解貴機構在業界的表現。