Elk-docker

本文接上篇ecs-docker-swarm,在实现ESC docker swarm并添加es-swarm-2 label:elk=yes基础上部署elk(elasticsearch、logstash、kibana),其中elasticsearch部署到label中elk=yes的节点也就是es-swarm-2

上文中的环境:

  • es-swarm-1(manager)
  • es-swarm-2(worker,label:elk=yes)

创建elk overlay

创建以elk命名的overlay network,之后elk的通信将通过elk overlay

1
2
3
eval $(docker-machine env swarm-1)

docker network create --driver overlay elk

创建elasticsearch service

创建global的elasticsearch service,并且通过constraint(参考docker-constraint)限制elasticsearch只能创建部署到label中elk=yes的节点,也就是es-swarm-2节点

1
2
3
4
5
6
7
8
docker service create --name elasticsearch \
    --mode global \
    --network elk \
    -p 9200:9200 \
    --constraint "node.labels.elk == yes" \
    --reserve-memory 500m \
    elasticsearch:2.4
    

因为后续的logstash servcie要依赖elasticsearch service所以要确保elasticsearch service完全启动后再去创建logstash。 如果是单独命令运行,只要用

1
docker service ps elasticsearch

去检查下elasticsearch的CURRENT STATE是不是Running,不是就等会儿。通过这个命令我们还可以看到elasticsearch在个个节点部署状态,下图可以看到elasticsearch已经运行,而且只有在es-swarm-2上是Running。

当然如果只是查看是否启动成功也可以

1
open http://$(docker-machine ip es-swarm-1):9200

直接打开浏览器看是否可以访问

如果elk整个启动是在一个脚本中运行,那就需要做一个等待处理。有很多方法,我这里采用的是过滤获取docker service ps命令日志信息来判断(方法自己感觉不是很好,如果有好办法欢迎指正)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

while true; do
    REPLICAS=$(docker service ps elasticsearch | grep es-swarm-2 | awk '{print $7}')
    echo "REPLICAS:"$REPLICAS
    A=$(docker service ps elasticsearch | grep es-swarm-2 | awk '{print $0}')
    echo $A
    if [[ $REPLICAS == "Running" ]]; then
        sleep 5
        echo "elasticsearch Running..."
        break
    else
        echo "Waiting for the elasticsearch service..."
        sleep 5
    fi
done

创建logstash service

添加logstash的配置文件,因为默认logstash的配置是

1
2
3
4
input {
    stdin {}
    syslog {}
}

我们要将logstash收集的日志输出到elasticsearch所以要创建配置文件,并再通过 mount让logstash读取修改后的配置

在本地创建config/logstash.conf,并修改为以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
input {
  syslog { port => 51415 }
}

output {
  elasticsearch {
    hosts => ["elasticsearch:9200"]
  }
  # Remove in production
  stdout {
    codec => rubydebug
  }
}

为了后面目录整齐,便于管理,我们创建统一docker目录。对于logstash的配置文件我们放到logstash目录中。并将docker目录传到两台ECS,也就是docker node上

1
2
3
4
mkdir -p docker/logstash
cp conf/logstash.conf docker/logstash/logstash.conf
scp -r docker root@xxx.xxx.xxx.xxx:/
scp -r docker root@xxx.xxx.xxx.xxx:/

创建logstash service。logstash service是global的,目前并没有通过label去限制logstash(正式环境视情况定),加入elk network,我们将上传到ECS的目录bind到了logstash的conf下,指定logstash的conf配置在/conf/logstash.conf。配置环境变量LOGSPOUT=ignore为后续logspout做准备

1
2
3
4
5
6
7
docker service create --name logstash \
    --mount "type=bind,source=/docker/logstash,target=/conf" \
    --mode global \
    --network elk \
    -e LOGSPOUT=ignore \
    --reserve-memory 100m \
    logstash:2.4 logstash -f /conf/logstash.conf

同样如果在一个脚本中,一样等待启动完成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
while true; do
    REPLICAS=$(docker service ps logstash | grep es-swarm-2 | awk '{print $7}')
    echo "REPLICAS:"$REPLICAS
     A=$(docker service ps logstash | grep es-swarm-2 | awk '{print $0}')
    echo $A
    if [[ $REPLICAS == "Running" ]]; then
        sleep 5
        echo "logstash Running..."
        break
    else
        echo "Waiting for the logstash service..."
        sleep 5
    fi
done

创建代理proxy overlay network。proxy用于代理与个个service间通信

1
docker network create --driver overlay proxy

通过swarm-listener、docker-flow-proxy实现swarm-mode-auto。swarm-listener监控swarm service的创建销毁事件,当service创建销毁时自动发送请求给docker-flow-proxy进行重新配置(reconfigure)。

创建swarm-listener service。-e环境变量意义部分参考文章swarm-mode-auto

1
2
3
4
5
6
7
8
docker service create --name swarm-listener \
    --network proxy \
    --mount "type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock" \
    -e DF_NOTIF_CREATE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/reconfigure \
    -e DF_NOTIF_REMOVE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/remove \
    --constraint 'node.role==manager' \
    vfarcic/docker-flow-swarm-listener
    

创建proxy service。80 http请求,443 https请求。外部请求通过proxy代理到目标service

1
2
3
4
5
6
7
docker service create --name proxy \
    -p 80:80 \
    -p 443:443 \
    --network proxy \
    -e MODE=swarm \
    -e LISTENER_ADDRESS=swarm-listener \
    vfarcic/docker-flow-proxy

一个shell脚本运行,确保服务启动。通过service ls的 replicas=1/1 确保swarm-listener 和 proxy启动完成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
while true; do
    REPLICAS=$(docker service ls | grep swarm-listener | awk '{print $3}')
    REPLICAS_NEW=$(docker service ls | grep swarm-listener | awk '{print $4}')
    if [[ $REPLICAS == "1/1" || $REPLICAS_NEW == "1/1" ]]; then
        break
    else
        echo "Waiting for the swarm-listener service..."
        sleep 5
    fi
done

while true; do
    REPLICAS=$(docker service ls | grep proxy | awk '{print $3}')
    REPLICAS_NEW=$(docker service ls | grep proxy | awk '{print $4}')
    if [[ $REPLICAS == "1/1" || $REPLICAS_NEW == "1/1" ]]; then
        break
    else
        echo "Waiting for the proxy service..."
        sleep 5
    fi
done

创建kibana service 并等待完成。kibana中的label作用参考swarm-mode-auto

1
2
3
4
5
6
7
8
9
10
11

docker service create --name kibana \
    --network elk \
    --network proxy \
    -e ELASTICSEARCH_URL=http://elasticsearch:9200 \
    --reserve-memory 50m \
    --label com.df.notify=true \
    --label com.df.distribute=true \
    --label com.df.servicePath=/app/kibana,/bundles,/elasticsearch \
    --label com.df.port=5601 \
    kibana:4.6

一个脚本运行时,确保服务启动

1
2
3
4
5
6
7
8
9
10
11
12

while true; do
    REPLICAS=$(docker service ls | grep proxy | awk '{print $3}')
    REPLICAS_NEW=$(docker service ls | grep proxy | awk '{print $4}')
    if [[ $REPLICAS == "1/1" || $REPLICAS_NEW == "1/1" ]]; then
        break
    else
        echo "Waiting for the proxy service..."
        sleep 5
    fi
done

访问kibana

1
open http://$(docker-machine ip es-swarm-1)/app/kibana

至此,在swarm mode 中部署elk完成。 完整脚本参考dm-swarm-services-elk

后续将通过logspout进行日志采集并发送到logstash再到elasticsearch,并通过kibana进行查看的例子 >>>

评论

Copyright © 2021 pangff 京ICP备14050056号-1 Design credit: Shashank Mehta