Google Kubernetes Engine中Python应用Stackdriver日志重复问题排查
解决GKE中Python应用日志重复且级别错误的问题
我之前在GKE上部署Python应用接入Stackdriver Logging时,也碰到过一模一样的日志重复问题,刚好可以帮你理清根源和解决办法:
问题根源
你猜的没错,核心原因是双重日志采集:
- 你通过
google.cloud.logging.Client().setup_logging()配置了SDK直接将日志发送到Stackdriver,生成的是jsonPayload格式、级别正确的日志条目。 - GKE集群默认的Fluentd采集器会自动抓取容器的
stdout和stderr输出,而Python默认的StreamHandler会把日志输出到stderr(尤其是当webapp2开启debug=True时,这个行为更明显)。Fluentd默认会把stderr的所有输出标记为ERROR级别,所以就出现了那条错误标记级别的textPayload重复日志。
解决办法
方法一:禁用Python默认的StreamHandler(推荐)
直接在应用代码里移除root logger中除了Cloud Logging Handler之外的所有handler,让日志只通过SDK发送,不再输出到stderr:
修改你的日志配置代码如下:
import webapp2 from paste import httpserver import rpc import logging # Imports the Google Cloud client library import google.cloud.logging from google.cloud.logging.handlers import CloudLoggingHandler # Instantiates a client client = google.cloud.logging.Client() # Connects the logger to the root logging handler client.setup_logging() # 移除root logger中的默认StreamHandler,避免日志输出到stderr root_logger = logging.getLogger() for handler in list(root_logger.handlers): if not isinstance(handler, CloudLoggingHandler): root_logger.removeHandler(handler) app = webapp2.WSGIApplication([('/rpc/([A-Za-z]+)', rpc.RpcHandler),], debug=True) httpserver.serve(app, host='0.0.0.0', port='80')
这样修改后,Python日志只会通过Cloud Logging SDK直接发送到Stackdriver,不会再输出到容器的stderr,自然就不会被Fluentd重复采集了。
方法二:调整GKE的Fluentd采集配置(适合集群级管控)
如果你需要保留容器stderr的其他输出,只过滤掉Python应用的日志,可以修改GKE的Fluentd配置,添加过滤规则忽略你的应用容器的stderr日志,或者配置Fluentd正确解析Python日志的级别。不过这个方法需要集群管理员权限,操作相对复杂,一般推荐优先用方法一。
额外注意点
- 如果你是在开发环境使用
debug=True,webapp2本身可能会输出一些调试日志到stderr,上面的方法一也会一并拦截,如果你需要保留这些调试日志,可以单独给webapp2的logger配置handler,而不是修改root logger。 - 生产环境建议关闭
debug=True,不仅能减少不必要的日志输出,也能提升应用安全性。
内容的提问来源于stack exchange,提问作者bplisted
相关产品推荐
相关产品推荐

