使用 Consul Template 達成 Nginx 設定檔的動態更新

你會不會覺得有些重複的工作很麻煩? 例如替主機更新檔案、調整設定檔等等。手動維護非常繁瑣耗時且容易出錯,而且通常又不是只有一台主機或一個設定檔,基本上都是一堆,帳號密碼都記不住了更別說每個步驟。

今天要介紹的 Consul Template 能夠讓我們只要在網頁、API、指令中觸發資料變更,就馬上變更設定檔,並執行你訂好的指令,自動化完成。例如藍綠部屬(Blue-green deployment),透過 Jenkins 或是其他 CI/CD 工具呼叫 API,把 Consul 上的資料調整,替換連接埠(port),自動修改設定檔並執行指令讓 Nginx 之類的反向代理伺服器熱重載,達成自動無縫切換伺服器的功能。
註: Consul 和 Consul Template 是同一間公司的兩套開源產品,本文皆會示範。

使用 Docker 安裝 Consul

註: Consul 有許多安裝方式,官方推薦是建立至少建立 3 個組成集群,提升穩定和增加容錯。Consul 通常會部屬在伺服器,本文會使用 Docker 最快速完成佈署。下一篇將會介紹使用 ACL 驗證、資料備份等。

Docker 一行安裝完畢:

docker run -d --name=consul -p 8500:8500 hashicorp/consul
    

如果遇到問題可以使用下面的指令查看 Consul log

docker logs consul
    

使用瀏覽器開啟 Consul 控制台:

http://localhost:8500
    


透過網頁 UI 新增內容

點選左側的 Key/Value > Create

在 Key of folder 的地方輸入 鍵,若結尾使用斜線(/)就會被視為是資料夾,可以有多層。 在這裡示範輸入 k1 和 v1 ,然後點選 Save

新增成功

透過 API 新增/更新

使用 PUT 方法就可以用呼叫 API 的方式新增/更新內容。下面的範例是 key=my-key, value=my-val,一樣可以使用斜線(/)來達成多層。

curl:
    
curl --request PUT \
     --data "my-val" \
     "http://localhost:8500/v1/kv/my-key"
    

補充: 如果要附加 token 可以加上: -H "X-Consul-Token:4321abcd-1234-0408-a123-fedcbaabcdef"

透過 API 查詢內容

    
curl "http://localhost:8500/v1/kv/my-key"
    

回應範例:
    
[
  {
    "LockIndex": 0,
    "Key": "my-key",
    "Flags": 0,
    "Value": "my-val",
    "CreateIndex": 49,
    "ModifyIndex": 49
  }
]
    

如果只想要實際內容可以使用 ?raw
    
curl "http://localhost:8500/v1/kv/my-key?raw"
    

透過指令新增/更新

因為我們放在 Docker 內,要更新就沒有那麼方便,不過也是一行就可以解決的事情:
    
docker exec -it consul consul kv put k2 v2
    

取得內容:
    
docker exec -it consul consul kv get k2
    

安裝 Consul Template

這裡就不使用 Docker 了,因為要存取檔案,如果檔案數量一多要掛載就非常麻煩,而且只要一個執行檔就可以了。
註:建議是佈署到 Linux 上,在 Windows 中有許多指令不容易使用。

先到官網下載 Consul Template 檔案,點選最新版本,筆者這裡選擇 consul-template_0.31.0

依照作業系統選擇檔案下載,筆者這裡下載的是 consul-template_0.31.0_windows_386.zip

下載完成解壓縮後,Windows 在執行檔的路徑下開啟終端機,就可以直接呼叫 .\consul-template.exe 這個執行檔了(可能需要使用相對或絕對路徑),如果有需要也可以把它所在的資料夾路徑加入到環境變數中,就可以直接透過 consul-template 指令執行。
延伸閱讀: Windows 11 設定環境變數 位置 而 Linux 可以直接移動到 /usr/local/bin/ 後 chmod +x consul-template 即可直接使用。

我們要先寫個範本檔,然後讓 Consul Template 監視我們寫在 Consul 的內容有沒有變更,有的話就會將內容填入範本檔並輸出,範本檔副檔名通常為 ctmpl

假設有個 json 設定檔 source.ctmpl 如下:
    
{
    "user" : {{ key "user"}},
    "password" : {{ key "password" }}
}
    

並且先在 Consul 中儲存好 user=uuu, password=ppp,就可以使用下面的指令輸出內容並持續監視,有變更就會再次輸出:
    
consul-template -template "C:\Users\ruyut\Desktop\source.ctmpl:C:\Users\ruyut\Desktop\my.json"
    


註: -template 後面是範本檔路徑 + 冒號(:) + 要輸出的檔案路徑。

輸出結果: my.json
    
{
    "user" : uuu,
    "password" : ppp
}
    


註:如果是透過直接呼叫執行檔的方式,需要指定完整檔名(.\consul-template.exe,Windows 有設定環境變數或是 Linux 有放到 $Path 才可以直接使用),

執行後會持續監視,如果只想要輸出一次可以加上 -once 參數:
    
.\consul-template.exe -template "source.ctmpl:my.json" -once
    

指定 ip 和 port

加上參數
    
-consul-addr="192.168.0.210:8500"
    

指定 token

如果有開啟 ACL 帶入 token 的方式:
    
-consul-token="c4de9682-a850-d49f-2b08-ec3cb671b9c4"
    

使用設定檔

每次都要輸入這麼長很麻煩,可以使用設定檔的方式,通常檔名會命名為 config.hcl 或 consul-template.hcl
    
consul{
  address= "192.168.0.210:8500"
  token="c4de9682-a850-d49f-2b08-ec3cb671b9c4"
}

template {
  source = "C:\\Users\\ruyut\\Desktop\\source.ctmpl"
  destination = "C:\\Users\\ruyut\\Desktop\\my.json"
  command = "nginx -s reload"
}
    
註:在 Winodws 中如果是 \ 斜線要寫成 \\ ,不然會出現錯誤

執行:
    
.\consul-template.exe -config="C:\Users\ruyut\Desktop\consul-template.hcl"
    

補充:指令部分可以寫成 "nginx -s reload || true" ,這樣裡面的指令出錯時也不會中斷 consul-template (in Linux)

註: 目前關閉容器資料會消失,在關閉前請先備份。

參考資料:
Github - hashicorp/consul-template
Templating Language
Configuring Consul Template

留言