Etcd + confd 通過 Nginx 對後端服務的註冊發現
本文介紹了Etcd+confd通過Nginx對後端服務的註冊過程總結出的實用經驗。
上篇文章回顧: ofollow,noindex">處理器核心真的越多越好?
先簡單介紹下用到的產品,Etcd是一個分部式KV儲存系統,confd是一個對Etcd key或目錄做變化監控的工具,並配有相關語法,可以將變化的KV處理後形成配置檔案,假設後端服務用的是Docker,Nginx就是對Docker做7層負載和流量排程的。
再看業務邏輯,Docker容器起來後,會通過介面(rest api或者rpc)向Etcd註冊相關KV資訊,confd檢測到Etcd的KV變化後,立即觸發程式通過模板形成新的Nginx配置檔案,先做離線語法測試,如果沒問題就覆蓋原配置,進而reload,測試不通過不覆蓋原配置,整個過程安全可控。在容器註冊到Nginx的upstream後,Nginx會對容器做健康檢查,如果正常,則分發流量過去。對應的業務流程圖如下:
根據業務情況,目前要考慮的問題有5個:
1、Nginx多域名多server的混合註冊,使Nginx可以混合排程多個業務;
2、不同機房如何在同一Etcd叢集上進行註冊,如何規劃;
3、confd更新頻率如何週期可控制,KV每有變化實時觸發reload太敏感,況且每個容器要註冊多個KV,在整體註冊完之前,是不需要reload的;
4、confd啟動時如何關聯多個Etcd的地址,保證高可用;
5、許可權問題如何處理,怎麼做,如果任何人知道ip和埠就可以註冊,那麼服務就垮了。
1
Nginx如何實現多域名多server的混合註冊
先分析下Nginx做負載均衡時的配置檔案,分析後發現能 決定不同的註冊服務的3個 關鍵元素:
-
server_name的域名
-
upstream的名稱
-
upstream裡的server,
有了這個思路後,設計confd對應的Nginx的模板檔案(confd是可以直接下載二進位制包,不存在安裝問題,配置好path後直接使用,在使用中預設讀取/etc/confd下的conf.d和templates下兩個目錄的配置,對應github: https://github.com/coreos/etcd ),具體是操作步驟如下:
1、建立confd使用的目錄
$mkdir -p /etc/confd/{conf.d,templates}
2、在conf.d下建立.toml配置檔案,在templates下建立.tmpl模板檔案(後面介紹,想看步驟3註冊效果)
3、根據Nginx的3個元素去分析規劃KV規則,優化後發現註冊一個服務要新增兩個健值,並用e tcdctl命令進行模擬測試,註冊第一個服務如下:
$etcdctl set /service_sgin/subdomain/service1"www.service1.com" $etcdctl set /service_sgin/upstream/service1/server1 192.168.1.1
其中service1是對應業務名稱," www.service1.com "是域名,192.168.1.1對應是server,先看下注冊後的結果:
然後再繼續註冊第二個服務,對應命令如下:
$etcdctl set /service_sgin/subdomain/service2"www.service2.compage.service2.com"$etcdctl set/service_sgin/upstream/service2/server1192.168.1.2
註冊後配置檔案截圖如下:
達到了混合註冊的效果,另外加了一個預設的server,當過來沒有符合業務的域名,直接302到小米的主頁http://www.mi.com,好了剖開看confd的兩個概要配置編碼如下:
$vim /etc/confd/conf.d/nginx.conf.toml
[template] prefix = "/service_sgin"#此配置對應Etcd的預設目錄 src = "nginx.conf.tmpl"#對應templates下的模板檔案 dest = '/usr/local/nginx/conf/nginx.conf'#對應nginx的配置檔案 owner = "root" mode = "0666" keys = ["/upstream",#監控的鍵值目錄 "/subdomain",#監控的鍵值目錄 ] check_cmd = "/usr/local/nginx/sbin/nginx -t -c {{.src}}"#檢測到變化後的測試 reload_cmd = "/usr/local/nginx/sbin/nginx -s reload"#配置檔案沒問題後的reload
$vim /etc/confd/templates/nginx.conf.tmpl
user root; worker_processes auto; worker_cpu_affinity auto; pidlogs/nginx.pid; #error_loglogs/error.log; #error_loglogs/error.lognotice; #error_loglogs/error.loginfo; #error_log_bind 192.168.1.31; worker_rlimit_nofile 512000; events { use epoll; worker_connections20480; } http { includemime.types; default_typeapplication/octet-stream; resolver 127.0.0.1 valid=10m; sendfileon; keepalive_timeout65s; proxy_next_upstream error timeout; proxy_buffering on; proxy_buffer_size 8k; proxy_buffers 32 4k; ######################對應upstream的模板部分################ {{range $sub := ls "/subdomain"}} upstream {{base $sub}} { {{$subdir := printf "/upstream/%s/*" $sub}}{{range getvs $subdir}} server {{.}}; {{end}} keepalive_timeout 65s; } {{end}} ############################################################# server { listen 80 backlog=65535 default; server_name localhost; location / { rewrite ^/(.*)$ http://www.sina.cn redirect; } } #####################對應server的模板部分#################### {{range gets "/subdomain/*"}} server { listen80; server_name{{.Value}}; location / { proxy_passhttp://{{base .Key}}; proxy_redirectoff; proxy_set_headerHost$host; proxy_set_headerX-Real-IP$remote_addr; proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for; } } {{end}} }
2
不同機房如何在同一Etcd叢集上進行註冊
這個看起來複雜,實施起來並不複雜簡單,為了合理利用資源和便於管理,不可能每個機房都對應建Etcd叢集,這個時候幾個鄰近機房可以複用Etcd叢集,比如c3和c4機房的註冊,可以使用改變預設Etcd鍵值目錄來實現:
prefix = "/service_sgin_c3" prefix="/service_sgin_c4"
3
confd更新頻率如何週期可控制上進行註冊
KV每有變化實時觸發reload太敏感,況且每個容器要註冊多個KV,在整體註冊完之前,是不需要reload的,即使後面可以用事務實現,不過confd本身也可以做一些調整,調整confd不要用watch模式,改而週期性去探測Etcd的鍵值變化,比如說2秒探測一次,這樣處理相對是比較友好的,對應啟動的命令如下:
./confd -backend="etcd" -node=10.211.103.151:2379 -interval=2
4
confd啟動時如何容災多個Etcd節點
同樣,只要修改下confd的啟動命令即可,讓confd監控更多node(當然生產化境也可以用比如四層vip等其它方案實現),目前測試環境有3個node,全部監控進去如下:
./confd -backend="etcd" -node=10.211.103.151:2379 -node=10.211.103.152:2379 -node=10.211.103.153:2379 -interval=2
5
許可權問題的處理
對於許可權有兩種方式,一個是證書,一個是賬號。一般生產環境直接用證書即可,不過還是介紹一下Etcd的賬號管理,Etcd的許可權設計主要通過使用者、規則來控制,將使用者和規則對應起來就是使用者的許可權,預設安裝後是不開啟許可權的,整理後相關的許可權操作如下:
使用者管理:
etcdctl user add root:123#加root使用者,開啟許可權必須先加 etcdctl auth enable#許可權管理開啟 etcdctl --username root:123 user list#檢視使用者 etcdctl --username root:123 user remove test_user#刪除使用者
role規則管理:
etcdctl --username root:123 role add test_role etcdctl --username root:123 role grant --path "/*"--rwtest_role#加許可權 etcdctl --username root:123 role revoke --path "/*" --write test_role#減許可權 etcdctl --username root:123 role remove test_role etcdctl --username root:123 role list etcdctl --username root:123 role get test_role
使用者規則管理:
etcdctl --username root:123 user add test_user:123 etcdctl --username root:123 user grant --roles test_roletest_user#加規則 etcdctl --username root:123 user revoke--roles test_role test_user#減規則 etcdctl --username root:123 user get test_user#檢視某個使用者下的規則
備註:
1、guest使用者的規則是guest,預設是全部許可權。
2、confd是以訪客guest身份監控KV的,對應的規則就是guest。