返回文章列表

GCP高用性Jenkins佈署實踐

本文介紹如何在 Google Cloud Platform 上佈署高用性的 Jenkins,包含使用堡壘機連線私有 Jenkins 例項、設定負載平衡器確保 Jenkins Master 高用性,以及利使用案例項群組和自動擴充套件政策管理 Jenkins Worker 節點,並搭配 Terraform

雲端運算 DevOps

在 GCP 環境中佈署 Jenkins 時,安全性與高用性至關重要。本文將引導你設定堡壘機,作為連線私有 Jenkins Master 的安全通道。同時,我們會利用 GCP 的負載平衡服務,將流量分發到健康的 Jenkins Master,確保服務持續執行。此外,為了最佳化資源使用,我們將使用案例項群組和自動擴充套件政策,根據負載動態調整 Jenkins Worker 的數量,提升建置效率並降低成本。最後,我們將使用 Terraform 進行基礎設施程式碼的管理,實作自動化佈署和管理。

在Google Cloud Platform上佈署高用性Jenkins

建立堡壘主機(Bastion Host)以存取私有Jenkins例項

為了能夠SSH到私有的Jenkins例項,我們將佈署一個堡壘主機。首先,建立bastion.tf檔案並定義一個虛擬機器例項,該例項位於公有子網路中,並具有靜態IPv4公有IP地址。

resource "google_compute_address" "static" {
  name = "ipv4-address"
}

resource "google_compute_instance" "bastion" {
  project      = var.project
  name         = "bastion"
  machine_type = var.bastion_machine_type
  zone         = var.zone
  tags         = ["bastion"]

  boot_disk {
    initialize_params {
      image = var.machine_image
    }
  }

  network_interface {
    subnetwork = google_compute_subnetwork.public_subnets[0].self_link
    access_config {
      nat_ip = google_compute_address.static.address
    }
  }

  metadata = {
    ssh-keys = "${var.ssh_user}:${file(var.ssh_public_key)}"
  }
}

內容解密:

  • google_compute_address資源用於建立一個靜態IPv4地址。
  • google_compute_instance資源定義了一個名為"bastion"的虛擬機器例項。
  • metadata屬性用於上傳公鑰,以便能夠使用SSH連線到堡壘主機。

設定防火牆規則以允許SSH連線

在同一個檔案中,建立一個防火牆規則以允許從任何地方SSH到堡壘主機。

resource "google_compute_firewall" "allow_ssl_to_bastion" {
  project = var.project
  name    = "allow-ssl-to-bastion"
  network = google_compute_network.management.self_link

  allow {
    protocol = "tcp"
    ports    = ["22"]
  }

  source_ranges = ["0.0.0.0/0"]
  source_tags   = ["bastion"]
}

內容解密:

  • google_compute_firewall資源定義了一個防火牆規則。
  • 此規則允許從任何IP地址(0.0.0.0/0)透過TCP協定的22埠(SSH)存取堡壘主機。

輸出堡壘主機的公有IP地址

建立一個outputs.tf檔案,並使用Terraform的輸出變數來輸出堡壘虛擬機器的公有IP地址。

output "bastion" {
  value = "${google_compute_instance.bastion.network_interface.0.access_config.0.nat_ip}"
}

內容解密:

  • output用於輸出堡壘主機的公有IP地址。

在Google Compute Engine上佈署Jenkins

現在,我們將在私有子網路中佈署一個根據Jenkins master映像的虛擬機器例項,並暴露一個公有負載平衡器來存取Jenkins的Web儀錶板。

建立一個jenkins_master.tf檔案,並定義一個私有的計算例項。

resource "google_compute_instance" "jenkins_master" {
  project      = var.project
  name         = "jenkins-master"
  machine_type = var.jenkins_master_machine_type
  zone         = var.zone
  tags         = ["jenkins-ssh", "jenkins-web"]
  depends_on   = [google_compute_instance.bastion]

  boot_disk {
    initialize_params {
      image = var.jenkins_master_machine_image
    }
  }

  network_interface {
    subnetwork = google_compute_subnetwork.private_subnets[0].self_link
  }

  metadata = {
    ssh-keys = "${var.ssh_user}:${file(var.ssh_public_key)}"
  }
}

內容解密:

  • google_compute_instance資源定義了一個名為"jenkins-master"的虛擬機器例項。
  • 此例項位於私有子網路中。

設定防火牆規則以允許存取Jenkins

定義防火牆規則以允許從堡壘主機SSH到Jenkins主機,並允許從任何地方存取Jenkins的Web介面。

resource "google_compute_firewall" "allow_ssh_to_jenkins" {
  project = var.project
  name    = "allow-ssh-to-jenkins"
  network = google_compute_network.management.self_link

  allow {
    protocol = "tcp"
    ports    = ["22"]
  }

  source_tags = ["bastion", "jenkins-ssh"]
}

resource "google_compute_firewall" "allow_access_to_ui" {
  project = var.project
  name    = "allow-access-to-jenkins-web"
  network = google_compute_network.management.self_link

  allow {
    protocol = "tcp"
    ports    = ["8080"]
  }

  source_ranges = ["0.0.0.0/0"]
  source_tags   = ["jenkins-web"]
}

內容解密:

  • 第一個防火牆規則允許從堡壘主機SSH到Jenkins主機。
  • 第二個防火牆規則允許從任何地方存取Jenkins的Web介面(埠8080)。

建立負載平衡器

首先,定義一個目標池資源,該資源定義了應該接收傳入流量的例項。

resource "google_compute_target_pool" "jenkins-master-target-pool" {
  name          = "jenkins-master-target-pool"
  session_affinity = "NONE"
  region        = var.region
  instances     = [
    google_compute_instance.jenkins_master.self_link
  ]
  health_checks = [
    google_compute_http_health_check.jenkins_master_health_check.name
  ]
}

內容解密:

  • google_compute_target_pool資源定義了一個目標池。
  • 此目標池包含Jenkins主機例項,並與健康檢查相關聯。

在多雲端提供者上佈署高用性 Jenkins

使用 Google Cloud Platform 佈署 Jenkins

設定負載平衡器

要確保 Jenkins 主節點的高用性,需要設定一個對外公開的負載平衡器。這個負載平衡器會將流量轉發到 Jenkins 主節點,只有當主節點運作正常並準備好接收流量時才會進行轉發。因此,需要定義一個健康檢查資源,以特定的頻率向 Jenkins 主節點的 8080 埠傳送健康檢查請求。

resource "google_compute_http_health_check" "jenkins_master_health_check" {
  name                = "jenkins-master-health-check"
  request_path        = "/"
  port                = "8080"
  timeout_sec         = 4
  check_interval_sec  = 5
}

設定轉發規則

接下來,定義一個轉發規則,將流量導向之前定義的目標池。

resource "google_compute_forwarding_rule" "jenkins_master_forwarding_rule" {
  name                  = "jenkins-master-forwarding-rule"
  region                = var.region
  load_balancing_scheme = "EXTERNAL"
  target                = google_compute_target_pool.jenkins-master-target-pool.self_link
  port_range            = "8080"
  ip_protocol           = "TCP"
}

輸出負載平衡器的 IP 位址

為了顯示負載平衡器的 IP 位址,在 outputs.tf 檔案中建立一個輸出區段:

output "jenkins" {
  value = google_compute_forwarding_rule.jenkins_master_forwarding_rule.ip_address
}

執行 terraform output 命令,即可在控制檯上顯示 Jenkins 負載平衡器的 IP 位址。

#### 內容解密:

此段落程式碼定義了一個對外公開的負載平衡器,並設定了健康檢查和轉發規則,以確保 Jenkins 主節點的高用性。透過 terraform apply 命令佈署後,可以在瀏覽器中輸入負載平衡器的 IP 位址和埠號(8080)來存取 Jenkins 的歡迎畫面。

在 GCP 上啟動自動管理的 Jenkins 工作節點

Jenkins 的強大功能之一是能夠將建置作業分配到多個工作節點上。為了避免在工作節點閒置時支付額外的資源費用,將在例項群組中佈署 Jenkins 工作節點,並設定自動擴充套件政策,以根據 CPU 使用率等指標觸發擴充套件或縮減事件。

建立 Jenkins 工作節點範本

首先,建立一個 jenkins_workers.tf 檔案,並定義用於建立 Jenkins 工作節點組態的例項範本。

resource "google_compute_instance_template" "jenkins-worker-template" {
  name_prefix          = "jenkins-worker"
  description          = "Jenkins workers instances template"
  region               = var.region
  tags                 = ["jenkins-worker"]
  machine_type         = var.jenkins_worker_machine_type
  metadata_startup_script = data.template_file.jenkins_worker_startup_script.rendered
  
  disk {
    source_image = var.jenkins_worker_machine_image
    disk_size_gb = 50
  }
  
  network_interface {
    network    = google_compute_network.management.self_link
    subnetwork = google_compute_subnetwork.private_subnets[0].self_link
  }
  
  metadata = {
    ssh-keys = "${var.ssh_user}:${file(var.ssh_public_key)}"
  }
}

#### 內容解密:

此段落程式碼定義了一個例項範本,用於建立 Jenkins 工作節點。範本中指定了機器型別、啟動指令碼、磁碟來源映像和網路介面等組態。啟動指令碼會在虛擬機器首次啟動時執行,使其自動加入 Jenkins 群集。

設定防火牆規則以允許 SSH 連線

定義一個防火牆規則,以允許從 Jenkins 主節點和堡壘主機到 Jenkins 工作節點的 SSH 連線。

resource "google_compute_firewall" "allow_ssh_to_worker" {
  project = var.project
  name    = "allow-ssh-to-worker"
  network = google_compute_network.management.self_link
}

#### 內容解密:

此防火牆規則允許從指定的來源到 Jenkins 工作節點的 SSH 連線,確保可以遠端管理這些工作節點。

圖表翻譯:

此圖示呈現了在 Google Cloud Platform 上佈署 Jenkins 群集的架構。首先,設定了一個對外公開的負載平衡器,以確保 Jenkins 主節點的高用性。然後,建立了一個例項範本,用於建立 Jenkins 工作節點,並設定了自動擴充套件政策,以根據 CPU 使用率等指標動態調整工作節點的數量。最後,定義了防火牆規則,以允許必要的網路連線。透過這些步驟,可以在 GCP 上成功佈署一個高用性的 Jenkins 環境。

在多雲供應商上佈署高用性 Jenkins

6.2 Microsoft Azure

Microsoft Azure 和 AWS 類別似,提供多種雲端服務。然而,使用 Microsoft 軟體的組織通常具有企業協定,可獲得軟體折扣。這些組織在使用 Azure 時通常可以獲得顯著的優惠。

6.2.1 在 Azure 中建立黃金 Jenkins 虛擬機器映像

在建置過程中,Packer 會建立臨時的 Azure 資源。因此,它需要被授權與 Azure API 互動。

建立 Azure 服務主體(SP)

建立具有建立和管理資源許可權的 Azure 服務主體(SP)。SP 代表存取 Azure 資源的應用程式。它由客戶端 ID(即應用程式 ID)識別,可以使用密碼或憑證進行身份驗證。

$sp = New-AzADServicePrincipal -DisplayName "PackerServicePrincipal"
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($sp.Secret)
$plainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
New-AzRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $sp.ApplicationId

內容解密:

此段 PowerShell 指令碼用於建立 Azure 服務主體。首先,建立一個名為 “PackerServicePrincipal” 的服務主體,然後將其密碼轉換為純文字格式,最後為該服務主體分配「Contributor」角色,以便其能夠建立和管理 Azure 資源。

執行以下命令輸出密碼和應用程式 ID:

$plainPassword
$sp.ApplicationId

儲存應用程式 ID 和密碼以供稍後使用。

建立 Jenkins Worker 映像

要建立 Jenkins Worker 映像,請建立一個 template.json 檔案。在該範本中,您定義了執行實際建置過程的建置器和提供者。Packer 有一個名為 azure-arm 的 Azure 建置器,允許您定義 Azure 映像。

{
  "variables": {
    "subscription_id": "YOUR SUBSCRIPTION ID",
    "client_id": "YOUR CLIENT ID",
    "client_secret": "YOUR CLIENT SECRET",
    "tenant_id": "YOUR TENANT ID",
    "resource_group": "RESOURCE GROUP NAME",
    "location": "LOCATION NAME"
  },
  "builders": [
    {
      "type": "azure-arm",
      <!-- 其他設定 -->
    }
  ]
}

內容解密:

此 JSON 範本檔案定義了 Packer 建置器的變數和設定。其中,variables 部分定義了 Azure 的訂閱 ID、客戶端 ID、客戶端密碼、租戶 ID、資源群組名稱和位置名稱。builders 部分定義了使用 azure-arm 建置器來建立 Azure 映像。您需要將 YOUR SUBSCRIPTION IDYOUR CLIENT IDYOUR CLIENT SECRETYOUR TENANT IDRESOURCE GROUP NAMELOCATION NAME 替換為您的實際 Azure 資訊。

圖表翻譯:

此圖表展示了在 Azure 中建立 Jenkins Worker 映像的流程。首先,建立 Azure 服務主體,然後使用 Packer 的 azure-arm 建置器建立映像。

Azure 中建立 Jenkins Worker 映像流程圖

@startuml
skinparam backgroundColor #FEFEFE

title GCP高用性Jenkins佈署實踐

|開發者|
start
:提交程式碼;
:推送到 Git;

|CI 系統|
:觸發建置;
:執行單元測試;
:程式碼品質檢查;

if (測試通過?) then (是)
    :建置容器映像;
    :推送到 Registry;
else (否)
    :通知開發者;
    stop
endif

|CD 系統|
:部署到測試環境;
:執行整合測試;

if (驗證通過?) then (是)
    :部署到生產環境;
    :健康檢查;
    :完成部署;
else (否)
    :回滾變更;
endif

stop

@enduml

此圖表清晰地展示了在 Azure 中建立 Jenkins Worker 映像所需的步驟,包括建立服務主體、定義 template.json 檔案和使用 Packer 建立映像。