注:写这篇文章花了不少时间 ,但是里面肯定还有不少错误,有什么问题可以提问,我有时间一定解答。这里面还缺少了一个很重要流程就是结合jenkins来做自动构建镜像,稍后我有时间再补上。
Docker从2013年发布第一个版本以来,已经火遍全球,技术迭代也比较频繁,其周边产品和技术也越来越丰富。Docker的轻量级容器不仅实现了资源隔离,而且几乎可以运行在任何地方,使得部署和扩展变得非常容易,随着Docker的日趋完善,目前Docker已经被越来越多的公司应用到生产环境中。
一、环境
1.1、宿主机操作系统环境
Centos7.1-64
1.2、docker版本
Server Version: 1.9.1
1.3、集群网络环境
master:10.2.0.80
slave1:10.2.0.77
slave2:10.2.0.134
服务发现:10.2.0.99
二、介绍一下各组件
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
具有报警选项的可插入日志和事件分析服务器
三、安装Docker
具体的安装方法可以参考官方文档:
https://docs.docker.com/engine ... ntos/
针对 CentOS, 则需要修改以下配置文件:
vim /etc/sysconfig/docker
如果没有个docker配置文件,可以把以下这段直接加上,
#
other_args="-g /opt/test/docker -H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock --insecure-registry registry.intra.test.com:5000 "
DOCKER_CERT_PATH=/etc/docker
DOCKER_NOWARN_KERNEL_VERSION=1
DOCKER_TMPDIR=/opt/docker/tmp
以上配置文件主要修改3点
1、docker安装的一些初始化信息变更。例如原来容器安装完,它们相关的信息默认是存储在/var/lib/docker目录下,我现在把安改到/opt/docker目录下,因为以后所有容器产生的日志等相关数据都会存在这个目录下,所以尽量选择一个大的分区。
2、docker daemon的socket绑定信息
3、增加了私有仓库地址,如果没有私有仓库,那就可以不用改。
然后你就可以启动Docker服务了.
systemctl enable docker && service start docker
四、安装consul服务
这就开始了,因为有了docker,所以千万就不要再想着用源代码或者rpm方式来安装相关服务,那样就显得太low了,以后一切的服务皆可用容器方式来运行。consul相关的资料请参考官网 https://www.consul.io/intro/ge ... .html ,如果还有不理解的就查查google吧,与它类似的服务还有etcd,zookeeper,doozerd等,这方面我就不多说了。因为consul的高可用集群最少需要3台机器,但是这3台,只要其中一台故障这个consul的集群就挂了,按官方的建 议最好5台,这样可以同时故障2台,但是我为节省资源就用3台。所以我在master,slave1,slave2的机器都安装了consul服务
4.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
解释下各个参数:
然后咱们开始部署其它2台consul agent机器, 这次要增加 -join 参数
4.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=consul progrium/consul:latest /
-server -join 10.2.0.80 -advertise 10.2.0.77 -client 0.0.0.0
4.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=consul progrium/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的状态
4.4、进入consul 容器
docker exec -it d638539891e7 bash
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
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
#现在就可以看到consul的web平台了
http://10.2.0.80:8500/ui/#/dc1/services
五、安装swarm、shipyard管理平台
swarm的具体资料可以参考官网 https://docs.docker.com/swarm/overview/
shipyard的具体资料可以参考官网是 http://www.shipyard-project.com
shipyard的官网的具体安装步骤 http://www.shipyard-project.co ... nual/
但是不要看着他们的安装步骤, 就直接开始了,因为官网用的是 etcd 不是 consul 的, consul 是 docker 官网推荐的,像大的互联网公司用的基本上是consul,所以我也推荐。
5.1、添加master:10.2.0.80节点
5.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
参数解释:
为了增加rethinkdb的高可用,有条件的话可以把它做成一个cluster,具体参考 https://github.com/dockerfile/rethinkdb
5.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
5.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
5.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
5.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
5.2、添加slave1:10.2.0.77节点
5.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
5.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
5.2.3、添加registrator
registrator 是基于 docker 的 sock 文件来做服务发现的一个第三方的方案,有实力的公司也可以自已开发服务注册agent。
registrator的官网资料参考 http://gliderlabs.com/registrator/latest/
docker run -d --restart=always --name=registrator --net=host -v /var/run/docker.sock:/tmp/docker.sock gliderlabs/registrator -ip ip-of-host consul://localhost:8500
例: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
参数解释:
参考资料:
Docker DNS & Service Discovery with Consul and Registrator
5.3、添加slave1:10.2.0.134节点
5.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
5.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
5.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
Docker DNS & Service Discovery with Consul and Registrator
以上服务都启动后就可以访问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的主机+端口信息,这样一组服务的容器在减缩时,可以做到自动伸缩,不需要人为干预。
6.1、nginx服务
nginx服务可以选择原生的,也可以选择阿里的tenginx
也可以选择sina开源的一个nginx模块,不过用这个不需要consul-tempate支持并且是即时生效的,并且不需要reload nginx服务,所以没有性能损耗。 https://github.com/weibocom/nginx-upsync-module
6.2、consul-template
upstream www.test.com {
{{range service "nginx-test-80"}}
server {{.Address}}:{{.Port}};
{{end}}
keepalive 65;
}
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 --config check_nginx.conf
启动结果:
2016/07/05 14:50:56 [DEBUG] (config) loading configs from "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
---------------------------------------------------------------------------------------
在本机绑定一下hosts,在浏览器中输入 www.test.com ,肯定有惊喜 ^-^!
七、容器资源监控
我们通过三个组件(cadvisor influxdb grafana)来搭建一个监控容器主机系统的实时信息。这里面有一个重要的问题,需要大家明确一个问题,因为容器有一个很重要的特性就是随时启动运行,随时停止销毁,所以我们的监控也需要支持,能够随着容器的启动运行,并自动加入监控,当销毁时,监控能够自动删除。这样就不需要人工过多的干预。
这边介绍下几个组件的功能,cadvisor谷歌公司自己用来监控他们基础设施的一款工具,这个工具厉害之处不仅能监控docker容器的实时信息,而且还能将你的cadvisor这容器所在的主机的系统的实时信息!,但是由于cadvisor只是能监控到实时的信息而不能保存,所以我们要使用influxdb将这些实时监控到的信息存放起来,以备以后需要。而grafana这个就是将influxdb存放的信息以图表的形式,非常清晰,完美地展现出来!
7.1、部署influxdb
具体可以参考 https://github.com/tutumcloud/influxdb
docker pull tutum/influxdb:0.10
docker run -d /
-p 8083:8083 /
-p 8086:8086 /
--expose 8090 /
--expose 8099 /
-v /opt/test/data/influxdb:/data /
--name influxsrv tutum/influxdb:0.10
参数解释:
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
Visit https://enterprise.influxdata.com to register for updates, InfluxDB server management, and monitoring.
Connected to http://localhost:8086 version 0.10.0
InfluxDB shell 0.10.0
CREATE DATABASE cadvisor
SHOW DATABASES
name
_internal
cadvisor
use cadvisor
CREATE USER "root" WITH PASSWORD 'root' WITH ALL PRIVILEGES
show users
user admin
root true
exit
7.2、部署cadvisor服务
具体可以参考 https://github.com/google/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
参数解释:
别的参数我就不解释了,大家可以看看文档,我就说一个最重要的。
7.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
还有具体的使用方法,可以参考官方网站,如果有什么不懂可以参考官方的例子很方便的。 http://play.grafana.org/
7.4、监控实例
八、日志收集
我这边用的是graylog,为什么要用这个日志的方案,有兴趣的朋友可以看一下这篇文章( https://testerhome.com/topics/3026 ),当然有开发实力的朋友,很多功能是可以自已去开发解决的。但是如果开源的产品也符合我们的需求,就不需要再重复的造轮子了。还有一点,这个日志的方案也是docker官方推荐的,所以我想应该也是不错的。( https://docs.docker.com/engine ... view/ )
8.1、graylog部署方法
graylog安装方法,我这边用测试用的是官方的docker-compose的方法,如果实际生产环境使用,如果量比较大的就需要采用分布式部署了。
http://docs.graylog.org/en/2.0 ... .html
这套日志系统唯一的缺点,我觉得是在mongodb上,所以如果量比较大的话,这个可能是一个瓶颈,当然mongodb的使用方案,现在也比较成熟,比如多个shard.还有公司如果有钱,用ssd盘来解决,问题也不大。这些都是需要随着业务的发展,去不断优化的。
some-mongo:
image: "mongo:3"
volumes:
- /opt/graylog/data/mongo:/data/db
some-elasticsearch:
image: "elasticsearch:latest"
command: "elasticsearch -Des.cluster.name='graylog'"
volumes:
- /opt/graylog/data/elasticsearch:/usr/share/elasticsearch/data
graylog:
image: graylog2/server
volumes:
- /opt/graylog/data/journal:/usr/share/graylog/data/journal
- /opt/graylog/config:/usr/share/graylog/data/config
environment:
GRAYLOG_PASSWORD_SECRET: somepasswordpepper
GRAYLOG_ROOT_PASSWORD_SHA2: 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
GRAYLOG_REST_TRANSPORT_URI: http://10.2.0.134:12900
links:
- some-mongo:mongo
- some-elasticsearch:elasticsearch
ports:
- "9000:9000"
- "12900:12900"
- "12201/udp:12201/udp"
- "1514/udp:1514/udp"
---------------------------------------------------------------------------------------------------------------------
8.2、启动graplog服务
docker-compose up -d
8.3、 http://10.2.0.134:9000/
用户名:admin
密码:graylog
8.4、设置接收器。
我这里用的是Gelf UDP的input方法来接收日志,用udp协议的好处是,当日志系统性能有问题或者别的故障时,不会影响生产服务。
system==>input==>select input ===>GELF UDP
8.5、设置容器的日志收集方法
大家都知道我们的每个容器产生的日志会自动保存在/var/lib/docker/containers/7e7cb74f63xxxxxxxxx/7e7cb74f63xxxxxxxxx.json.log
所以我们收集日志的方法很多:
a、可以在本地启动一个收集日志的工具,时时监听这个日志文件
b、可以用docker原生自带的log-driver方法来收集日志,我是比较偏向这个,因为日志存本地,对于请求量比较大的业务,IO是一项极大的挑战。
注:如果想把docker的应用日志输出到外面,也就是说用docker logs -f可以看到,需要我们在编写dockerfile时把日志做一下处理。
例如:nginx服务 参考官方 https://www.nginx.com/blog/dep ... cker/
FROM centos:centos7
MAINTAINER NGINX Docker Maintainers " docker-maint@nginx.com "
RUN yum install -y ca-certificates
ADD nginx-repo.crt /etc/ssl/nginx/
ADD nginx-repo.key /etc/ssl/nginx/
RUN wget -q -O /etc/yum.repos.d/nginx-plus-7.repo https://cs.nginx.com/static/fi ... .repo
RUN yum install -y nginx-plus
RUN ln -sf /dev/stdout /var/log/nginx/access.log
RUN ln -sf /dev/stderr /var/log/nginx/error.log
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
---------------------------------------------------------
access.log -> /dev/stdout
error.log -> /dev/stderr
如果容器里的应用服务用supervisord来管理,那么需要把supervisord的服务配置文件做以下设置,应用的日志才会对外输出。
[program:nginx]
command=/usr/sbin/nginx -g 'daemon off;'
autostart = true
startsecs = 3
autorestart = true
startretries = 3
user = root
redirect_stderr = false
stdout_logfile_maxbytes=0
stdout_logfile=/dev/stdout
stderr_logfile_maxbytes=0
#设置单个docker的日志收集方法
docker run -d -p 80 /
-h $HOSTNAME /
--name www.test-01 /
--log-driver=gelf /
--log-opt gelf-address=udp://10.2.0.134:12201 /
registry.intra.test.com:5000/ops/nginx-test:v0.1
这样的好处是,不用每次创建容器时,都需要指定日志的接收器的地址。
---------------------------------------------------------
#
other_args="-g /opt/docker -H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock --insecure-registry registry.intra.test.
com:5000 "
other_args="-g /opt/docker -H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock --log-driver=gelf --log-opt gelf-address=udp://10.2.0.134:12201 --insecure-registry registry.intra.test.
com:5000 "
DOCKER_NOWARN_KERNEL_VERSION=1
8.6、监控实例
这个日志面板生成功能非常方便,简单易用,随时用随时生成。还有最重要的这套日志系统,还可以设置数据流的报警功能,需要大家自已去研究使用。并且有完善的用户管理体系。