不知道配置檔案上次什麼時候修改的、修改了什麼內容?改了配置檔案還要重新發布專案或者手動觸發重啟服務?無緣無故發現配置檔案錯了影響到線上正常部署?你是否正在因為這些問題而困擾?50+線上專案,數百+配置檔案,我們經常被這些配置檔案虐的生無可戀,是時候作出改變了!本文將帶你解決這些問題,喝著咖啡輕鬆運維
配置中心選型
選型的原則:簡單,易落地,不挑平臺,不挑語言,儘量少的依賴。
對比了Disconf、Apollo等方案,最終選擇了Etcd+Confd的方案,基本符合上邊的原則,且Etcd我們在部署Kubernetes的時候已經有過使用,算是輕車熟路。
配置中心架構圖
- 配置中心整體採用C/S的模式,用Etcd作為服務端來儲存資料,Confd作為客戶端去Etcd取資料更新
- 為了更方便的管理寫了WebUI,實際上是一個Etcd服務的WebUI,主要與Etcd服務互動,去Etcd存取資料
- Confd根據配置檔案去Etcd叢集拉取資料,然後根據模板檔案將資料按照設定的格式填充的固定的位置生成最終的配置檔案
- 配置檔案生成後還可以配合
check_cmd
和reload_cmd
命令對配置檔案進行檢查和重新載入
配置中心部署
Etcd叢集
-
系統環境
- System:Debian 8
- Etcd:v3.3.9
-
伺服器地址
- 192.168.107.101
- 192.168.107.102
- 192.168.107.103
所有伺服器都需要執行以下命令來安裝etcd和建立目錄
1.下載etcd安裝包並解壓
# wget https://github.com/coreos/etcd/releases/download/v3.3.9/etcd-v3.3.9-linux-amd64.tar.gz
# tar -zxvf etcd-v3.3.9-linux-amd64.tar.gz
複製程式碼
2.拷貝程式到/usr/bin目錄下方便執行,etcd為go編寫,直接可執行,主要有兩個檔案etcd和ectdctl,
# mv etcd-v3.3.9-linux-amd64/etcd* /usr/bin/
複製程式碼
3.建立etcd配置檔案目錄/etc/etcd
和資料存放目錄/home/data/etcd
# mkdir /etc/etcd /home/data/etcd
複製程式碼
三個node節點etcd配置檔案分別如下
node1配置
# cat /etc/etcd/etcd.conf
name: `node1`
data-dir: /home/data/etcd
listen-peer-urls: http://192.168.107.101:2380
listen-client-urls: http://192.168.107.101:2379,http://127.0.0.1:2379
initial-cluster-state: `new`
initial-cluster-token: `etcd-cluster-conf`
advertise-client-urls: http://192.168.107.101:2379
initial-advertise-peer-urls: http://192.168.107.101:2380
initial-cluster: node1=http://192.168.107.101:2380,node2=http://192.168.107.102:2380,node3=http://192.168.107.103:2380
複製程式碼
node2配置
# cat /etc/etcd/etcd.conf
name: `node2`
data-dir: /home/data/etcd
listen-peer-urls: http://192.168.107.102:2380
listen-client-urls: http://192.168.107.102:2379,http://127.0.0.1:2379
initial-cluster-state: `new`
initial-cluster-token: `etcd-cluster-conf`
advertise-client-urls: http://192.168.107.102:2379
initial-advertise-peer-urls: http://192.168.107.102:2380
initial-cluster: node1=http://192.168.107.101:2380,node2=http://192.168.107.102:2380,node3=http://192.168.107.103:2380
複製程式碼
node3配置
# cat /etc/etcd/etcd.conf
name: `node3`
data-dir: /home/data/etcd
listen-peer-urls: http://192.168.107.103:2380
listen-client-urls: http://192.168.107.103:2379,http://127.0.0.1:2379
initial-cluster-state: `new`
initial-cluster-token: `etcd-cluster-conf`
advertise-client-urls: http://192.168.107.103:2379
initial-advertise-peer-urls: http://192.168.107.103:2380
initial-cluster: node1=http://192.168.107.101:2380,node2=http://192.168.107.102:2380,node3=http://192.168.107.103:2380
複製程式碼
每個節點配置完成後均啟動
需要放在後臺執行,推薦使用screen
工具
# /usr/bin/etcd --config-file /etc/etcd/etcd.conf
複製程式碼
三個節點全部啟動完成後,可通過etcdctl member list
命令檢視叢集列表,確認叢集狀態
# etcdctl member list
732ca490026f580d: name=node3 peerURLs=http://192.168.107.103:2380 clientURLs=http://192.168.107.103:2379 isLeader=false
bc16d35c3ad1c5ee: name=node2 peerURLs=http://192.168.107.102:2380 clientURLs=http://192.168.107.102:2379 isLeader=true
f7a043d3b65cd4a4: name=node1 peerURLs=http://192.168.107.101:2380 clientURLs=http://192.168.107.101:2379 isLeader=false
複製程式碼
Confd
1.下載confd並放到/usr/bin/
目錄下方便使用
# wget https://github.com/kelseyhightower/confd/releases/download/v0.16.0/confd-0.16.0-linux-amd64
# mv confd-0.16.0-linux-amd64 /usr/bin/confd
# chmod +x /usr/bin/confd
複製程式碼
2.新建confd配置檔案目錄
# mkdir /etc/confd/{conf.d,templates}
複製程式碼
3.新建資原始檔,.toml
檔案結尾已經成了固定格式
# cat /etc/confd/conf.d/nginx.conf.toml
[template]
src = "nginx.conf.tmpl"
dest = "/tmp/nginx.conf"
keys = [
"/conf/project/env/nginx/nginx.conf",
]
check_cmd = "/usr/sbin/nginx -t -c {{.src}}"
reload_cmd = "/usr/sbin/service nginx reload"
複製程式碼
這裡我們新建了一個nginx配置的資原始檔,引數解釋:
-
src:指定模板檔案的位置,也就是nginx配置檔案模板tmpl的位置
-
dest:指定最終生成或更新的配置檔案絕對路徑,這裡為了測試我們給指定到/tmp/下
-
keys:模板檔案裡邊要用到的key,也就是etcd裡邊對應的這個專案配置檔案的key
-
check_cmd:在更新配置檔案完成後執行的check命令,這裡我們就check下nginx配置檔案是否有語法錯誤
-
reload_cmd:在check通過後可以執行這裡配置的命令,上一步的check沒有問題,就會執行reload命令重新載入配置檔案
-
prefix:配置key的字首,例如我們的key都是以/conf開頭的,那麼可以增加個配置
prefix="/conf"
,在下邊keys裡就可以省略掉/conf了 -
owner:配置生成配置檔案的使用者
-
mode:配置生成配置檔案的許可權
4.新建模板檔案
# cat /etc/confd/templates/nginx.conf.tmpl
{{getv "/conf/project/env/nginx/nginx.conf"}}
複製程式碼
- confd的模板語法有很多,這裡不贅述,具體可查官網
- 我們是把整個配置檔案的內容作為一個value存在etcd裡邊的,所以這裡只需要一個getv指令獲取到value的值填充到目標檔案就可以了
聯調測試
部署好了etcd叢集和confd服務,接下來我們就要測試下他們是否能夠正常協同工作了
1.在Etcd伺服器新建一個KV值
# etcdctl set /conf/project/env/nginx/nginx.conf `user www-data;
> worker_processes 4;
>
> pid /var/run/nginx.pid;
> error_log /home/logs/nginx/error.log warn;
>
> events {
> use epoll;
> worker_connections 51200;
> }
>
> http {
> default_type application/octet-stream;
>
> server {
> listen 80;
> server_name domain.com;
>
> root /home/project/webroot;
> index index.shtml index.html;
> }
> }`
複製程式碼
# 檢視設定key的內容
# etcdctl get /conf/project/env/nginx/nginx.conf
user www-data;
worker_processes 4;
pid /var/run/nginx.pid;
error_log /home/logs/nginx/error.log warn;
events {
use epoll;
worker_connections 51200;
}
http {
default_type application/octet-stream;
server {
listen 80;
server_name domain.com;
root /home/project/webroot;
index index.shtml index.html;
}
}
複製程式碼
- Etcd API分v2和v3版本,兩個版本差別較大,v3優化了很多,但考慮相容性等問題我們這裡使用v2版本
- 預設為v2版本,可以通過環境變數
export ETCDCTL_API=3
來切換到v3版本,v2通過etcdctl -v
可以檢視api版本,v3通過etcdctl version
檢視api版本
2.啟動confd
# confd -watch -backend etcd -node=http://192.168.107.101:2379 -node=http://192.168.107.102:2379 -node=http://192.168.107.103:2379
2018-08-23T13:46:13+08:00 onlinegame.i.nease.net confd[17084]: INFO Backend set to etcd
2018-08-23T13:46:13+08:00 onlinegame.i.nease.net confd[17084]: INFO Starting confd
2018-08-23T13:46:13+08:00 onlinegame.i.nease.net confd[17084]: INFO Backend source(s) set to http://192.168.107.101:2379, http://192.168.107.102:2379, http://192.168.107.103:2379
2018-08-23T13:46:13+08:00 onlinegame.i.nease.net confd[17084]: INFO Target config /tmp/nginx.conf out of sync
2018-08-23T13:46:13+08:00 onlinegame.i.nease.net confd[17084]: INFO Target config /tmp/nginx.conf has been updated
複製程式碼
配置引數說明
-
-watch:開啟watch模式,監聽etcd配置中心檔案變化,一旦有變這邊立即更新,沒有這個選項配置中心修改client不會更新
-
-backend:後端型別,目前支援etcd、zookeeper、consul、vault、redis、file、rancher等多種型別,confd也有一些針對不通後端型別的單獨配置,具體可以通過
confd --help
命令檢視 -
-node:etcd節點地址,有多個節點的話就這麼寫多個-node就好了,我們etcd是三個節點的叢集所以這裡寫三次`-node`
-
-onetime:可用來替換上邊的
-watch
引數,表示執行一次就退出,如果你不想讓配置檔案實時更新,只是想更新一次,可以用這個引數 -
-interval:可用來替換上邊的
-watch
引數,表示每隔多少秒去backend取一次資料,如果想降低etcd伺服器壓力,又想讓客戶端配置檔案能自動更新,可以通過這個引數來控制
3.通過上邊日誌可以看到/tmp/nginx.conf檔案已經正常同步且更新了,檢視/tmp/nginx.conf確定內容正確
WebUI Kerrigan
總不能所有的配置檔案更新都通過命令列的方式吧?為了方便管理,花了三天(真的是三天)寫了個WebUI,命名為Kerrigan,能夠實現目錄樹,線上檢視配置、修改配置、檢視配置更新歷史等實用功能
配置頁面,通過這個頁面可以配置etcd的連線資訊
首頁,左側專案列表(專案資訊同步CMDB)
點選專案列表後,根據對應規則去etcd裡邊取出目錄結構按樹狀呈現出來
點選配置檔案,右側會展示當前配置檔案內容
點選“編輯”按鈕可以編輯這個配置,新建頁面一樣,只是編輯不允許修改路徑
點選“歷史”按鈕,則跳轉到配置檔案的歷史頁面,這個頁面展示了這個配置檔案所有的修改歷史
寫在最後
- 是不是要說這個介面醜爆了!沒辦法,前端後端測試加上線都我一人幹,沒有設計細胞,就這麼看吧,並且最重要的不是功能好用麼
- 為什麼不用K8S的configmap?我們最初是想用K8S的configmap來做配置中心的,但是並非所有的專案都跑在K8S裡,且修改configmap也需要重啟容器才能生效,所以就沒有采用了
- etcd誰都可以修改麼,感覺不安全啊?實際上我們是用了賬號密碼認證的,且只在內網,限制IP,安全一點吧,另一種解決方案是etcd走ssl,但client端要放證書比較麻煩沒有采用
- 怎麼確認Client端配置檔案更新成功了?如果你是一次性啟動可以在啟動命令之後判斷啟動命令是否正常執行,如果你是watch模式或者interval,那麼。。只能人肉check了吧,我也沒有好方法
如果你覺得文章對你有幫助,請轉發分享讓更多好友看到。如果你覺得讀的不盡興,推薦閱讀以下文章: