基於etcd+confd通過nginx對docker服務混合註冊發現詳解

  先簡單說下業務邏輯,etcd是一個分部式k/v存儲系統,confd是一個對etcd的key或者目錄做變化監控的軟件,並配有相關語法,可以將變化的k/v處理後形成配置文件,nginx不用多說了,做docker容器的負載均衡流量調度。

  在業務過程中,docker容器健康起來後,會通過接口向etcd註冊相關k/v信息,confd檢測到etcd的k/v變化後,立即觸發程序通過模板形成新的nginx配置文件,先做離線語法測試,如果沒問題就覆蓋原配置,進而reload,測試不通過就不覆蓋原配置,整個過程是安全可控的。在容器註冊到nginx的upstream後,nginx會對容器做健康檢查發現,如果正常,則分發流量過去。對應的業務流程圖如下:

wKioL1jR9SGwQOthAAF-cP-4rNY162.png

根據業務情況,要解決如下幾個問題:

  1、nginx負載均衡的混合註冊,使得nginx可以混合負載多個業務;

  2、不同機房如何在同一etcd集羣上進行註冊,如何規劃;

  3、confd更新頻率如何週期可控制,k/v每有變化實時觸發reload太敏感,況且每個容器要註冊多個k/v,在整體註冊完之前,是不需要reload的;

  4、confd啓動時如何關聯多個etcd的地址,保證高可用;

  5、權限問題如何處理,怎麼做,如果任何人知道ip和端口就可以註冊,那麼服務就垮了。

一、nginx負載均衡的混合註冊,使得nginx可以混合負載多個業務域名容器

   先分析下nginx做負載均衡時的配置文件,分析後註冊時的變化因子主要有3個,1是server_name的域名,2是upstream的名稱,3是upstream裏的server,這三個元素就決定了不同的註冊服務。有了這個思路後,設計confd對應的nginx的模板文件,先簡單說下confd,confd可以直接下載二進制包,不存在安裝的問題,配置好path後直接使用命令,在使用中默認讀取/etc/confd下的conf.d和templates下兩個目錄的配置,對應github是https://github.com/coreos/etcd ,創建過程如下:

mkdir -p /etc/confd/{conf.d,templates}

   然後在conf.d下創建.toml配置文件,在templates下創建.tmpl模板文件。

   根據nginx的3個元素去分析規劃k/v規則,優化後發現註冊一個服務要添加兩個健值,並用etcdctl命令進行模擬測試,註冊第一個服務如下:

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,先看下注冊後的結果:

wKioL1jQ8mSzWC7rAABMApx55SI444.png

然後我再繼續註冊第二個服務,對應命令如下:

etcdctl set /service_sgin/subdomain/service2  "www.service2.com  page.service2.com"
etcdctl set  /service_sgin/upstream/service2/server1  192.168.1.2

註冊後配置文件截圖如下:

wKioL1jQ8sax-P3qAACD4MWXxJs880.png 

  要的就是這個效果,另外加了一個默認的server,當過來沒有符合業務的域名,直接302到某個業務地址,好了剖開看confd的兩個概要配置如下:

/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

/etc/confd/templates/nginx.conf.tmpl

user root;
worker_processes auto;
worker_cpu_affinity auto;
pid   logs/nginx.pid;
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#error_log_bind 192.168.1.31;
worker_rlimit_nofile 512000;
events {
    use epoll;
    worker_connections  20480;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    resolver 127.0.0.1 valid=10m;
    sendfile        on;
    keepalive_timeout  65s;
    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 {
        listen  80;
        server_name  ``.`Value`;
        location / {
                proxy_pass              http://{{base .Key}};
                proxy_redirect  off;
                proxy_set_header  Host                   $host;
                proxy_set_header  X-Real-IP             $remote_addr;
                proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
          }
    }
`end`
}

二、不同機房如何在同一etcd集羣上進行註冊,如何規劃

  這個其實看起來複雜,實施起來非常簡單,爲了節省資源,不可能每個機房都對應建etcd集羣,這個時候就可以複用etcd集羣,比如北顯和亦莊機房的註冊,可以使用改變默認etcd鍵值目錄來實現:

prefix = "/service_sgin_bx" 
prefix  =  "/service_sgin_yz"

三、confd更新頻率如何週期可控制,k/v每有變化實時觸發reload太敏感,況且每個容器要註冊多個k/v,在整體註冊完之前,是不需要reload的

  這個同樣,看起來複雜,其實confd改一下模式就能實現,不要用watch模式,改而週期性去探測etcd的鍵值變化,比如說2秒探測一次,對應啓動時的命令如下:

./confd -backend="etcd" -node=10.211.103.151:2379 -interval=2

四、confd啓動時如何關聯多個etcd的地址,保證高可用

  同樣,只要修改下confd的啓動命令即可,讓confd監控更多node,我目前的etcd有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

五、權限問題的處理

 對於權限有兩種方式,一個是證書,一個是賬號,業務本就跑到內網,再加之賬號的配合是靈活迅速的,就從賬號着手了,對於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 "/*"  --rw  test_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_role   test_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身份監控k/v的,對應的規則就是guest;


後附一:etcd的集羣配置,擴容

    假設初始化3臺etcd分別是10.211.103.152、10.211.103.153、10.211.103.154,etcd下載下來就可以用,主要是如何配置啓動,分別再三臺機器上編寫如下啓動腳本etcdnew.sh,然後依次啓動即可:

10.211.103.152服務器:

#/bin/sh
#writer:gaolixu
/usr/local/etcd/etcd --name etcd152 --data-dir /data1/etcd \
--initial-advertise-peer-urls http://10.211.103.152:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://10.211.103.152:2379 \
--initial-cluster-token etcd-cluster-1 \
--initial-cluster etcd152=http://10.211.103.152:2380,etcd153=http://10.211.103.153:2380,etcd154=http://10.211.103.154:2380 \
--initial-cluster-state new  &

10.211.103.153服務器:

#/bin/sh
#writer:gaolixu
/usr/local/etcd/etcd --name etcd153 --data-dir /data1/etcd \
--initial-advertise-peer-urls http://10.211.103.153:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://10.211.103.153:2379 \
--initial-cluster-token etcd-cluster-1 \
--initial-cluster etcd152=http://10.211.103.152:2380,etcd153=http://10.211.103.153:2380,etcd154=http://10.211.103.154:2380 \
--initial-cluster-state new   &

10.211.103.154服務器:

#/bin/sh
#writer:gaolixu
/usr/local/etcd/etcd --name etcd154 --data-dir /data1/etcd \
--initial-advertise-peer-urls http://10.211.103.154:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://10.211.103.154:2379 \
--initial-cluster-token etcd-cluster-1 \
--initial-cluster etcd152=http://10.211.103.152:2380,etcd153=http://10.211.103.153:2380,etcd154=http://10.211.103.154:2380 \
--initial-cluster-state new  &

啓動後可以看到集羣成員和健康情況如下:

wKioL1jR3JPyAj14AABQ_MYz7rs055.png

添加、刪除etcd集羣節點操作:

比如添加10.211.103.151節點

etcdctl member add etcd151 http://10.211.103.151:2380

執行命令後會有提示,然後再151上編寫如下腳本etcdadd.sh:

#/bin/sh
#writer:gaolixu
/usr/local/etcd/etcd --name etcd151 --data-dir /data1/etcd \
--initial-advertise-peer-urls http://10.211.103.151:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://10.211.103.151:2379 \
--initial-cluster-token etcd-cluster-1 \
--initial-cluster etcd153=http://10.211.103.153:2380,etcd154=http://10.211.103.154:2380,etcd151=http://10.211.103.151:2380,etcd152=http://10.211.103.152:2380 \
--initial-cluster-state existing   &

刪除節點的話執行如下命令:

etcdctl member remove cf5e47596c46611a #通過etcdctl member list 查看到id

後附2:etcd的api 2和api 3的轉換及confd的使用轉換

1、etcd通過環境變量的調整來修改

export ETCDCTL_API=2   #api2版本
export ETCDCTL_API=3   #api3版本

2、confd通過監控時的參數修改

下載二進制文件直接使用: https://github.com/bacongobbler/confd/releases

-backend etcdv3  即 etcd api v3
-backend etcd    即 etcd api v2

自建個人原創站運維網咖社(www.net-add.com),新的博文會在網咖社更新,歡迎瀏覽


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章