在現代軟體開發流程中,持續整合與持續交付(CI/CD)至關重要。Jenkins 作為常用的 CI/CD 工具,其高用性佈署對於保障開發流程的穩定性尤為重要。本文將探討如何利用基礎設施即程式碼(IaC)工具,如 Packer 和 Terraform,在多雲端平台上實作 Jenkins 的高用性佈署。首先,我們會使用 Packer 建立標準化的 Jenkins 虛擬機器映像,確保跨平台一致性。接著,利用 Terraform 在 AWS、Azure、GCP 和 DigitalOcean 等平台上佈署和管理 Jenkins 叢集,並整合自動擴充套件功能,以動態調整 worker 節點數量,提升資源利用率並降低營運成本。最後,我們將驗證跨雲端平台佈署的一致性,確保無論選擇哪個雲端供應商,都能維持相同的 Jenkins 服務品質。
在多雲端平台上佈署高用性 Jenkins
在前一章中,我們已經瞭解如何使用 Terraform 在 AWS 上佈署具有高用性、安全性及彈性的 Jenkins 叢集。本章將延續相同的目標,透過相同的工具和流程,在不同的雲端服務供應商(如 Microsoft Azure、Google Cloud Platform 和 DigitalOcean)上實作基礎設施層級的自動化與快速佈署。
使用 Packer 自動化 Jenkins 虛擬機器的建置過程
為了確保跨雲端平台的一致性,我們將使用 Packer 來自動建立 Jenkins 虛擬機器映像。Packer 允許我們使用相同的範本,在不同的雲端供應商上建立相同的 Jenkins 機器映像,從而簡化了佈署流程並減少了錯誤。
建立 Jenkins 機器映像的步驟
準備 Packer 範本:首先,我們需要準備一個 Packer 範本,該範本定義了 Jenkins 虛擬機器的組態,包括安裝所需的軟體和設定。
使用 Packer 建置映像:接著,使用 Packer 根據範本建立 Jenkins 機器映像。這個過程包括了安裝 Jenkins、組態必要的外掛和設定安全引數等。
佈署到多雲端平台:一旦 Jenkins 機器映像建立完成,我們就可以將其佈署到不同的雲端平台上,如 Azure、GCP 和 DigitalOcean。
在 Azure、GCP 和 DigitalOcean 上佈署 Jenkins 叢集
本章將介紹如何在上述三個雲端平台上佈署 Jenkins 叢集。我們將使用 Terraform 來管理基礎設施資源,利用前面使用 Packer 建立的 Jenkins 機器映像來佈署 worker 節點。
自動擴充套件 Jenkins Worker 節點
為了提高資源利用率並降低成本,我們將實作根據需求自動建立和刪除 Jenkins worker 節點的功能。這需要組態雲端平台的自動擴充套件功能,以及在 Jenkins 中設定相關的 slave 節點組態。
跨雲端平台的一致性佈署
本章的一個重點是展示如何使用相同的 Packer 範本和 Terraform 組態,在不同的雲端平台上實作一致的 Jenkins 叢集佈署。這種方法不僅提高了佈署的效率,也使得跨雲端的管理變得更加簡單。
重點回顧
使用 Packer 自動建立跨雲端平台的 Jenkins 虛擬機器映像。 利用 Terraform 在 Azure、GCP 和 DigitalOcean 上佈署 Jenkins 叢集。 實作根據需求自動擴充套件 Jenkins worker 節點的功能,以降低成本。 使用相同的組態和範本實作跨雲端平台的一致性佈署。
透過本章的學習,讀者將能夠掌握在多雲端環境下佈署和管理高用性 Jenkins 叢集的技能,並瞭解如何利用 IaC 工具簡化這一過程。
在多雲端供應商上佈署高用性Jenkins
6.1 Google Cloud Platform
眾所周知,AWS 的網頁控制檯並非最具使用者友善性的介面。Google Cloud Platform(GCP)憑藉著更好的使用者經驗成功超越 AWS。GCP 提供一系列服務,從運算、網路到提取-轉換-載入(ETL)管道,因其較低的增量計費(10 分鐘而非 1 小時)而比競爭對手(AWS)便宜 25%。
此外,GCP 在大資料方面擁有更多專業知識,提供如 BigQuery(https://cloud.google.com/bigquery)、Cloud Bigtable(https://cloud.google.com/bigtable)和 Dataflow(https://cloud.google.com/dataflow)等服務。此外,您可以在 Kubernetes 上執行容器工作負載,並使用 TensorFlow 佈署機器學習(ML)模型;Kubernetes 和 TensorFlow 均源自 Google。然而,相比於市場上最老牌、最成熟的雲端供應商 AWS,GCP 仍然缺乏一些功能。
那麼,為什麼要在 GCP 上使用 Jenkins?您可以與 Kubernetes 實作無縫整合;藉助 Google Kubernetes Engine(GKE)等服務,您可以執行短暫的 Jenkins 工作節點,確保每次構建都在乾淨的環境中執行。另一個原因是對 Docker 容器的原生支援,以及使用 Container Registry 來儲存和管理在 CI/CD 管道中構建的 Docker 映像。此外,您還可以獲得整合的安全性和合規性,詳細報告構建工件的漏洞影響和可用的修復方案。最後,當您使用 GCP 虛擬機器(VM)來加速 Jenkins 構建時,您只需按使用量付費。
話雖如此,讓我們開始使用 Terraform 和 Packer 在 GCP 上佈署 Jenkins 叢集。首先,使用 Gmail 地址註冊一個免費帳戶(https://console.cloud.google.com/)。您將自動獲得為期 12 個月的免費試用和 300 美元的信用額度。您需要提供信用卡資訊,但直到試用期結束或您用完 300 美元信用額度之前,您不會被額外收費。
構建 Jenkins VM 映像
為了讓 Packer 構建自定義映像,它需要與 GCP 互動。因此,我們需要為 Packer 建立一個專用的服務帳戶,以授權其存取 Google API 中的資源。
前往 GCP 控制檯,導航至 IAM & Admin 儀錶板,如圖 6.1 所示。在服務帳戶部分,建立一個名為 Packer 的新服務帳戶,然後點選「建立」按鈕。
此圖示顯示了在 GCP 中建立 Packer 服務帳戶的過程。
將 Project Owner 角色指派給服務帳戶(或者至少選擇 Compute Engine Instance Admin 和 Service Account User 角色),然後點選「繼續」按鈕,如圖 6.2 所示。
每個服務帳戶都與一個金鑰(JSON 或 P12 格式)相關聯,該金鑰由 GCP 管理。此金鑰用於服務間的身份驗證。透過點選「建立金鑰」按鈕下載 JSON 金鑰。服務帳戶檔案被建立並下載到電腦上。將此 JSON 檔案複製並放置在安全的資料夾中。確保 Google Compute Engine API 在您的 GCP 專案中已啟用。
使用 Packer 建立 Jenkins Worker 映像
更新第 4 章提供的 Jenkins Worker 的 Packer 範本檔案,或者從 GitHub 存函式庫中的 chapter6/gcp/packer/worker/setup.sh 複製並貼上內容。
{
"variables": {
"service_account": "SERVICE ACCOUNT JSON FILE PATH",
"project": "GCP PROJECT ID",
"zone": "GCP ZONE ID"
},
"builders": [
{
"type": "googlecompute",
"image_name": "jenkins-worker",
"account_file": "{{user `service_account`}}",
"project_id": "{{user `project`}}",
"source_image_family": "centos-8",
"ssh_username": "packer",
"zone": "{{user `zone`}}"
}
],
"provisioners": [
{
"type": "shell",
"script": "./setup.sh",
"execute_command": "sudo -E -S sh '{{ .Path }}'"
}
]
}
內容解密:
variables部分定義了在執行時將被提供的變數,例如服務帳戶 JSON 檔案路徑、GCP 專案 ID 和區域 ID。builders部分使用googlecompute建構器在 CentOS 8 的基礎上建立一個名為jenkins-worker的映像。provisioners部分執行一個 shell 指令碼./setup.sh,以安裝所需的依賴項,如 Git、JDK 和 Docker。
Packer 的強大之處在於利用範本檔案來建立獨立於目標平台的相同虛擬機器映像。因此,我們可以使用相同的範本檔案為 AWS、GCP 或 Azure 建立相同的 Jenkins 映像。
在提供了所有必要的變數之後,執行 packer build 命令。輸出應該類別似於以下內容,為了簡潔起見已被縮短:
此圖示顯示了 CentOS 基礎映像來自 GCE 映像。
您也可以使用 gcloud compute images list 命令列出特定 GCP 地點中可用的映像。
圖表翻譯:
此圖示展示了在 GCP 中建立 Jenkins Worker 映像的流程,包括建立服務帳戶、設定許可權和下載 JSON 金鑰等步驟。
在Google Cloud Platform上佈署高用性Jenkins
自動化Jenkins映象建置
首先,我們需要在Google Cloud Platform(GCP)上建立Jenkins worker和master的機器映象。這個過程是透過Packer工具實作自動化的。
Jenkins Worker映象建置
在完成建置程式後,Jenkins worker的映象應該可以在Google Compute Engine(GCE)控制檯中看到,如圖6.4所示。
Jenkins Master映象建置
接下來,我們將使用與第4章清單4.12中相同的藍圖範本來建立Jenkins master機器映象。唯一的區別是在builders部分使用了googlecompute。
{
"variables": {
"service_account": "服務帳戶JSON路徑",
"project": "專案ID",
"zone": "區域ID",
"ssh_key": "私有SSH金鑰路徑"
},
"builders": [
{
"type": "googlecompute",
"image_name": "jenkins-master-v22041",
"account_file": "{{user `service_account`}}",
"project_id": "{{user `project`}}",
"source_image_family": "centos-8",
"ssh_username": "packer",
"zone": "{{user `zone`}}"
}
],
"provisioners": [
...
]
}
內容解密:
- 上述JSON組態定義了一個Packer範本,用於建立Jenkins master的GCP映象。
variables部分定義了所需的變數,如服務帳戶路徑、專案ID、區域ID和SSH金鑰路徑。builders部分指定了使用googlecompute建置器,並設定了映象名稱、帳戶檔案、專案ID、來源映象家族、SSH使用者名稱和區域。provisioners部分用於執行進一步的組態和安裝步驟。
在執行建置之前,先透過以下命令驗證範本:
packer validate template.json
然後,使用以下命令進行建置:
packer build template.json
建置完成後,可以在GCP控制檯的「Images」部分找到新建立的映象,如圖6.5所示。
使用Terraform組態GCP網路
在本文中,我們將使用Terraform來佈署虛擬機器例項,並根據前面建立的映象建立一個私有的網路環境。
建立Terraform組態檔案
首先,建立一個terraform.tf檔案,並宣告Google作為提供者,同時組態它使用前面建立的服務帳戶。
provider "google" {
credentials = file(var.credentials_path)
project = var.project
region = var.region
}
內容解密:
- 這段HCL程式碼組態了Google Cloud提供者。
credentials屬性指定了服務帳戶的JSON檔案路徑。project和region屬性分別指定了預設的專案和區域。
接下來,在network.tf檔案中定義一個區域性的VPC網路。
resource "google_compute_network" "management" {
name = var.network_name
auto_create_subnetworks = false
routing_mode = "REGIONAL"
}
內容解密:
- 這段程式碼定義了一個名為
management的VPC網路。 auto_create_subnetworks設為false表示不會自動建立子網路。routing_mode設為"REGIONAL"表示這是一個區域性的網路。
然後,宣告兩個公有和兩個私有的子網路。
resource "google_compute_subnetwork" "public_subnets" {
count = var.public_subnets_count
name = "public-10-0-${count.index * 2 + 1}-0"
ip_cidr_range = "10.0.${count.index * 2 + 1}.0/24"
region = var.region
network = google_compute_network.management.self_link
}
resource "google_compute_subnetwork" "private_subnets" {
count = var.private_subnets_count
name = "private-10-0-${count.index * 2}-0"
ip_cidr_range = "10.0.${count.index * 2}.0/24"
region = var.region
network = google_compute_network.management.self_link
private_ip_google_access = true
}
內容解密:
- 這兩段程式碼分別定義了公有和私有的子網路。
count屬性根據變數public_subnets_count和private_subnets_count的值來決定建立的子網路數量。- 每個子網路都有其自己的CIDR區塊,且位於不同的區域以實作高用性。
在執行terraform apply之前,先宣告變數並初始化Terraform。
terraform init
terraform plan --var-file=variables.tfvars
terraform apply --var-file=variables.tfvars
完成後,您應該可以看到如圖6.8所示的私有網路環境。