Docker + Consul + registrator實現服務發現及nginx反向代理

一. 架構設計

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

本文中我們主要來介紹 Docker+Etcd+Confd+Nginx方案,此方案更加高效、快捷,並且維護代價和容錯率更低,分佈式支持力度更強,如下圖所示:
Docker + Consul + registrator實現服務發現及nginx反向代理

上面示意圖的大概流程如下:
1、docker01主機上以二進制包的方式部署consul服務並後臺運行,其身份爲leader;
2、docker02、docker03以容器的方式運行consul服務,並加入到docker01的consul羣集中;
3、在主機docker02、docker03上後臺運行registrator容器,使其自動發現docker容器提供的服務;
4、在docker01上部署Nginx,提供反向代理服務,docker02、docker03主機上基於Nginx鏡像,各運行兩個web容器,提供不同的網頁文件,以便測試效果;
5、在docker01上安裝consul-template命令,將收集到的信息(registrator收集到容器的信息)寫入template模板中,並且最終寫入Nginx的配置文件中。
6、至此,實現客戶端通過訪問Nginx反向代理服務器(docker01),獲得docker02、docker03服務器上運行的Nginx容器提供的網頁文件。
注:registrator是一個自動發現docker container提供的服務,並且在後端服務註冊中心(數據中心)註冊服務。主要用來收集容器運行服務的信息,並且發送給consul。數據中心除了consul外,還有etcd、zookeeper等。

二. 架構優勢

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.nsul template 搭配consul使用,支持多種接入層,如Nginx、Haproxy。

三. 實驗環境

主機 iP地址 服務
docker01 192.168.1.11 consul+consul-template+nginx
docker02 192.168.1.13 consul+registrator
docker03 192.168.1.20 consul+registrator

三臺主機關閉防火牆,禁用selinux,更改主機名如上所述。

四. 部署consul服務

(1)docker01去官網https://www.consul.io/downloads.html下載consul服務

[root@docker01 ~]# unzip consul_1.5.1_linux_amd64.zip 
//現在是本地導入壓縮包,需要解壓              
[root@docker01 ~]# mv consul /usr/local/bin/
//移動服務到bin目錄
[root@docker01 ~]# chmod +x /usr/local/bin/consul
//給予一個可執行權限

(2)啓動consul

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

PS: //-bootstrap: 加入這個選項時,一般都在server單節點的時候用,自選舉爲leader。

參數解釋:
-server:添加一個服務
-bootstrap:一般在server單節點的時候使用,自選舉爲leader。
-data-dir:key/volume指定數據存放的目錄
-ui:開啓內部的web界面
-bind:指定開啓服務的ip
-client:指定訪問的客戶端
-node:在集羣內部通信使用的名稱,默認是主機名。

Docker + Consul + registrator實現服務發現及nginx反向代理

現在這個ip是外部使用

PS:開啓的端口
8300 集羣節點
8301 集羣內部的訪問
8302 跨數據中心的通信
8500 web ui界面
8600 使用dns協議查看節點信息的端口

可參考下圖查看端口的意思:
Docker + Consul + registrator實現服務發現及nginx反向代理

這時,這條啓動consul的命令會佔用終端,可以使用nohup命令讓它保持後臺運行。

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

(3)查看consul端口的信息**

[root@docker01 ~]# consul info

Docker + Consul + registrator實現服務發現及nginx反向代理

五. docker01下載部署consul-template

https://github.com/hashicorp/consul-template 上,下載consul-template

[root@docker01 ~]# unzip consul-template_0.19.5_linux_amd64.zip
//解壓安裝好的consul-template包
[root@docker01 ~]# mv consul-template /usr/local/bin/
//移動到命令目錄
[root@docker01 ~]# chmod +x /usr/local/bin/consul-template 
//給予一個可執行權限

六和七步驟簡要說明

在docker01和docker02上操作

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

分別在兩臺docker服務器上都創建registrator容器,注意到consul服務中心;
在docker01上運行兩臺nginx容器(端口隨機生成),在docker02上運行兩臺nginx容器(端口隨機生成);
修改這4臺nginx容器中的index.html頁面內容爲(xgp-web01、xgp-web02、xgp-web03、xgp-web04)
訪問consul web界面驗證
訪問nginx服務器地址 http://192.168.1.11:8000 進行驗證;

六. docker02,docker03,加入consul集羣

這裏我們採用容器的方式去運行consul服務。

(1)下載consu所需的l鏡像

[root@docker02 ~]# docker pull consul

(2)基於consul鏡像開啓一臺容器

[root@docker02 ~]# docker run -d --name consul -p 8301:8301 -p 8301:8301/udp -p 8500:8500 -p 8600:8600 -p 8600:8600/udp --restart always progrium/consul -join 192.168.1.11 -advertise 192.168.1.13 -client 0.0.0.0 -node=node01

參數解釋:

-d:守護進程

--name:容器名稱

--restart:容器隨着docker服務一直運行

-advertise:聲明本機地址

-join:聲明服務端地址

-node:consul集羣中的名稱

(3)docker查看consul集羣成員的信息

[root@docker01 ~]# consul members

Docker + Consul + registrator實現服務發現及nginx反向代理

(4)兩臺docker開啓容器後,docker01查看

Docker + Consul + registrator實現服務發現及nginx反向代理

(5)瀏覽器訪問http://192.168.1.11:8500

Docker + Consul + registrator實現服務發現及nginx反向代理

七. docker02、docker03 上部署registrator服務

registrator是一個能自動發現docker container提供的服務,並在後端服務註冊中心註冊服務或取消服務的工具,後端註冊中心支持conusl、etcd、 skydns2、zookeeper等。

(1)下載registrator鏡像

[root@docker02 ~]# docker pull registrator
//下載registrator鏡像

(2)基於registrator鏡像,開啓一臺容器

[root@docker02 ~]# docker run -d  --name registrator -v /var/run/docker.sock:/tmp/docker.sock  --restart always gliderlabs/registrator consul://192.168.1.13:8500

參數說明:

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

(3)開啓一臺nginx容器

[root@docker02 ~]# docker run -d —P --name nginx nginx:latest 

(4)瀏覽器查看一下http://192.168.1.11:8500/ui/dc1/nodes

Docker + Consul + registrator實現服務發現及nginx反向代理
Docker + Consul + registrator實現服務發現及nginx反向代理

八.docker01部署一個nginx服務

配置nginx,大概配置的思路爲:

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

(1)安裝開啓nginx服務

安裝nginx依賴包

[root@docker01 ~]#  yum -y install pcre pcre-devel openssl openssl-devel zlib zlib-devel

編譯安裝nginx

[root@docker01 ~]# cd nginx-1.14.0/
[root@docker01 nginx-1.14.0]# ./configure --user=nginx --group=nginx  --with-http_stub_status_module --with-http_realip_module --with-pcre --with-http_ssl_module && make && make install

創建所需用戶和鏈接命令目錄

[root@docker01 nginx-1.14.0]# useradd -M -s /sbin/nologin nginx
[root@docker01 nginx-1.14.0]# ln -s /usr/local/nginx/sbin/* /usr/local/bin/

檢查nginx是否有問題,並開啓nginx

[root@docker01 nginx-1.14.0]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@docker01 nginx-1.14.0]# nginx

PS:這裏nginx作爲反向代理,代理後端docker02、 docker03 上nginx的容器服務,所以我們先去docker02、docker03. 上部署一些服務, 爲了方便等會看到負載的效果,所以,我們運行完成容器之後,做一個主界面內容的區分。

(2)安裝完成之後,本機測試訪問

[root@docker01 nginx-1.14.0]# curl 127.0.0.1

Docker + Consul + registrator實現服務發現及nginx反向代理

(3)部署環境

主機 服務
docker02 nginx web01,web02
docker03 nginx web03,web04

<1>下載nginx鏡像(docker02,docker03都要)

[root@docker02 ~]# docker pull nginx
//下載nginx鏡像

<2>docker01操作

基於nginx鏡像運行上述所說的容器並設置測試頁面

web01
[root@docker02 ~]# docker run  -itd --name web01 -P nginx:latest
[root@docker02 ~]# docker exec -it web01 /bin/bash
root@44b59d07202f:/# cd /usr/share/nginx/html/
root@44b59d07202f:/usr/share/nginx/html# echo web01 > index.html

web02
[root@docker02 ~]# docker run  -itd --name web02 -P nginx:latest
[root@docker02 ~]# docker exec -it web02 /bin/bash
root@44b59d07202f:/# cd /usr/share/nginx/html/
root@44b59d07202f:/usr/share/nginx/html# echo web02 > index.html

<3>docker02操作

基於nginx鏡像運行上述所說的容器並設置測試頁面

web03
[root@docker03 ~]#  docker run  -itd --name web03 -P nginx:latest
[root@docker03 ~]#  docker exec -it web03 /bin/bash
root@fd8e8b2df136:/# cd /usr/share/nginx/html/
root@fd8e8b2df136:/usr/share/nginx/html#  echo web03 > index.html
root@fd8e8b2df136:/usr/share/nginx/html# exit

web04
[root@docker03 ~]#  docker run  -itd --name web04 -P nginx:latest
[root@docker03 ~]#  docker exec -it web04 /bin/bash
root@fd8e8b2df136:/# cd /usr/share/nginx/html/
root@fd8e8b2df136:/usr/share/nginx/html#  echo web04 > index.html
root@fd8e8b2df136:/usr/share/nginx/html# exit

(4)docker01更改nginx配置文件

[root@docker01 ~]# cd /usr/local/nginx/
//進入nginx配置文件目錄
[root@docker01 nginx]# mkdir consul
//創建consul目錄
[root@docker01 nginx]# cd consul/
//進入consul目錄

<1>創建nginx.ctmpl模板

[root@docker01 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。

<2>修改nginx配置文件,通過 include 參數包含剛剛創建的文件

[root@docker01 consul]# cd /usr/local/nginx/conf/
[root@docker01 conf]# vim nginx.conf
  include /usr/local/nginx/consul/*.conf;  #文件最後添加(要在大括號裏面)

<3> 生成一個vhost.conf配置文件,並重啓nginx(會佔用終端)

使用consul-template命令,根據模板生產新的配置文件,並重新加載nginx的配置文件。

[root@docker01 conf]# consul-template -consul-addr 192.168.1.11:8500 -template "/usr/local/nginx/consul/nginx.ctmpl:/usr/local/nginx/consul/vhost.conf:/usr/local/bin/nginx -s reload"

參數說明:

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

這時,這條命令會佔用終端,可以使用nohup命令讓它保持後臺運行,並重啓nginx服務。

[root@docker01 conf]# nohup consul-template -consul-addr 192.168.1.11:8500 -template   "/usr/local/nginx/consul/nginx.ctmpl:/usr/local/nginx/consul/vhost.conf:/usr/local/sbin/nginx -s reload"  &

查看一下文件是否生成,裏面是否有內容

[root@docker01 ~]# cd /usr/local/nginx/consul/
[root@docker01 consul]# ls
nginx.ctmpl  vhost.conf

Docker + Consul + registrator實現服務發現及nginx反向代理

[root@docker01 consul]# cat vhost.conf 

Docker + Consul + registrator實現服務發現及nginx反向代理

此時,應該能夠看到,新生產的vhost.conf配置文件已經生效,訪問本機8000端口可以得到不同容器提供的服務。

<4>測試訪問

[root@docker01 consul]# curl 127.0.0.1:8000
web01

Docker + Consul + registrator實現服務發現及nginx反向代理

此時可以看到負載均衡的效果!

<5>如果訪問不成功

查看端口8000是否開啓

[root@docker01 consul]# ss -lnt

檢查nginx配置文件

[root@docker01 consul]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

檢查自己編寫的nginx配置文件

[root@docker01 consul]# cd /usr/local/nginx/consul/
[root@docker01 consul]# cat 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配置文件沒問題,重啓nginx

[root@docker01 consul]# nginx -s reload

<6>測試自動發現

docker02 創建測試容器

[root@docker02 ~]# docker run  -itd --name web05 -P nginx:latest
[root@docker02 ~]# docker exec -it web05 /bin/bash
root@44b59d07202f:/# cd /usr/share/nginx/html/
root@44b59d07202f:/usr/share/nginx/html# echo web02 > index.html
[root@docker02 ~]# docker ps 

Docker + Consul + registrator實現服務發現及nginx反向代理

docker01查看

[root@docker01 consul]# cd /usr/local/nginx/consul/
[root@docker01 consul]# cat vhost.conf 

Docker + Consul + registrator實現服務發現及nginx反向代理

docker01測試訪問

[root@docker01 consul]# curl 127.0.0.1:8000

Docker + Consul + registrator實現服務發現及nginx反向代理

//同上

此時可以看到負載均衡的效果!

這時不需要考慮後端的web服務器添加還是刪除都會自動更新的,這是因爲在運行consul-template這條命令後添加的/usr/local/sbin/nginx -s reload的作用!

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