1. 程式人生 > >基於Consul+Registrator+Nginx實現容器服務自動發現的集群框架

基於Consul+Registrator+Nginx實現容器服務自動發現的集群框架

docker consul 服務發現 docker+consul 甘兵

我們先來看一下服務發現常用的框架有哪些:

  • zookeeper
  • eureka
  • etcd
  • consul

這裏就不挨個來介紹它們了,本文中主要以consul為主,如果你在大量接觸或使用微服務的話,你可能會碰到一個問題?當你創建的服務數量越來越多時,這些服務之間的通信便越難管理,而且維護代價會越來越高。consul可以給你答案,我們一起來了解一下consul:
技術分享圖片

1.了解consul

Consul是一個分布式,高度可用且支持多數據中心的服務發現,配置和編排工具。 Consul支持大規模部署,配置和維護面向服務的體系結構。 欲了解更多官方信息,請參閱:

  • consul 文檔
  • consul github

1.1 架構設計

在現實中,我們一直渴望著追求提供高質量、高可用的服務架構體系,同時減少不必要的部署和維護代價,減少容錯率。面對如此高的要求,可以有兩種架構方案:

  • Docker+Etcd+Confd+Nginx
  • Docker+Consul+Nginx

本文中我們主要來介紹 Docker+Consul+Nginx方案,此方案更加高效、快捷,並且維護代價和容錯率更低,分布式支持力度更強,如下圖所示:
技術分享圖片

使用Docker將Consul、Consul Template、Registrator和Nginx組裝成一個值得信任且可擴展的服務框架,這套架構讓你在這個框架中添加和移除服務,不需要重寫任何配置,也不需要重啟任何服務,一切都能正常運行,工作流程很簡單:

docker節點 ---------> consul ---------> nginx.conf

1.2 架構優勢

Docker+Consul+Nginx雖然看起來是三個組件的運用,但卻證明是一個有機的整體。它們互相聯系、互相作用,完全滿足我們對高可用、高效服務架構方案的需求,是Docker生態圈中最理想的組合之一,具有以下優勢:

  1. 自動發現與註冊組件consul使用 Raft 算法來保證一致性,比復雜的Paxos 算法更直接。相比較而言,zookeeper 采用的是 Paxos,而 etcd 使用的則是 Raft;
  2. 支持多數據中心,多數據中心集群可以避免單數據中心的單點故障,zookeeper 和 etcd 均不提供多數據中心功能的支持;
  3. 自動、實時發現及無感知服務刷新,具備資源彈性,伸縮自如;
  4. 支持健康檢查,負載能動態在可用的服務實例上進行均衡,etcd 不提供此功能;
  5. 支持足夠多臺Docker容器(前提架構資源足以保證性能支撐);
  6. 支持http 和dns 協議接口,zookeeper 的集成較為復雜,etcd 只支持 http 協議;
  7. 服務規模方便進行快速調整,官方提供web管理界面,etcd 無此功能;
  8. Consul template 搭配consul使用,支持多種接入層,如Nginx、Haproxy。

2.環境說明

本文所用的環境均按1.1中的架構圖來部署,nginx用1臺服務器、consul用1臺服務器、docker host用2臺服務器,共用4臺服務器來部署,當然如果你的服務器緊張,用3臺也一樣,減少1臺docker host就行:

服務器IP 服務器名 角色
172.18.18.32 nginx 運行nginx服務、consul-template守護進程
172.18.18.33 consul 運行consul服務
172.18.18.34 docker01 運行registrator容器、運行nginx容器(映射端口81、82)
172.18.18.35 docker01 運行registrator容器、運行nginx容器(映射端口83、84)

3.部署nginx

在nginx服務器上操作

3.1 安裝nginx

1、下載並解壓nginx:
你可以用docker的方案運行nginx、也可以用源碼包編譯安裝nginx。在本文中nginx用源碼包的方式安裝

[root@nginx /]# cd /usr/src/
[root@nginx src /]# tar -zxvf nginx-1.12.1.tar.gz

2、編譯安裝nginx:

[root@nginx src]# yum -y install gcc gcc-c++ make openssl-devel pcre-devel
[root@nginx src]# cd nginx-1.12.1/
[root@nginx nginx-1.12.1]# ./configure --prefix=/usr/local/nginx   --with-http_stub_status_module --with-http_realip_module --with-pcre  --with-http_ssl_module
[root@nginx nginx-1.12.1]# make -j 2
[root@nginx nginx-1.12.1]# make install

3.2 安裝consul-template

安裝consul-template非常簡單,下載二進制包即可使用
1、下載consul-template
下載地址:https://releases.hashicorp.com/consul-template/0.19.3/consul-template_0.19.3_linux_amd64.zip

[root@nginx ]# wget https://releases.hashicorp.com/consul-template/0.19.3/consul-template_0.19.3_linux_amd64.zip

2、解壓並安裝到/usr/bin目錄

[root@nginx ]# unzip consul-template_0.19.3_linux_amd64.zip
[root@nginx ]# mv consul-template /usr/bin/

4.部署consul

在consul服務器上操作

4.1 安裝consul

有兩種方式安裝consul(容器、二進制包),在本文中選使用二制包的方式。
1、下載consul二進制包
下載地址 https://www.consul.io/downloads.html

2、解壓、安裝

[root@consul ~]#unzip consul_0.9.2_linux_amd64.zip
[root@consul ~]#mv consul /usr/bin/

3、部署consul

[root@consul ~]#consul agent -server -bootstrap -ui -data-dir=/var/lib/consul-data -bind=172.18.18.33 -client=0.0.0.0 -node=server01

參數說明:
agent:運行一個consul代理。
-server :切換代理到服務器模式。
-bootstrap :將服務器設置為引導模式。
-ui:啟用內置的靜態web UI服務器。
-data-dir:路徑到數據目錄存儲代理狀態。
-bind:設置集群通信的綁定地址。
-client:設置用於綁定客戶端訪問的地址。這包括RPC、DNS、HTTP和HTTPS(如果配置)。
-node:此節點的名稱。 在集群中必須是唯一的,如果你運行第2臺consul,可以寫server02、server03等。

consul啟動後它會在前臺顯示,如果你想讓它在後臺運行,可以加上nohup &來運行它:

[root@consul ~]#nohup consul agent -server -bootstrap -ui -data-dir=/var/lib/consul-data -bind=172.18.18.33 -client=0.0.0.0 -node=server01 &

4、查看consul啟動後的情況:
技術分享圖片
啟動consul後默認會監聽5個端口:
8300: replication、leader farwarding的端口
8301: lan cossip的端口
8302: wan gossip的端口
8500: web ui界面的端口
8600: 使用dns協議查看節點信息的端口
可參考下圖查看端口的意思:
技術分享圖片

4.2 查看consul集群信息

[root@consul ~]#consul members
[root@consul ~]#consul info |grep leader
[root@consul ~]#consul catalog services

4.3 通過http api獲取集群信息

# 集群server成員
[root@consul ~]#curl 127.0.0.1:8500/v1/status/peers
# 集群Raft leader
[root@consul ~]#curl 127.0.0.1:8500/v1/status/leader
# 註冊的所有服務
[root@consul ~]#curl 127.0.0.1:8500/v1/catalog/services
# 服務信息
[root@consul ~]#curl 127.0.0.1:8500/v1/catalog/services/nginx
# 集群節點詳細信息
[root@consul ~]#curl 127.0.0.1:8500/v1/catalog/nodes

一般我們通過 http://consul服務器:8500 web界面來訪問查看:
技術分享圖片
從上圖可以看到,consul 界面有5個菜單項(SERVICES、NODES、KEY/VALUE、ACL、DC1)。在SERVICES中,目前因為沒有任何服務加入進來,只顯示了consul它自己的服務狀態。

我們在來看下NODES,從圖中很好理解, 在server01這臺節點上有個consul :8300的服務:
技術分享圖片

接下來,我們去nginx服務器上配置一下nginx模板,並在兩臺docker主機上運行registrator服務進行測試。

5.配置nginx

在步驟3中nginx已經安裝好了,這一步只是配置nginx,大概配置的思路為:

  • 在/usr/local/nginx/conf中創建目錄consul,目錄名自定義;
  • 在consul目錄中創建nginx.ctmpl模板;
  • 在nginx.conf配置中添加include項並指向consul目錄 ;
  • 重啟nginx服務;

5.1 創建nginx.ctmpl模板

[root@nginx /]#/usr/local/nginx/consul/
[root@nginx /]#cd /usr/local/nginx/consul/
[root@nginx consul]#vim nginx.ctmpl
upstream http_backend {
    {{range service "nginx"}}
    server {{ .Address }}:{{ .Port }};
    {{ end }}
}

server {
    listen 8000;
    server_name localhost;
    location / {
    proxy_pass http://http_backend;
    }
}

nginx.ctmpl模板中的內容就是兩段意思,熟悉nginx的朋友一看也能明白:第1 定義nginx upstream一個簡單模板,第2 定義一個server,監聽8000端口,反向代理到upstream。

5.2 修改nginx.conf

[root@nginx consul]# vim /usr/local/nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
        #添加這一行
    include /usr/local/nginx/consul/*.conf;
}

添加好了在重載nginx服務:

[root@nginx consul]# /usr/local/nginx/sbin/nginx  -s reload

5.3 運行consul-template進程

1、啟動consul-template

[root@nginx consul]#consul-template --consul-addr 172.18.18.33:8500 --template "./nginx.ctmpl:vhost.conf" --log-level=info
2018/03/14 08:08:06.933447 [INFO] consul-template v0.19.3 (ebf2d3d)
2018/03/14 08:08:06.933459 [INFO] (runner) creating new runner (dry: false, once: false)
2018/03/14 08:08:06.933779 [INFO] (runner) creating watcher
2018/03/14 08:08:06.933858 [INFO] (runner) starting
2018/03/14 08:08:06.933873 [INFO] (runner) initiating run
2018/03/14 08:08:06.935387 [INFO] (runner) initiating run

註意:它這個日誌是一直在前臺輸出,通過ctrl+c停止consul-template進程。

參數說明:
--consul-addr:指定consul服務的ip和端口;
./nginx.ctmpl:這是用nginx.ctmpl這個模板來啟動進程,這是寫的相對路徑,也可以寫絕對路徑;
vhost.conf:nginx.ctmpl模板生成後的文件名,這也可以寫絕對路徑,如果不寫絕對路徑,這個文件就在當前目錄生成(/usr/local/nginx/consul/)

2、驗證consul-template
由於consul-template在前臺運行,所以我們在打開一個nginx終端驗證。

#查看下進程
[root@nginx ~]# ps -ef | grep consul-template
root     22954 22794  0 16:08 pts/0    00:00:00 consul-template --consul-addr 172.18.18.33:8500 --template ./nginx.ctmpl:vhost.conf --log-level=info
#查看下consul目錄下的文件
[root@nginx ~]# cd /usr/local/nginx/consul/
[root@nginx consul]# ls
nginx.ctmpl  vhost.conf

在consul目錄下,是不是發現多了一個文件vhost.conf,就是剛才啟動consul-template進程時生成的。

在來查看下vhost.conf的內容,目前upstraem配置為空,還沒有docker主機加入進來:

[root@nginx consul]# cat vhost.conf 
upstream http_backend {

}

server {
    listen 8000;
    server_name localhost;
    location / {
    proxy_pass http://http_backend;
    }
}

接下來去配置下docker主機。

6.部署docker

先來說一下在docker服務器上操作的大概思路:

  • 分別在兩臺docker服務器上都創建registrator容器,註意到consul服務中心;
  • 在docker01上運行兩臺nginx容器(端口81、82),在docker02上運行兩臺nginx容器(端口83、84);
  • 修改這4臺nginx容器中的index.html頁面內容為(docker01:81、docker01:82、docker02:83、docker02:84)
  • 訪問consul web界面驗證
  • 訪問nginx服務器地址 http://172.18.18.33:8000 進行驗證;

6.1 安裝docker服務

安裝過程省略,可參考筆者這篇文章進行安裝 《docker環境安裝(Ubuntu、Centos)》

6.2 創建registrator容器

分別在docker 01 和docker 02 上都創建:

[root@docker01 /]# docker run -d --name registrator --network=host -v /var/run/docker.sock:/tmp/docker.sock --restart=always gliderlabs/registrator:latest --ip 172.18.18.34 consul://172.18.18.33:8500

[root@docker02 /]# docker run -d --name registrator --network=host -v /var/run/docker.sock:/tmp/docker.sock --restart=always gliderlabs/registrator:latest --ip 172.18.18.35 consul://172.18.18.33:8500

參數說明:
--network:把運行的docker容器設定為host網絡模式;
-v /var/run/docker.sock:把宿主機的Docker守護進程(Docker daemon)默認監聽的Unix域套接字掛載到容器中;
--ip : 剛才把network指定了host模式,所以我們指定下IP為宿主機的IP;
consul:j最後這個選項是配置consul服務器的IP和端口。

### 6.3 啟動nginx容器

1、先在docker01上啟動第1臺nginx,也就是端口為81的容器:

[root@docker01 /]#docker run -itd --name nginx_81 -p 81:80 nginx

進入容器修改index.html:

[root@docker01 /]# docker exec -it nginx_81 bash
root@272533504ab0:/# cd /usr/share/nginx/html/
root@272533504ab0:/usr/share/nginx/html# echo  "docker01:81" > index.html 

在去nginx服務器上驗證下vhost.conf,從下面可以看到docker01的nginx 81註冊進來了:

[root@nginx consul]# cat vhost.conf 
upstream http_backend {

    server 172.18.18.34:81;

}

server {
    listen 8000;
    server_name localhost;
    location / {
    proxy_pass http://http_backend;
    }
}

然後訪問一下nginx服務器的IP地址,http://172.18.18.32:8000 ,從下圖可以看出是可以訪問的:
技術分享圖片

2、在docker01上啟動第2臺nginx,也就是端口為82的容器,並修改好index.html:

[root@docker01 /]# docker run -itd --name nginx_82 -p 82:80 nginx
[root@docker /]# docker exec -it nginx_82  bash
root@b66febfa0753:/# cd /usr/share/nginx/html/
root@b66febfa0753:/usr/share/nginx/html# echo  "docker01:82" > index.html 

在去nginx服務器上驗證下vhost.conf,從下面可以看到docker01的nginx 82也註冊進來了:
技術分享圖片

接著,我們訪問下consul服務的web界面,http://172.18.18.33:8500 ,從下圖可以看出,在SERVICE中是不是發現多了個nginx 服務:
技術分享圖片

然後,在看看NODES,從下圖可以看出,剛才創建的兩個nginx容器(81、82)都註冊到了server01這臺consul服務器,如果我們的consul是集群環境的話,可以分別註冊到server02或server03中:
技術分享圖片

3、把docker02服務器上的nginx容器83和84也創建了
創建nginx:83

[root@docker02 /]# docker run -itd --name nginx_83 -p 83:80 nginx
[root@docker02 /]# docker exec -it nginx_83 bash
root@5c21ba694829:/# cd /usr/share/nginx/html/
root@5c21ba694829:/usr/share/nginx/html# echo  "docker02:83" > index.html

創建nginx:84

[root@docker02 /]# docker run -itd --name nginx_84 -p 84:80 nginx
[root@docker02 /]#docker exec -it nginx_84  bash
root@0f9d72ff453b:/# cd /usr/share/nginx/html/
root@0f9d72ff453b:/usr/share/nginx/html#  echo  "docker02:84" > index.html

4、去nginx服務器上驗證vhost.conf:
技術分享圖片
從上圖可以看出,docker02服務器上的83和84也自動註冊進來了。

5、在來看看consul服務器上的web界面:
技術分享圖片
從上圖可以看出,SERVICE中的nginx已經有了4個,並且還多其它的服務,這些服務是我docker02上跑的其它應用的容器,也都會自動註冊進來。

6、訪問nginx服務器做最後的驗證,http://172.18.18.32:8000 ,記得用f5刷新驗證:
技術分享圖片
F5刷新一下頁面:
技術分享圖片
在刷新一下,是不是訪問到了docker02這臺主機了:
技術分享圖片

到此,自動註冊服務的過程就完成了,想到詳細了解consul的朋友可以參考官方文檔:

consul 官方下載:https://www.consul.io/downloads.html
consul官方集群安裝:https://www.consul.io/intro/getting-started/join.html
consul github :https://github.com/hashicorp/consul
consul官方鏡像: https://hub.docker.com/_/consul/

喜歡我的文章,請點擊最上方右角處的《關註》支持一下!

基於Consul+Registrator+Nginx實現容器服務自動發現的集群框架