使用Fluentd在Docker网络中记录日志的问题及解决方案

54次阅读
没有评论

问题描述

在设置一个由三个运行小型Flask应用程序的Docker容器组成的网络时,遇到了一个关于日志记录的奇怪问题。他的Python应用程序如下所示:

from flask import Flask, request
import sys
import logging
import logging.handlers
import os

app = Flask(__name__)
logger = logging.getLogger('Logger')
logger.setLevel(logging.DEBUG)
log_handler = logging.StreamHandler(sys.stdout)
logger.addHandler(log_handler)
service_name = ""
if 'SERVICE_NAME' in os.environ:
    service_name = os.environ['SERVICE_NAME']
logger = logging.LoggerAdapter(logger, {"serviceName" : service_name})

@app.route("/ping")
def ping():
    logger.info(f'answering ping request')
    return f'{service_name} OK'

if __name__ == "__main__":
    logger.info("Started")
    app.run(debug=True, host='0.0.0.0')

他在一个Docker网络中启动了三个此应用程序的实例,并在nginx后面运行:

docker network create tNet
docker run -it -d -p 24224:24224 -v `pwd`:/fluentd/etc -e FLUENTD_CONF=fluentd.conf --name=fluentd_logging fluent/fluentd
docker run -d --log-driver=fluentd --name ms1 -e SERVICE_NAME="ms1" --network tNet testflask
docker run -d --log-driver=fluentd --name ms2 -e SERVICE_NAME="ms2" --network tNet testflask
docker run -d --log-driver=fluentd --name ms3 -e SERVICE_NAME="ms3" --network tNet testflask
docker run -d --name=nginx --network tNet --volume `pwd`/nginx.conf:/etc/nginx/conf.d/default.conf -p 2000:2000 -p 3000:3000 nginx

nginx的配置如下:

upstream app {
    server ms1:5000;
    server ms2:5000;
    server ms3:5000;
}

server {
    listen 2000;
    location / {
        proxy_pass http://app;
    }
}

Fluentd的配置如下:

<source>
    @type forward
</source>
<match>
    @type stdout
</match>

虽然使用curl可以看到每个服务实例都有响应:

curl localhost:2000/ping
ms1 OK
curl localhost:2000/ping
ms2 OK
curl localhost:2000/ping
ms3 OK

但当用户检查日志时,只能看到来自第三个服务实例的日志:

docker logs <fluent容器ID> | grep -Eis "answering ping"
19-08-06 15:34:46.000000000 +0000 be338a3d5aa0: {"container_id":"be338a3d5aa0b8920366fdf1ba2a267082cee47e681adcea16b6c51c9c82cf0d","container_name":"/ms3","source":"stdout","log":"answering ping request"}

解决方案

请注意以下操作可能因版本差异而有所不同,建议进行备份。
用户在这里遇到了Fluentd容器启动需要一些时间的问题。由于Fluentd容器是以--detach模式启动的,所以在后续的容器尝试连接之前,Fluentd实际上还没有完全运行。只有当Fluentd已经启动时,Flask应用程序的第三个实例才能连接。因此,通过延迟其他容器的启动,可以解决这个问题。

解决方案步骤

  1. 修改启动脚本,将其他Flask应用程序容器的启动延迟一段时间,以确保Fluentd容器已经完全运行。
  2. 可以使用一些简单的延迟机制,如在脚本中使用sleep命令。

以下是示例脚本修改:

#!/bin/bash
# 启动Fluentd容器
docker run -it -d -p 24224:24224 -v `pwd`:/fluentd/etc -e FLUENTD_CONF=fluentd.conf --name=fluentd_logging fluent/fluentd

# 延迟一段时间,等待Fluentd完全启动
sleep 5

# 启动其他Flask应用程序容器
docker run -d --log-driver=fluentd --name ms1 -e SERVICE_NAME="ms1" --network tNet testflask
docker run -d --log-driver=fluentd --name ms2 -e SERVICE_NAME="ms2" --network tNet testflask
docker run -d --log-driver=fluentd --name ms3 -e SERVICE_NAME="ms3" --network tNet testflask

# 启动Nginx容器
docker run -d --name=nginx --network tNet --volume `pwd`/nginx.conf:/etc/nginx/conf.d/default.conf -p 2000:2000 -p 3000:3000 nginx

通过在脚本中添加适当的延迟,可以确保所有Flask应用程序容器在Fluentd容器完全运行后才连接,从而解决日志记录问题。

这样,所有的Flask应用程序容器将有足够的时间连接到Fluentd容器,确保日志能够正确记录。

请注意,延迟的时间可以根据实际情况进行调整,以确保Fluentd容器已经完全就绪。

正文完