Docker 1.12 Swarm集群实战(第五章)
补充一些遗漏的问题.本章主要内容:使用 constraints 指定 service 约束.service 挂载使用本地volume.ELK日志平台使用GELF日志驱动收集日志.1. 指定service约束在前几章中, 我们创建的 registry 服务,是由swarm自动调度定义执行在某个节点上的. 这样的话我们如果我们重启 service 以后, registr
补充一些遗漏的问题.
本章主要内容:
- 使用
constraints
指定service
约束. service
挂载使用本地volume.- ELK日志平台使用GELF日志驱动收集日志.
1. 指定service约束
在前几章中, 我们创建的 registry
服务,是由swarm自动调度定义执行在某个节点上的. 这样的话我们如果我们重启 service
以后, registry
服务可能会被启动再随机的节点.
造成我们上传的镜像都不见了. 如何解决这个问题呢?
在创建service的时候可以使用 --constraints
参数,后面跟表达式,限制service容器在每个节点的调度情况.比如你想指定service运行在某个节点上等.
例如指定service运行在node01上:
docker service create --name registry --publish 5000:5000 \
--constraint 'node.hostname==node01' registry
除了 hostname
也可以使用其他节点属性来创建约束表达式写法参见下表:
节点属性 | 匹配 | 示例 |
---|---|---|
node.id | 节点 ID | node.id == 2ivku8v2gvtg4 |
node.hostname | 节点 hostname | node.hostname != node02 |
node.role | 节点 role: manager | node.role == manager |
node.labels | 用户自定义 node labels | node.labels.security == high |
engine.labels | Docker Engine labels | engine.labels.operatingsystem == ubuntu 14.04 |
用户自定义labels可以使用 docker node update
命令添加, 例如:
# docker node update --label-add security=high node01
查看自定义labels
# docker node inspect node01
[
{
"ID": "0nhjsflo3tbd0b7hv2cyrjpin",
...
"Spec": {
"Labels": {
"security": "high"
},
"Role": "manager",
"Availability": "active"
},
"Description": {
"Hostname": "node01",
"Platform": {
"Architecture": "x86_64",
"OS": "linux"
},
...
}
]
对于已有service, 可以通过 docker service update
,添加 constraint
配置, 例如:
docker service update registry \
--constraint-add 'node.labels.security==high'
2. volume 创建管理
有了service约束, 我们可以保证我们的 registry
服务, 一直在node01节点上了. 不过还有一个问题, 就是如果我们删除了 registry
服务. 那我们上传的容器镜像也就被删除了.
如何保证即使 registry
服务被删除, 镜像可以保留呢?
这里我们可以使用 docker volume
指定挂载一个数据卷用来保存镜像, 即使 registry
服务被删除了. 我们重新启动一个服务, 挂载这个数据卷. 我们上传的镜像还可以保存的.
在 swarm
集群中我们可以创建本地卷或者全局卷来挂载到容器, 用来保存数据.
-
全局卷可以被挂载在
swarm
集群的任意节点, 所以不管你的服务容器启动在哪个节点, 都可以访问到数据. 不过docker目前还没有默认的全局卷驱动支持, 你可以安装一些插件驱动来实现全局卷例如Flocker, Portworx等. -
本地卷, 就只存在与某个节点本地的一个挂载卷.
Storage is Hard
这里我们还是使用简单的本地卷吧, ^_^
.
为我们刚刚新建的 registry
服务, 挂载一个本地卷,可以使用如下命令:
docker service update registry \
--mount-add type=volume,source=registry-vol,target=/var/lib/registry
source=registry-vol
中 registry-vol
为卷名字, 执行上述命令以后,docker会自动为我们创建一个 registry-vol
本地卷.
可以使用 docker volume ls
命令查看:
# docker volume ls
DRIVER VOLUME NAME
local registry-vol
# docker volume inspect registry-vol
[
{
"Name": "registry-vol",
"Driver": "local",
"Mountpoint": "/var/lib/docker/volumes/registry-vol/_data",
"Labels": null,
"Scope": "local"
}
]
上面命令, 可以看到本机卷挂载到节点的目录.
这样即使我们现在删除 registry
服务. 也可以只用如下命令重新创建一个 registry
服务, 挂载 registry-vol
来找回我们的镜像.
docker service create --name registry --publish 5000:5000 \
--mount source=registry-vol,type=volume,target=/var/lib/registry \
-e SEARCH_BACKEND=sqlalchemy \
--constraint 'node.hostname==node01' registry
测试
使用docker-compose 编译上传我们的docker币镜像
[root@node01 ~]# git clone https://github.com/jpetazzo/orchestration-workshop.git
[root@node01 ~]# orchestration-workshop/dockercoins
[root@node01 dockercoins]# cat docker-compose.yml-images
version: "2"
services:
rng:
build: rng
image: ${REGISTRY_SLASH}rng${COLON_TAG}
ports:
- "8001:80"
hasher:
build: hasher
image: ${REGISTRY_SLASH}hasher${COLON_TAG}
ports:
- "8002:80"
webui:
build: webui
image: ${REGISTRY_SLASH}webui${COLON_TAG}
ports:
- "8000:80"
volumes:
- "./webui/files/:/files/"
redis:
image: redis
worker:
build: worker
image: ${REGISTRY_SLASH}worker${COLON_TAG}
上传我们的应用镜像到 registry
export REGISTRY_SLASH=localhost:5000/
export COLON_TAG=:v0.01
docker-compose -f docker-compose.yml-images build
docker-compose -f docker-compose.yml-images push
测试 registry
内容
[root@node01 dockercoins]# curl localhost:5000/v2/_catalog
{"repositories":["hasher","rng","webui","worker"]}
删除 registry
服务
[root@node01 dockercoins]# docker service ls
ID NAME REPLICAS IMAGE COMMAND
5qvu78ths5wb registry 1/1 registry
[root@node01 dockercoins]# docker service rm registry
registry
服务删除以后我们可以看到本地卷还在.
[root@node01 dockercoins]# docker volume ls
DRIVER VOLUME NAME
local registry-vol
重建 registry
服务, 挂载 registry-vol
卷.
[root@node01 dockercoins]# docker service create --name registry --publish 5000:5000 --mount source=registry-vol,type=volume,target=/var/lib/registry -e SEARCH_BACKEND=sqlalchemy --constraint 'node.hostname==node01' registry
[root@node01 dockercoins]# curl localhost:5000/v2/_catalog
{"repositories":["hasher","rng","webui","worker"]}
3. ELK日志平台使用GELF驱动收集日志
上一章我们介绍了ELK日志平台, 用于管理收集swarm集群的应用日志. 当时我们使用的logspout容器, 自动将我们swarm节点上所有容器日志发送的日志平台.
可是如果我们关心特定容器的日志, 并不想收集其他容器的日志怎么办呢?
我们可以时候创建service的时候使用 --log-driver
参数, 使用GELF驱动将日志发送到ELK平台.
创建ELK平台
上一章已经有详细说明了, 下面这里简单过一下, 凑字数.哈哈…
创建Logging网络
docker network create --driver overlay logging
创建Elasticsearch服务
docker service create --network logging --name elasticsearch \
--mount source=elasticsearch-vol,type=volume,target=/usr/share/elasticsearch \
--constraint 'node.hostname==node02' \
elasticsearch
创建Kibana服务
docker service create --network logging --name kibana --publish 5601:5601 \
-e LOGSPOUT=ignore -e ELASTICSEARCH_URL=http://elasticsearch:9200 kibana
创建Logstash服务
我们重新build一个logstash镜像, 使用 ~/orchestration-workshop/elk/logstash.conf
这个配置文件.
[root@node01 ~]cd ~/orchestration-workshop/elk/
[root@node01 elk]# cat Dockerfile
FROM logstash
COPY logstash.conf /etc/logstash/
CMD ["-f", "/etc/logstash/logstash.conf"]
[root@node01 elk]# docker build -t localhost:5000/logstash .
[root@node01 elk]# docker push localhost:5000/logstash
启动logstash
docker service create --network logging --name logstash -p 12201:12201/udp \
localhost:5000/logstash
发送容器日志到logstash
我们已经有了ELK平台, 下面我们启动 docker币
应用, 发送容器日志到logstash.
很简单, 只要在创建 service
的时候添加 --log-driver
和 --log-opt
两个参数就行了.
#创建应用网络
docker network create --driver overlay dockercoins
#启动我们的docker币 webui应用
DOCKER_REGISTRY=localhost:5000
TAG=v0.01
docker service create --network dockercoins --name webui \
--log-driver gelf --log-opt gelf-address=udp://127.0.0.1:12201 \
-p 8000:80 $DOCKER_REGISTRY/webui:$TAG
使用下面这段脚本启动hasher rng worker 应用:
DOCKER_REGISTRY=localhost:5000
TAG=v0.01
for SERVICE in hasher rng worker; do
docker service create --network dockercoins --name $SERVICE \
--log-driver gelf --log-opt gelf-address=udp://127.0.0.1:12201 \
$DOCKER_REGISTRY/$SERVICE:$TAG
done
启动redis数据库:
docker service create --network dockercoins \
--limit-memory 100M --name redis \
--mount source=redis-vol,type=volume,target=/data \
--constraint 'node.hostname==node03' \
redis
为了方便观看日志, 我们sacle up下应用, 多启动一些容器:
docker service scale worker=10 rng=10
好了现在用浏览器, 打开Kibana( http://192.168.33.101:5601/ ), 我们就可以看到容器日志了.
##4. visualier
visualizer是一个小程序,用于可视化 swarm
集群容器分布情况.
在 swarm
的manager节点上运行, HOST
参数指定节点IP地址.
docker run --name visualizer -d \
-p 8089:8089 \
-e HOST=192.168.33.101 \
-e PORT=8089 \
-v /var/run/docker.sock:/var/run/docker.sock \
manomarks/visualizer
浏览器访问 http://192.168.33.101:8089/ 容器多了不是很好看 :-(
最后
挖坑, 有了日志收集平台, 我们还需要性能监控平台, 所以下一章介绍下如何使用cadvisor, influxdb, grafana搭建简单的swarm性能监控平台.
influxdb
docker service create --network logging \
-p 8083:8083 -p 8086:8086 \
--mount source=influxdb-vol,type=volume,target=/var/lib/influxdb \
--name=influxdb --constraint 'node.hostname==node03' \
influxdb:alpine
docker service create --network logging --name cadvisor --mode global \
--mount source=/var/run/,type=bind,target=/var/run,readonly=false \
--mount source=/,type=bind,target=/rootfs,readonly=true \
--mount source=/sys,type=bind,target=/sys,readonly=true \
--mount source=/var/lib/docker/,type=bind,target=/var/lib/docker,readonly=true \
google/cadvisor:latest -storage_driver=influxdb -storage_driver_host=influxdb:8086 \
-storage_driver_db=cadvisor
docker service create --network logging -p 3000:3000 -e INFLUXDB_HOST=influxdb -e INFLUXDB_PORT=8086 -e INFLUXDB_NAME=grafana -e INFLUXDB_USER=root -e INFLUXDB_PASS=root -e "GF_SECURITY_ADMIN_PASSWORD=admin" --constraint 'node.hostname==node05' --name grafana grafana/grafana
更多推荐
所有评论(0)