补充一些遗漏的问题.

本章主要内容:

使用 

constraints

  1.  指定 

serviceservice

  1. 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/