隨著雲端原生應用和微服務架構的普及,自動化 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_token和region。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流程階段
- 程式碼簽出:從版本控制系統中簽出最新的程式碼。
- 單元測試:執行單元測試以驗證個別元件的功能。
- 品質測試:進行更全面的測試,包括整合測試和效能測試。
- 安全性檢查:掃描程式碼和依賴項中的已知漏洞。
- 建置:編譯程式碼並建立可佈署的構件。
- 推播:將構件推播到遠端倉函式庫進行版本控制和佈署。
使用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'
}
}
}
}
內容解密:
pipeline區塊定義了整個Pipeline的結構。agent any表示Jenkins可以在任何可用的代理節點上執行此Pipeline。stages區塊包含了Pipeline的不同階段,如簽出、測試、建置和推播。- 每個
stage內包含一個或多個steps,這些步驟定義了在該階段要執行的具體操作。 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展示資料。