隨著雲端原生應用和微服務架構的普及,自動化 CI/CD 流程變得至關重要。本文將引導讀者如何在 DigitalOcean 上快速搭建一個高用性的 Jenkins 叢集,並探討如何在 Jenkins 上實踐微服務的持續整合與佈署。我們將使用 Packer 建立客製化的 Jenkins Master 和 Worker 映像檔,再利用 Terraform 自動化佈署和管理 DigitalOcean 基礎設施,最後示範如何組態 Jenkins 多分支Pipeline以實作自動化建置、測試和佈署流程。

在多雲端平台佈署高用性 Jenkins 叢集:DigitalOcean 篇

在雲端運算的世界中,DigitalOcean 是一個相對較新的玩家,但它憑藉簡潔的介面、實惠的價格和針對開發者設計的虛擬機器(Droplet)迅速獲得了開發者和新創公司的青睞。本章節將介紹如何使用 Packer 和 Terraform 在 DigitalOcean 上佈署一個高用性的 Jenkins 叢集。

為什麼選擇 DigitalOcean?

與 AWS、Google Cloud 和 Azure 這些巨頭相比,DigitalOcean 的最大優勢在於其簡單性和成本效益。DigitalOcean 提供了虛擬機器(稱為 Droplet),沒有複雜的服務目錄,讓開發者能夠快速建立和管理自己的伺服器。此外,DigitalOcean 的價格相對較低,使其成為初創企業和小型專案的理想選擇。

使用 Packer 建立 Jenkins DigitalOcean 映像檔

要使用 Packer 與 DigitalOcean 互動,首先需要生成一個 DigitalOcean API Token。這個 Token 可以在 DigitalOcean 的 Applications & API 頁面中生成。

建立 Jenkins Worker 映像檔

{
  "variables": {
    "api_token": "YOUR_DIGITALOCEAN_API_TOKEN",
    "region": "YOUR_DIGITALOCEAN_REGION"
  },
  "builders": [
    {
      "type": "digitalocean",
      "api_token": "{{user `api_token`}}",
      "image": "centos-8-x64",
      "region": "{{user `region`}}",
      "size": "512mb",
      "ssh_username": "root",
      "snapshot_name": "jenkins-worker"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "script": "./setup.sh",
      "execute_command": "sudo -E -S sh '{{ .Path }}'"
    }
  ]
}

內容解密:

  • variables 部分定義了需要使用者輸入的變數,如 api_tokenregion
  • builders 部分指定了使用 digitalocean 構建器,並根據設定的變數建立一個 CentOS 8 的 Droplet。
  • provisioners 部分執行了一個 shell 指令碼 ./setup.sh 來安裝必要的工具和組態 Jenkins worker。

建立 Jenkins Master 映像檔

同樣地,可以更新 Jenkins master 的範本來使用 digitalocean 構建器。這個範本會建立一個包含 Jenkins master 組態的映像檔。

{
  "variables": {
    "api_token": "YOUR_DIGITALOCEAN_API_TOKEN",
    "region": "YOUR_DIGITALOCEAN_REGION",
    "ssh_key": "YOUR_PRIVATE_SSH_KEY_FILE"
  },
  "builders": [
    {
      "type": "digitalocean",
      "api_token": "{{user `api_token`}}",
      "image": "centos-8-x64",
      "region": "{{user `region`}}",
      "size": "2gb",
      "ssh_username": "root",
      "snapshot_name": "jenkins-master-2.204.1"
    }
  ],
  "provisioners": [
    # 省略部分內容
  ]
}

內容解密:

  • 這裡同樣使用了 digitalocean 構建器,但大小改為 2gb 以滿足 Jenkins master 的需求。
  • Provisioners 部分會建立 Jenkins 認證,並組態 SSH 金鑰以便 Jenkins master 能夠與 worker 連線。

使用 Terraform 佈署 Jenkins Droplet

首先,需要定義 terraform.tf 檔案並宣告 DigitalOcean 為提供者。

provider "digitalocean" {
  token = var.token
}

然後,定義一個 digitalocean_droplet 資源來佈署 Jenkins master。

data "digitalocean_image" "jenkins_master_image" {
  name = var.jenkins_master_image
}

resource "digitalocean_droplet" "jenkins-master" {
  # 設定引數
}

圖表翻譯:

此圖示呈現了使用 Terraform 在 DigitalOcean 上佈署 Jenkins master Droplet 的流程。

在DigitalOcean上佈署Jenkins Master與Worker節點

佈署Jenkins Master節點

首先,我們需要在DigitalOcean上建立一個Jenkins Master節點。為此,我們將使用Terraform來定義相關資源。

Jenkins Master Droplet組態

resource "digitalocean_droplet" "jenkins_master" {
  name   = "jenkins-master"
  image  = data.digitalocean_image.jenkins_master_image.id
  region = var.region
  size   = "s-1vcpu-2gb"
  ssh_keys = [var.ssh_fingerprint]
}

內容解密:

此段程式碼定義了一個名為jenkins-master的Droplet,使用之前透過Packer建立的Jenkins Master映像,位於指定的區域,組態為1vCPU和2GB RAM。同時,它還增加了SSH公鑰以實作無密碼登入。

防火牆組態

接下來,我們需要為Jenkins Master組態防火牆規則,以允許必要的入站流量。

resource "digitalocean_firewall" "jenkins_master_firewall" {
  name        = "jenkins-master-firewall"
  droplet_ids = [digitalocean_droplet.jenkins_master.id]

  inbound_rule {
    protocol         = "tcp"
    port_range       = "22"
    source_addresses = ["0.0.0.0/0", "::/0"]
  }

  inbound_rule {
    protocol         = "tcp"
    port_range       = "8080"
    source_addresses = ["0.0.0.0/0", "::/0"]
  }

  # 省略出站規則組態...
}

內容解密:

此防火牆規則允許從任何地方存取Jenkins Master的SSH(22埠)和Web介面(8080埠)。出站規則允許Droplet與外界進行通訊。

輸出Jenkins Master的IP地址

為了方便存取Jenkins Master,我們將其IP地址輸出到控制檯。

output "master" {
  value = digitalocean_droplet.jenkins_master.ipv4_address
}

內容解密:

此輸出將顯示Jenkins Master Droplet的IPv4地址,方便使用者透過瀏覽器存取Jenkins介面。

佈署Jenkins Worker節點

為了擴充套件Jenkins叢集,我們需要佈署多個Worker節點。

Jenkins Worker Droplet組態

resource "digitalocean_droplet" "jenkins_workers" {
  count = var.jenkins_workers_count
  name   = "jenkins-worker-${count.index}"
  image  = data.digitalocean_image.jenkins_worker_image.id
  region = var.region
  size   = "s-1vcpu-2gb"
  ssh_keys = [var.ssh_fingerprint]
  user_data = data.template_file.jenkins_worker_startup_script.rendered
  depends_on = [digitalocean_droplet.jenkins_master]
}

內容解密:

此段程式碼根據jenkins_workers_count變數的值建立多個Jenkins Worker Droplet。每個Worker使用相同的映像和組態,並在啟動時執行一個指令碼以自動加入Jenkins叢集。

Jenkins Worker防火牆組態

resource "digitalocean_firewall" "jenkins_workers_firewall" {
  name        = "jenkins-workers-firewall"
  droplet_ids = [for worker in digitalocean_droplet.jenkins_workers : worker.id]

  inbound_rule {
    protocol         = "tcp"
    port_range       = "22"
    source_droplet_ids = [digitalocean_droplet.jenkins_master.id]
  }
}

內容解密:

此防火牆規則允許Jenkins Master透過SSH連線到Worker節點,從而實作Master與Worker之間的通訊。

在多雲環境中佈署高可用性Jenkins叢集與微服務的持續整合流程

微服務架構下的持續整合挑戰與解決方案

在現代軟體開發中,微服務架構因其模組化、可擴充套件性等優勢而被廣泛採用。然而,這種架構也帶來了持續整合(CI)和持續佈署(CD)的挑戰。本章將探討如何在Jenkins上為微服務定義CI流程,並介紹相關的最佳實踐。

微服務的持續整合流程

持續整合是一種軟體開發實踐,旨在透過自動化測試和建置來驗證程式碼變更。對於微服務架構而言,CI流程至關重要,因為它能夠確保各個服務之間的相容性和整體系統的穩定性。

CI流程階段

  1. 程式碼簽出:從版本控制系統中簽出最新的程式碼。
  2. 單元測試:執行單元測試以驗證個別元件的功能。
  3. 品質測試:進行更全面的測試,包括整合測試和效能測試。
  4. 安全性檢查:掃描程式碼和依賴項中的已知漏洞。
  5. 建置:編譯程式碼並建立可佈署的構件。
  6. 推播:將構件推播到遠端倉函式庫進行版本控制和佈署。

使用Jenkins實作CI流程

Jenkins是一個流行的開源自動化伺服器,支援多種外掛和整合工具。對於微服務架構,可以使用Jenkins的多分支Pipeline外掛來實作CI流程。

Jenkins多分支Pipeline組態
pipeline {
    agent any
    stages {
        stage('Checkout') {
            steps {
                git 'https://github.com/your-repo/your-project.git'
            }
        }
        stage('Test') {
            steps {
                sh 'make test'
            }
        }
        stage('Build') {
            steps {
                sh 'make build'
            }
        }
        stage('Push') {
            steps {
                sh 'make push'
            }
        }
    }
}

內容解密:

  1. pipeline 區塊定義了整個Pipeline的結構。
  2. agent any 表示Jenkins可以在任何可用的代理節點上執行此Pipeline。
  3. stages 區塊包含了Pipeline的不同階段,如簽出、測試、建置和推播。
  4. 每個 stage 內包含一個或多個 steps,這些步驟定義了在該階段要執行的具體操作。
  5. sh 步驟用於執行 shell 命令,例如執行測試、建置和推播構件。

微服務應使用案例項:Watchlist市場

為了演示如何為微服務定義CI/CD流程,我們使用了一個名為Watchlist的網頁應用。該應用允許使用者瀏覽史上最偉大的100部電影,並將其新增到自己的觀影清單中。

Watchlist應用架構

Watchlist應用由多個微服務組成,包括:

  • Loader服務(Python):負責讀取包含電影清單的JSON檔案,並將每個電影專案推播到訊息佇列(如Amazon SQS)。
  • Parser服務(Golang):訂閱SQS並從IMDb網站抓取電影資訊,將後設資料儲存到MongoDB。
  • Store服務:透過RESTful API提供資料,並透過Marketplace UI進行視覺化展示。

架構圖示

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title DigitalOcean佈署高可用性Jenkins叢集

package "Docker 架構" {
    actor "開發者" as dev

    package "Docker Engine" {
        component [Docker Daemon] as daemon
        component [Docker CLI] as cli
        component [REST API] as api
    }

    package "容器運行時" {
        component [containerd] as containerd
        component [runc] as runc
    }

    package "儲存" {
        database [Images] as images
        database [Volumes] as volumes
        database [Networks] as networks
    }

    cloud "Registry" as registry
}

dev --> cli : 命令操作
cli --> api : API 呼叫
api --> daemon : 處理請求
daemon --> containerd : 容器管理
containerd --> runc : 執行容器
daemon --> images : 映像檔管理
daemon --> registry : 拉取/推送
daemon --> volumes : 資料持久化
daemon --> networks : 網路配置

@enduml

圖表翻譯: 此圖示展示了Watchlist應用的架構流程。Loader服務將電影清單推播到SQS,Parser服務消費這些訊息並抓取電影資訊,最終將資料儲存到MongoDB。Store服務提供RESTful API供Marketplace UI展示資料。