Docker的高可用解决方案

作者:管理员发表于:2019-01-28

Docker从2013年发布第一个版本以来,已经火遍全球,技术迭代也比较频繁,其周边产品和技术也越来越丰富。Docker的轻量级容器不仅实现了资源隔离,而且几乎可以运行在任何地方,使得部署和扩展变得非常容易,随着Docker的日趋完善,目前Docker已经被越来越多的公司应用到生产环境中。


 

一、docker简介

Docker是一个由GO语言写的程序运行的“容器”(Linux containers, LXCs);目前云服务的基石是操作系统级别的隔离,在同一台物理服务器上虚拟出多个主机。Docker则实现了一种应用程序级别的隔离; 它改变我们基本的开发、操作单元,由直接操作虚拟主机(VM),转换到操作程序运行的“容器”上来。

 

二、docker各组件

1、Docker:Docker daemon引擎。

2、consul:服务发现和配置共享的服务软件。

3、swarm:基于Docker的集群调度管理软件,Docker 1.2版本中已经自动集成集群功能了。

4、rethinkdb:RethinkDB是一个完全支持Memcached协议、数据可持久化的工业级key-value存储系统,它自带了cluster和web资源管理功能。

5、shipyard:Docker可视化资源管理平台

6、registrator:服务自动注册

7、nginx:web服务代理软件

8、consultemplate:Docker服务自动发现软件,这个要结合nginx使用,当我们在宿主机上启动一个容器服务时,这时候consultemplate就会自动从consul服务上发现在这个容器,并更新nginx配置文件。

9、cadvisor:google公司开源的docker容器资源监控软件

10、influxDB:InfluxDB是一个开源分布式时序、事件和指标数据库。使用 Go 语言编写,无需外部依赖。其设计目标是实现分布式和水平伸缩扩展。

11、grafana:图表展现服务,功能非常强大。

12、graylog+ Elasticsearch:具有报警选项的可插入日志和事件分析服务器。

 

三、安装consul服务

因为consul的高可用集群最少需要3台机器,但是这3台,只要其中一台故障这个consul的集群就挂了,按官方的建 议最好5台,这样可以同时故障2台。但是我为节省资源就用3台。

 

3.1、master:10.2.0.80

 

docker run -d \\

-p 8300:8300 \\

-p 8301:8301 \\

-p 8301:8301/udp \\

-p 8302:8302 \\

-p 8302:8302/udp \\

-p 8400:8400 \\

-p 8500:8500 \\

-p 8600:53 \\

-p 53:53/udp \\

-v /opt/test/data/consul:/data \\

-h $HOSTNAME \\

--restart=always \\

--name=consul progrium/consul:latest -server -bootstrap -ui-dir=/ui -advertise 10.2.0.80 -client 0.0.0.0

 

解释下各个参数:

-d容器在后台运行, detached mode

--restart=always重启模式, always 表示永远。

-p 8400:8400映射 consul的 rpc 端口8400。

-p 8500:8500映射 UI 界面的端口8500。

-p 53/udp绑定udp 端口53(默认 DNS端口)在 Docker0 bridge 地址上。

-v /opt/test/data/consul:/data  这个把consul的数据文件目录挂载到宿主机上,这样万一容器重启,数据就不会丢失。

 

3.2、slave1:10.2.0.77

docker run -d \\

-p 8300:8300 \\

-p 8301:8301 \\

-p 8301:8301/udp \\

-p 8302:8302 \\

-p 8302:8302/udp \\

-p 8400:8400 \\

-p 8500:8500 \\

-v /opt/test/data/consul:/data \\

-h $HOSTNAME \\

--restart=always \\

--name=consulprogrium/consul:latest\\

-server -join 10.2.0.80 -advertise 10.2.0.77 -client 0.0.0.0

 

3.3、slave2:10.2.0.134

docker run -d \\

-p 8300:8300 \\

-p 8301:8301 \\

-p 8301:8301/udp \\

-p 8302:8302 \\

-p 8302:8302/udp \\

-p 8400:8400 \\

-p 8500:8500 \\

-v /opt/test/data/consul:/data \\

-h $HOSTNAME \\

--restart=always \\

--name=consulprogrium/consul:latest\\

-server -join 10.2.0.80 -advertise 10.2.0.134 -client 0.0.0.0

 

这样consul集群服务已经安装完成,进入10.2.0.80启动的consul容器查看一下consul的状态

 

3.4、进入consul 容器

Docker exec -it d638539891e7 bash

#consul info   //查看consul状态,看到leader = true和server=true说明整集群状态已经正常了。

 

agent:

check_monitors = 0

check_ttls = 0

checks = 0

services = 29

build:

prerelease =

revision = 9a9cc934

version = 0.5.2

consul:

bootstrap = true

known_datacenters = 1

leader = true

server = true

#consul members   //

看到consul集群已检测到3台server了,并且状态都正常。

Node                                  Address          Status  Type    Build  Protocol  DC

10.2.0.80                          10.2.0.80:8301   alive   server  0.5.2  2         dc1

10.2.0.77                          10.2.0.77:8301   alive   server  0.5.2  2         dc1

10.2.0.134                        10.2.0.134:8301  alive   server  0.5.2  2         dc1

#现在就可以看到consul的web平台了,http://10.2.0.80:8500/ui/#/dc1/services。

 

四、安装swarm、shipyard管理平台

 

4.1、添加master:10.2.0.80节点

 

4.1.1、启动容器shipyard-rethinkdb

docker run -it -d -p 8080:8080 -h $HOSTNAME -v /opt/test/data:/data --restart=always  --name shipyard-rethinkdb rethinkdb:latest

参数解释:

-v /opt/test/data:data把rethinkdb的数据目录挂载到宿主机的/opt/test/data目录下,这样rethinkdb容器如果重启,数据不会丢失。

-p 8080:8080 映射rethinkdb的 web UI端口,这样可以看到rethinkdb的web可视化资源管理平台。

#为了增加rethinkdb的高可用,有条件的话可以把它做成一个cluster,具体参考https://github.com/dockerfile/rethinkdb。

 

4.1.2、启动shipyard-proxy

docker run  -ti  -d  -p 10.2.0.80:2375:2375  --hostname=$HOSTNAME --restart=always --name shipyard-proxy  -v /var/run/docker.sock:/var/run/docker.sock  -e PORT=2375  shipyard/docker-proxy:latest

 

4.1.3、启动shipyard-swarm-manager

docker run  -ti -d --restart=always --name shipyard-swarm-manager registry.intra.test.com:5000/ops/shipyard-swarm:v0.1 manage --replication --addr 10.2.0.80:3375 --host tcp://0.0.0.0:3375 consul://10.2.0.80:8500

 

4.1.4、启动shipyard-swarm-agent

docker run -ti  -d  --restart=always  --name shipyard-swarm-agent registry.intra.test.com:5000/ops/shipyard-swarm:v0.1  join --addr 10.2.0.80:2375 consul://10.2.0.80:8500

 

4.1.5、启动shipyard-controller

docker run -it -d --restart=always --name shipyard-controller --link shipyard-rethinkdb:rethinkdb --link shipyard-swarm-manager:swarm -p 80:8080 shipyard/shipyard:latest server -d tcp://swarm:3375

 

4.2、添加slave1:10.2.0.77节点

 

4.2.1、启动shipyard-proxy

docker run  -ti  -d  -p 10.2.0.77:2375:2375  --hostname=$HOSTNAME --restart=always --name shipyard-proxy  -v /var/run/docker.sock:/var/run/docker.sock  -e PORT=2375  registry.intra.test.com:5000/ops/shipyard-docker-proxy:v0.1

 

4.2.2、启动shipyard-swarm-agent

docker run -ti  -d  --restart=always  --name shipyard-swarm-agent registry.intra.test.com:5000/ops/shipyard-swarm:v0.1  join --addr 10.2.0.77:2375 consul://10.2.0.80:8500

 

4.2.3、添加registrator

registrator 是基于 Docker 的 sock 文件来做服务发现的一个第三方的方案,有实力的公司也可以自已开发服务注册agent。

docker run -d --restart=always --name=registrator --net=host -v /var/run/docker.sock:/tmp/docker.sock gliderlabs/registrator -ip 10.2.0.77 consul://localhost:8500

参数解释:

-v /var/run/docker.sock:/tmp/docker.sock映射 Docker 的 socket 到 container 中的对应位置,这样 registration 就能监控有哪些服务启动了。

registration 所属的主机 IP, 一定要设置此属性, 否则服务IP会显示为127.0.0.1

consul://localhost:8500consul 绑定到本地的 consul 接口上。

 

4.3、添加slave1:10.2.0.134节点

 

4.3.1、启动shipyard-proxy

docker run  -ti  -d  -p 10.2.0.134:2375:2375  --hostname=$HOSTNAME --restart=always --name shipyard-proxy  -v /var/run/docker.sock:/var/run/docker.sock  -e PORT=2375  registry.intra.test.com:5000/test/ops/shipyard-docker-proxy:v0.1

 

4.3.2、启动shipyard-swarm-agent

docker run -ti  -d  --restart=always  --name shipyard-swarm-agent registry.intra.test.com:5000/ops/shipyard-swarm:v0.1  join --addr 10.2.0.134:2375 consul://10.2.0.80:8500

 

4.3.3、添加registrator

docker run -d --restart=always --name=registrator --net=host -v /var/run/docker.sock:/tmp/docker.sock gliderlabs/registrator -ip 10.2.0.134 consul://localhost:8500

 

以上服务都启动后就可以访问shipyard的管理平台了http://10.2.0.80/#/containers,默认的用户名:admin,密码:shipyard ,通过这个平台就可以看到这3台宿主机上启动的所有容器,可以对它进行重启,暂停,部署,扩容等各种可视化操作。这个平台满足目前开发和测试的环境,我觉得问题不大,如果要用于生产环境,还是有几点以下问题的思考:

1、需要考虑shipyard管理平台本身的高可用。

2、整个集群的资源无法进行隔离,例如:这个集群我有10台slave宿主机,我想把其中的一个服务的10个容器只部署在3台宿主机上。目前这个集群做不到。

3、集群中的容器要做升级时,无法选择升级策略。

 

 

五、流量接入层配置

 

这边主要采用的是nginx+consul-template方案,我觉得nginx做代理,效率比较好,再说nginx的7层规则写起来也比较方便。当然也可以用别的方法,例如:dns、haproxy等。

consul-template主要是从consul自动发现service的主机+端口信息,这样一组服务的容器在减缩时,可以做到自动伸缩,不需要人为干预。

 

5.1、nginx服务

nginx服务可以选择原生的,也可以选择阿里的tenginx,也可以选择sina开源的一个nginx模块,不过用这个不需要consul-tempate支持并且是即时生效的,并且不需要reload nginx服务,所以没有性能损耗。https://github.com/weibocom/nginx-upsync-module。

 

5.2、consul-template

#nginx模块文件

vim log.test.com.ctmpl

upstream www.test.com {

{{range service "nginx-test-80"}}

server {{.Address}}:{{.Port}};

#server {{.Address}}:{{.Port}} weight=10 max_fails=3 fail_timeout=10s;

{{end}}

keepalive 65;

#check interval=3000 rise=2 fall=5 timeout=3000 type=http

#check_http_send "GET /health HTTP/1.1\\r\\n\\r\\n";

#check_http_expect_alive http_2xx http_3xx;

}

server {

listen       80;

server_name  www.test.com;

location / {

proxy_pass http://www.test.com;

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;

proxy_next_upstream error timeout invalid_header http_500 http_502 h

ttp_503 http_504;

proxy_max_temp_file_size 0;

proxy_connect_timeout      90;

proxy_send_timeout         90;

proxy_read_timeout         90;

proxy_buffer_size          4k;

proxy_buffers              4 32k;

proxy_busy_buffers_size    64k;

proxy_temp_file_write_size 64k;

}

error_page   500 502 503 504  /50x.html;

location = /50x.html {

root   html;

}

}

 

#consu-template配置文件

consul = "10.2.0.80:8500"

log_level = "warn"

#token  = "f37ab43b-4d2de-aa283-6effsdf507a9eb71d1b”   //如果consul有配token,需要加上token,不然是取不到数据。

template {

source = "/opt/test/consultemplate/www.test.com.ctmpl"

destination = "/opt/test/nginx/conf/conf.d/www.test.com.conf"

command = “/opt/test/nginx/sbin/nginx -t && /opt/test/nginx/sbin/nginx -s

reload"

}

 

#启动consul-template服务./consul-template --config check_nginx.conf

启动结果:

 

"check_nginx.conf"

the configuration file /opt/test/nginx/conf/nginx.conf syntax is ok

configuration file /opt/test/nginx/conf/nginx.conf test is successful

 

 

六、容器资源监控

 

我们通过三个组件(cadvisor influxdb grafana)来搭建一个监控容器主机系统的实时信息。这里面有一个重要的问题,需要大家明确一个问题,因为容器有一个很重要的特性就是随时启动运行,随时停止销毁,所以我们的监控也需要支持,能够随着容器的启动运行,并自动加入监控,当销毁时,监控能够自动删除,这样就不需要人工过多的干预。

 

6.1、部署influxdb

docker pulltutum/influxdb:0.10

docker run -d \\

-p8083:8083 \\

-p 8086:8086 \\

--expose 8090 \\

--expose 8099 \\

-v  /opt/test/data/influxdb:/data  \\

--name influxsrv  tutum/influxdb:0.10

参数解释:

-p 8083:8083映射8083端口,是为能够看到influxdb的web管理平台。

-p 8086:8086映射8086端口,数据api接口,到时候cadvisor会访问这个接口。

-v /opt/test/data/influxdb:/data映射数据目录到宿主机上,这样容器重启保证数据不会丢失。

#docker ps

b2da5c842a06        tutum/influxdb:0.10                                                  "/run.sh"                5 days ago          Up 23 hours         0.0.0.0:8083->8083/tcp, 8090/tcp, 0.0.0.0:8086->8086/tcp, 8099/tcp                                                                   influxsrv

#新建数据库

docker exec -ti influxsrv /bin/bash

root@b2da5c842a06:/# influx

Visithttps://enterprise.influxdata.comto register for updates, InfluxDB server management, and monitoring.

Connectedtohttp://localhost:8086 version 0.10.0

InfluxDBshell0.10.0

>CREATEDATABASEcadvisor

>SHOWDATABASES

name:databases

---------------

name

_internal

cadvisor

>usecadvisor

>CREATEUSER"root"WITHPASSWORD'root'WITHALLPRIVILEGES

>showusers

useradmin

roottrue

>exit

 

6.2、部署cadvisor服务

docker run -d \\

--volume=/:/rootfs:ro \\

--volume=/var/run:/var/run:rw \\

--volume=/sys:/sys:ro \\

--volume=/var/lib/docker/:/var/lib/docker:ro \\

--publish=8080:8080 \\

--detach=true \\

--link influxsrv:influxsrv \\

--name=cadvisor google/cadvisor:latest \\

-docker_only \\

-h $HOSTNAME

-storage_driver=influxdb \\

-storage_driver_db=cadvisor \\

-storage_driver_host=10.2.0.134:8086

#启动容器后,用浏览器就可以看到本机所有容器的时时监控信息了。http://10.2.2.134:8080。

参数解释:

-docker_only:这个参数主要是说明现在cadvisor容器只监控容器,如果不加会把docker相关一堆没有用的信息都加进来,对后续添加grafana时带来很多的麻烦。

-h $HOSTNAME:这个参数很重要,一定要加上,不然后面的grafana取监控主机时,只能看到的是一串数字,很不方便,加上这个参数,就可以直接看到主机名了,一目了然。

 

6.3、部署grafana服务

docker run -d \\

-p 3000:3000 \\

-e INFLUXDB_HOST=10.2.0.134 \\

-e INFLUXDB_PORT=8086 \\

-e INFLUXDB_NAME=cadvisor \\

-e INFLUXDB_USER=root \\

-e INFLUXDB_PASS=root \\

--link influxsrv:influxsrv \\

--name grafana grafana/grafana