补充一些遗漏的问题.
本章主要内容:
使用
constraints
- 指定
serviceservice
- ELK日志平台使用GELF日志驱动收集日志.
1. 指定service约束
registry 服务,是由swarm自动调度定义执行在某个节点上的. 这样的话我们如果我们重启 service 以后, registry
造成我们上传的镜像都不见了. 如何解决这个问题呢?
--constraints
例如指定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 |
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"
},
...
}
]
docker service update ,添加 constraint配置, 例如:
docker service update registry \
--constraint-add 'node.labels.security==high'
2. volume 创建管理
registry 服务, 一直在node01节点上了. 不过还有一个问题, 就是如果我们删除了 registryregistrydocker volume 指定挂载一个数据卷用来保存镜像, 即使 registryswarmswarm
- 本地卷, 就只存在与某个节点本地的一个挂载卷.
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-voldocker 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节点上所有容器日志发送的日志平台.
可是如果我们关心特定容器的日志, 并不想收集其他容器的日志怎么办呢?
--log-driver
创建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
http://192.168.33.101:5601/
创建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
docker币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
swarmswarm 的manager节点上运行, HOST
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
http://192.168.33.101:8083/
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
http://192.168.33.101:3000/