隨著系統規模的增長,維護系統的穩定性和可用性變得越來越具有挑戰性。本文介紹的自我修復系統,旨在透過自動化監控和修復機制,提高系統的容錯能力和穩定性。系統的核心元件包括 Consul、Jenkins 和 Ansible。Consul 負責服務發現和健康檢查,Jenkins 負責 CI/CD 流程,而 Ansible 則負責自動化組態管理。透過整合這些工具,我們可以實作對硬體資源和服務的全面監控,並在出現問題時自動觸發修復程式,例如重新佈署服務或傳送告警通知。
自我修復系統的設定與硬體監控
環境設定
首先,我們需要建立四個虛擬機器(VMs),並使用Vagrant來管理它們。我們將建立一個名為cd的節點,並使用Ansible來組態其他節點。同時,cd節點也將託管Jenkins,這將是自我修復過程中的重要部分。其他三個虛擬機器將形成Swarm叢集。
vagrant up cd swarm-master swarm-node-1 swarm-node-2
啟動所有虛擬機器後,我們可以透過SSH連線到cd節點,並使用Ansible來設定Swarm叢集。
vagrant ssh cd
ansible-playbook /vagrant/ansible/swarm.yml -i /vagrant/ansible/hosts/prod
接下來,我們需要組態cd伺服器上的Jenkins。
ansible-playbook /vagrant/ansible/jenkins-node-swarm.yml -i /vagrant/ansible/hosts/prod
ansible-playbook /vagrant/ansible/jenkins.yml --extra-vars "main_job_src=service-healing-config.xml" -c local
使用Consul進行健康檢查和監控
Consul允許我們傳送指令來執行週期性的服務檢查或整個節點的檢查。它不帶有預定義的檢查,而是執行指令碼、執行HTTP請求或等待TTL訊號。我們將建立一些指令碼來執行硬體檢查,例如檢查磁碟使用率。
df -h
內容解密:
df -h命令用於顯示檔案系統的磁碟使用情況,-h選項使其以人類可讀的格式輸出。- 輸出結果包含了檔案系統的大小、已用空間、可用空間、使用百分比和掛載點等資訊。
我們需要過濾df命令的輸出,以提取根目錄(/)的使用情況,包括磁碟大小、已用空間和使用百分比。
set -- $(df -h | awk '$NF=="/"{print $2" "$3" "$5}')
total=$1
used=$2
used_percent=${3::-1}
printf "Disk Usage: %s/%s (%s%%)\n" $used $total $used_percent
內容解密:
awk '$NF=="/"{print $2" "$3" "$5}'用於過濾出根目錄(/)的行,並列印出第二、第三和第五列(分別代表磁碟大小、已用空間和使用百分比)。- 將提取的值賦給
total、used和used_percent變數。 used_percent=${3::-1}移除使用百分比後的百分號(%)。printf陳述式用於格式化輸出磁碟使用情況。
建立Consul檢查指令碼
在swarm-master節點上建立一個指令碼,用於檢查磁碟使用率並根據閾值傳回相應的離開碼。
echo '#!/usr/bin/env bash
set -- $(df -h | awk '"'"'$NF=="/"{print $2" "$3" "$5}'"'"')
total=$1
used=$2
used_percent=${3::-1}
printf "Disk Usage: %s/%s (%s%%)\n" $used $total $used_percent
if [ $used_percent -gt 95 ]; then
exit 2
elif [ $used_percent -gt 80 ]; then
exit 1
else
exit 0
fi' | sudo tee /data/consul/scripts/disk.sh
sudo chmod +x /data/consul/scripts/disk.sh
內容解密:
- 指令碼首先提取根目錄的磁碟使用資訊。
- 根據使用百分比與設定的閾值(95%和80%)比較,傳回不同的離開碼(2表示錯誤,1表示警告,0表示正常)。
- 將指令碼寫入
/data/consul/scripts/disk.sh並賦予執行許可權。
組態Consul檢查
建立一個JSON檔案來定義Consul檢查,該檢查將執行我們剛建立的指令碼。
echo '{
"checks": [
{
"id": "disk",
"name": "Disk utilization",
"notes": "Critical 95% util, warning 80% util",
"script": "/data/consul/scripts/disk.sh",
"interval": "10s"
}
]
}' | sudo tee /data/consul/config/consul_check.json
sudo killall -HUP consul
內容解密:
- JSON檔案定義了一個名為“Disk utilization”的檢查,指令碼路徑為
/data/consul/scripts/disk.sh,並設定每10秒執行一次。 - 使用
sudo killall -HUP consul重新載入Consul組態,使新的檢查生效。
結果驗證
存取Consul的UI(http://10.100.192.200:8500/ui/),導航到節點頁面並選擇swarm-master節點,可以看到我們建立的“Disk utilization”檢查的狀態。
自我修復系統中的 Consul Watcher 機制實作
在前面的章節中,我們已經瞭解如何在 Consul 中新增檢查機制。現在,我們需要定義當檢查失敗時應該執行的動作。這可以透過 Consul Watches 來實作。Consul Watches 提供了一種機制,讓我們能夠根據不同的事件型別建立相應的處理方案。
Consul Watches 的型別
Consul 支援七種不同型別的 Watches:
- key:監控特定的 KV 對
- keyprefix:監控 KV 儲存中的字首
- services:監控可用的服務列表
- nodes:監控節點列表
- service:監控特定服務的例項
- checks:監控健康檢查的值
- event:監控自定義的使用者事件
這些 Watch 型別在不同的情況下非常有用,並且共同提供了一個非常全面的框架,用於建立自我修復和容錯的系統。
建立 Consul Watcher 指令碼
我們將專注於 checks 型別,因為它允許我們利用之前建立的硬碟檢查。讓我們先建立一個指令碼,該指令碼將由 Consul Watcher 執行。
#!/usr/bin/env bash
RED="\033[0;31m"
NC="\033[0;0m"
read -r JSON
echo "Consul watch request:"
echo "$JSON"
STATUS_ARRAY=($(echo "$JSON" | jq -r ".[].Status"))
CHECK_ID_ARRAY=($(echo "$JSON" | jq -r ".[].CheckID"))
LENGTH=${#STATUS_ARRAY[*]}
for (( i=0; i<=$(( $LENGTH -1 )); i++ ))
do
CHECK_ID=${CHECK_ID_ARRAY[$i]}
STATUS=${STATUS_ARRAY[$i]}
echo -e "${RED}Triggering Jenkins job http://10.100.198.200:8080/job/hardware-notification/build${NC}"
curl -X POST http://10.100.198.200:8080/job/hardware-notification/build \
--data-urlencode json="{\"parameter\": [{\"name\":\"checkId\", \"value\":\"$CHECK_ID\"}, {\"name\":\"status\", \"value\":\"$STATUS\"}]}"
done
內容解密:
- 指令碼初始設定:定義了
RED和NC變數,用於在輸出中以紅色顯示關鍵資訊。 - 讀取 Consul 輸入:讀取 Consul 傳入的 JSON 資料並儲存到
JSON變數中。 - 解析 JSON 資料:使用
jq工具解析 JSON 資料,提取Status和CheckID值,並分別儲存到STATUS_ARRAY和CHECK_ID_ARRAY陣列中。 - 迴圈處理檢查結果:遍歷陣列中的每個元素,根據
CheckID和Status的值,向 Jenkins 傳送 POST 請求,觸發hardware-notification作業的構建。
建立 Watcher 指令碼檔案
echo '#!/usr/bin/env bash
# ... (指令碼內容與上述相同)
' | sudo tee /data/consul/scripts/manage_watches.sh
sudo chmod +x /data/consul/scripts/manage_watches.sh
定義 Consul Watches 設定
{
"watches": [
{
"type": "checks",
"state": "warning",
"handler": "/data/consul/scripts/manage_watches.sh >>/data/consul/logs/watches.log"
},
{
"type": "checks",
"state": "critical",
"handler": "/data/consul/scripts/manage_watches.sh >>/data/consul/logs/watches.log"
}
]
}
內容解密:
- Watches 設定結構:定義了一個包含兩個 Watch 的設定,分別用於監控
warning和critical狀態的檢查。 - 處理指令碼:當檢查狀態符合設定的條件時,執行
manage_watches.sh指令碼,並將輸出記錄到watches.log檔案中。
建立 Watches 設定檔案
echo '{
"watches": [
{
"type": "checks",
"state": "warning",
"handler": "/data/consul/scripts/manage_watches.sh >>/data/consul/logs/watches.log"
},
{
"type": "checks",
"state": "critical",
"handler": "/data/consul/scripts/manage_watches.sh >>/data/consul/logs/watches.log"
}
]
}' | sudo tee /data/consul/config/watches.json
修改硬碟檢查門檻值並重新載入 Consul
sudo sed -i "s/80/2/" /data/consul/scripts/disk.sh
sudo killall -HUP consul
練習:修改 Jenkins 作業以刪除日誌檔案
修改 hardware-notification Jenkins 作業,使其在 checkId 值為 disk 時刪除日誌檔案。在伺服器上建立模擬日誌檔案並手動執行該作業。完成後,確認日誌檔案是否已被刪除。
自動修復系統的硬體與服務監控實作
在前面的章節中,我們已經成功地在 swarm-master 節點上設定了 Consul 健康檢查與監控硬體資源。然而,這種手動設定的方式不僅耗時,而且難以擴充套件到整個叢集。因此,本章節將介紹如何使用 Ansible 自動化設定 Consul 健康檢查與監控硬體資源,並進一步擴充套件到服務監控。
使用 Ansible 自動化設定 Consul 健康檢查
首先,我們需要執行 Ansible playbook 來自動化設定 Consul 健康檢查。相關的 playbook 是 swarm-healing.yml,它與之前的 swarm.yml playbook 類別似,但額外使用了 consul-healing 角色。
vagrant ssh cd
ansible-playbook /vagrant/ansible/swarm-healing.yml -i /vagrant/ansible/hosts/prod
內容解密:
vagrant ssh cd:登入 Vagrant 虛擬機器。ansible-playbook命令用於執行 Ansible playbook。/vagrant/ansible/swarm-healing.yml是 playbook 的路徑。-i /vagrant/ansible/hosts/prod指定了 inventory 檔案的路徑,用於定義目標主機。
swarm-healing.yml playbook 的內容如下:
- hosts: swarm
remote_user: vagrant
serial: 1
sudo: yes
vars:
- debian_version: vivid
- docker_cfg_dest: /lib/systemd/system/docker.service
- is_systemd: true
roles:
- common
- docker
- consul-healing
- swarm
- registrator
內容解密:
hosts: swarm指定了目標主機群組。remote_user: vagrant指定了遠端使用者名稱。serial: 1表示 Ansible 將逐一執行任務,而不是平行執行。sudo: yes允許 Ansible 使用 sudo 許可權執行任務。vars部分定義了變數,例如 Debian 版本和 Docker 設定檔的路徑。roles部分列出了將要執行的角色,包括consul-healing。
Consul 健康檢查的運作
在執行完 Ansible playbook 後,我們可以檢查 Consul UI 以確認健康檢查是否已經設定成功。請開啟 http://10.100.192.200:8500/ui/#/dc1/nodes,並點選任意節點。你將會看到每個節點都有 Disk utilization 和 Memory utilization 的監控專案。
從硬體監控到服務監控
雖然監控硬體資源是有用的,但真正的價值在於監控服務。在本章節中,我們將介紹如何使用 Consul 監控服務。首先,我們需要佈署 books-ms 容器。請開啟 Jenkins job books-ms,點選 Branch Indexing 連結,並執行 Run Now。Jenkins 將會偵測到 swarm 分支,並執行第一次建置。
@startuml
skinparam backgroundColor #FEFEFE
title 自我修復系統Consul監控與自動化佈署
|開發者|
start
:提交程式碼;
:推送到 Git;
|CI 系統|
:觸發建置;
:執行單元測試;
:程式碼品質檢查;
if (測試通過?) then (是)
:建置容器映像;
:推送到 Registry;
else (否)
:通知開發者;
stop
endif
|CD 系統|
:部署到測試環境;
:執行整合測試;
if (驗證通過?) then (是)
:部署到生產環境;
:健康檢查;
:完成部署;
else (否)
:回滾變更;
endif
stop
@enduml此圖示說明瞭從 Jenkins 建置 books-ms 到 Consul 監控服務的流程。
在服務監控方面,我們可以使用 HTTP 檢查代替指令碼檢查。Consul 將會定期傳送請求到我們的服務,並將失敗的結果傳送到 watches。
自我修復系統中的服務檢查與自動化佈署
在自我修復系統中,服務檢查與自動化佈署是確保系統高用性的關鍵環節。本文將探討如何透過Consul、Jenkins和Ansible實作服務檢查和自動化佈署。
服務檢查的定義與重要性
服務檢查是監控系統健康狀態的重要手段。與硬體檢查不同,服務檢查的定義可能因服務而異,因此將檢查定義儲存在服務程式碼倉函式庫中可以提高靈活性。這樣,服務團隊可以自由定義適合其服務的檢查專案。
使用Consul Template定義服務檢查
Consul Template是一種用於生成Consul組態檔案的範本語言。透過Consul Template,可以定義服務檢查的詳細資訊,包括檢查的ID、名稱、HTTP檢查地址、檢查間隔和超時時間等。
{
"service": {
"name": "books-ms",
"tags": ["service"],
"port": 80,
"address": "{{key "proxy/ip"}}",
"checks": [{
"id": "api",
"name": "HTTP on port 80",
"http": "http://{{key "proxy/ip"}}/api/v1/books",
"interval": "10s",
"timeout": "1s"
}]
}
}
內容解密:
"service"定義了服務的基本資訊,包括名稱、標籤、埠和地址。"checks"定義了對服務的檢查,包括檢查ID、名稱、HTTP檢查地址、檢查間隔和超時時間。- 使用Consul Template的
{{key "proxy/ip"}}動態取得代理伺服器的IP地址。
Jenkinsfile中的自動化佈署流程
Jenkinsfile定義了自動化佈署的流程,包括構建、測試、佈署和更新Consul檢查組態等步驟。其中,updateChecks函式負責更新Consul的檢查組態。
node("cd") {
def serviceName = "books-ms"
// ...
def flow = load "/data/scripts/workflow-util.groovy"
// ...
flow.updateChecks(serviceName, swarmNode)
}
內容解密:
node("cd")指定了執行Jenkins任務的節點。load "/data/scripts/workflow-util.groovy"載入了包含自動化流程的Groovy指令碼。flow.updateChecks(serviceName, swarmNode)呼叫了更新Consul檢查組態的函式。
updateChecks函式的實作
updateChecks函式負責將Consul Template檔案複製到Swarm Master節點,並執行Consul Template命令生成Consul組態。
def updateChecks(serviceName, swarmNode) {
stage "Update checks"
stash includes: 'consul_check.ctmpl', name: 'consul-check'
node(swarmNode) {
unstash 'consul-check'
sh "sudo consul-template -consul localhost:8500 \
-template 'consul_check.ctmpl:/data/consul/config/${serviceName}.json:killall -HUP consul' \
-once"
}
}
內容解密:
stash和unstash用於在不同節點之間傳遞檔案。consul-template命令根據範本生成Consul組態檔案,並在完成後傳送HUP訊號給Consul程式以使其重新載入組態。
Consul檢查觸發的自動化回應
當Consul檢測到服務失敗時,會觸發相應的Jenkins任務進行自動化回應。對於硬體故障,會觸發hardware-notification任務;對於服務故障,則會觸發service-redeploy任務。
if [[ "$CHECK_ID" == "mem" || "$CHECK_ID" == "disk" ]]; then
curl -X POST http://{{ jenkins_ip }}:8080/job/hardware-notification/build \
--data-urlencode json="{\"parameter\": [{\"name\":\"checkId\", \"value\":\"$CHECK_ID\"}, {\"name\":\"status\", \"value\":\"$STATUS\"}]}"
else
curl -X POST http://{{ jenkins_ip }}:8080/job/service-redeploy/buildWithParameters?serviceName=${SERVICE_ID}
fi
內容解密:
- 根據檢查ID的不同,決定觸發不同的Jenkins任務。
- 使用
curl命令向Jenkins傳送POST請求以觸發任務。