如何在Ubuntu14.04上使用Fluentd和ElasticSearch集中您的Docker日志
Fluentd 的一篇文章
介绍
什么是流利的?
Fluentd 是一个开源数据收集器,旨在统一日志记录基础设施。 它旨在通过简化和可扩展的方式收集和存储日志,将运维工程师、应用程序工程师和数据工程师聚集在一起。
流利之前
流利后
主要特点
Fluentd 有四个关键特性,使其适合构建干净、可靠的日志管道:
- 使用 JSON 进行统一日志记录: Fluentd 尝试尽可能地将数据结构化为 JSON。 这允许 Fluentd 统一处理日志数据的所有方面:收集、过滤、缓冲和输出跨多个源和目标的日志。 使用 JSON 进行下游数据处理要容易得多,因为它有足够的结构可以访问,而无需强制使用严格的模式
- Pluggable Architecture: Fluentd 有一个灵活的插件系统,允许社区扩展其功能。 300 多个社区贡献的插件将数十个数据源连接到数十个数据输出,根据需要操纵数据。 通过使用插件,您可以立即更好地利用日志
- 所需资源最少: 数据收集器应该是轻量级的,以便用户可以在繁忙的机器上舒适地运行它。 Fluentd 是结合 C 和 Ruby 编写的,并且需要最少的系统资源。 vanilla 实例在 30-40MB 内存上运行,可以处理 13,000 个事件/秒/核心
- 内置可靠性: 永远不会发生数据丢失。 Fluentd 支持基于内存和文件的缓冲,以防止节点间数据丢失。 Fluentd 还支持强大的故障转移,并且可以设置为高可用性
目标:使用 Fluentd 收集集中的 Docker 容器日志
随着 Docker 容器在生产中的推出,越来越需要将容器的日志保存在比容器更短暂的地方。
在本教程中,我们将向您展示如何安装 Fluentd 并使用它从 Docker 容器中收集日志,并将它们存储在外部,以便在容器停止后可以保存数据。 我们会将数据流式传输到另一个运行 Elasticsearch 的容器,该容器位于同一 Ubuntu 14.04 服务器上。
正如 Kubernetes 的 GitHub 存储库 中所述,该架构使用 Fluentd 的能力来跟踪和解析 Docker 守护程序为每个容器生成的 JSON-per-line 日志文件。 有关最小设置,请参阅 this recipe。
在本教程的最后,我们将讨论另外两个用例。 阅读本文后,您应该了解如何使用 Fluentd 的基础知识。
先决条件
请确保您完成了本教程的这些先决条件。
- Ubuntu 14.04 液滴
- 具有 sudo 访问权限 的用户
第 1 步 — 安装 Fluentd
部署 Fluentd 最常见的方式是通过 td-agent
包。 Fluentd 的原作者 Treasure Data 将 Fluentd 与自己的 Ruby 运行时打包在一起,这样用户就不需要设置自己的 Ruby 来运行 Fluentd。
目前,td-agent
支持以下平台:
- Ubuntu:清晰、精确和可靠
- Debian:喘息和挤压
- RHEL/Centos:5、6 和 7
- Mac OSX:10.9 及以上
在本教程中,我们假设您使用的是运行 Ubuntu 14.04 LTS (Trusty) 的 DigitalOcean Droplet。
使用以下命令安装 td-agent
:
curl -L http://toolbelt.treasuredata.com/sh/install-ubuntu-trusty-td-agent2.sh | sh
开始td-agent
:
sudo /etc/init.d/td-agent start
检查日志以确保它已成功安装:
tail /var/log/td-agent/td-agent.log
您应该会看到类似于以下内容的输出:
port 24230 </source> </ROOT> 2015-02-22 18:27:45 -0500 [info]: adding source type="forward" 2015-02-22 18:27:45 -0500 [info]: adding source type="http" 2015-02-22 18:27:45 -0500 [info]: adding source type="debug_agent" 2015-02-22 18:27:45 -0500 [info]: adding match pattern="td.*.*" type="tdlog" 2015-02-22 18:27:45 -0500 [info]: adding match pattern="debug.**" type="stdout" 2015-02-22 18:27:45 -0500 [info]: listening fluent socket on 0.0.0.0:24224 2015-02-22 18:27:45 -0500 [info]: listening dRuby uri="druby://127.0.0.1:24230" object="Engine"
注意: 或者,Fluentd 可以作为 Ruby gem 使用,并且可以与
gem install fluentd
一起安装。 如果您没有 sudo 权限,请安装 Ruby(例如,参见 Installing Ruby 此处)并运行:gem install fluentd --no-rdoc --no-ri
第 2 步 — 安装 Docker
现在我们将安装 Docker。 本教程使用 Docker v1.5.0 进行了测试。
添加 Docker 存储库的密钥,以便我们可以获得最新的 Docker 包:
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
将存储库添加到您的源:
sudo sh -c "echo deb https://get.docker.com/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
更新您的系统:
sudo apt-get update
安装 Docker:
sudo apt-get install lxc-docker
通过检查版本来验证是否安装了 Docker:
docker --version
您应该看到如下输出:
Docker version 1.5.0, build a8a31ef
第 3 步 — 将用户添加到 docker 组
Docker 以 root 身份运行,因此为了发出 docker
命令,请将您的 sudo 用户添加到 docker 组。 将 sammy
替换为您选择的用户。
sudo gpasswd -a sammy docker
然后,重新启动 Docker。
sudo service docker restart
最后,如果您当前以 sudo 用户身份登录,则必须注销并重新登录。
第 4 步 - 构建 Fluentd 图像
在本节中,我们将为 Fluentd Docker 容器创建 Docker 映像。 如果您想全面了解 Docker,请阅读 这个入门教程 。
为您的 Fluentd Docker 资源创建一个新目录,然后进入其中:
mkdir ~/fluentd-docker && cd ~/fluentd-docker
创建以下 Dockerfile
:
sudo nano Dockerfile
将以下内容准确地添加到您的文件中。 此文件告诉 Docker 更新 Docker 容器并安装 Ruby、Fluentd 和 Elasticsearch:
FROM ruby:2.2.0 MAINTAINER kiyoto@treausuredata.com RUN apt-get update RUN gem install fluentd -v "~>0.12.3" RUN mkdir /etc/fluent RUN apt-get install -y libcurl4-gnutls-dev make RUN /usr/local/bin/gem install fluent-plugin-elasticsearch ADD fluent.conf /etc/fluent/ ENTRYPOINT ["/usr/local/bundle/bin/fluentd", "-c", "/etc/fluent/fluent.conf"]
您还需要在同一目录中创建一个 fluent.conf
文件。
sudo nano fluent.conf
fluent.conf
文件应如下所示。 您可以完全复制此文件:
<source> type tail read_from_head true path /var/lib/docker/containers/*/*-json.log pos_file /var/log/fluentd-docker.pos time_format %Y-%m-%dT%H:%M:%S tag docker.* format json </source> # Using filter to add container IDs to each event <filter docker.var.lib.docker.containers.*.*.log> type record_transformer <record> container_id ${tag_parts[5]} </record> </filter> <match docker.var.lib.docker.containers.*.*.log> type elasticsearch logstash_format true host "#{ENV['ES_PORT_9200_TCP_ADDR']}" # dynamically configured to use Docker's link feature port 9200 flush_interval 5s </match>
该文件的目的是告诉 Fluentd 在哪里可以找到其他 Docker 容器的日志。
然后,构建您的 Docker 映像,名为 fluentd-es
:
docker build -t fluentd-es .
这将需要几分钟才能完成。 检查您是否已成功构建映像:
docker images
你应该看到这样的输出:
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE fluentd-es latest 89ba1fb47b23 2 minutes ago 814.1 MB ruby 2.2.0 51473a2975de 6 weeks ago 774.9 MB
第 5 步 — 启动 Elasticsearch 容器
现在回到 Elasticsearch 容器的主目录或首选目录:
cd ~
下载并启动 Elasticsearch 容器。 为此已经有一个自动构建:
docker run -d -p 9200:9200 -p 9300:9300 --name es dockerfile/elasticsearch
等待容器镜像下载并启动。
接下来,通过检查 Docker 进程确保 Elasticsearch 容器正常运行:
docker ps
你应该看到这样的输出:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c474fd99ce43 dockerfile/elasticsearch:latest "/elasticsearch/bin/ 4 minutes ago Up 4 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp es
第 6 步 — 启动 Fluentd-to-Elasticsearch 容器
现在我们将启动运行 Fluentd 的容器,收集日志并将它们发送到 Elastcisearch。
docker run -d --link es:es -v /var/lib/docker/containers:/var/lib/docker/containers fluentd-es
在上述命令中,--link es:es
部分将 Elasticsearch 容器链接到 Fluentd 容器。 -v /var/lib/docker/containers:/var/lib/docker/containers
部分用于将宿主容器的日志目录挂载到 Fluentd 容器中,以便 Fluentd 可以在创建容器时跟踪日志文件。
最后,通过检查我们的活动 Docker 进程来检查容器是否正在运行:
docker ps
这一次,您应该同时看到 Elasticsearch 容器和新的 fluentd-es
容器:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f0d2cac81ac8 fluentd-es:latest "/usr/local/bundle/b 2 seconds ago Up 2 seconds stupefied_brattain c474fd99ce43 dockerfile/elasticsearch:latest "/elasticsearch/bin/ 6 minutes ago Up 6 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp es
第 7 步 - 确认 Elasticsearch 正在接收事件
最后,让我们确认 Elasticsearch 正在接收事件:
curl -XGET 'http://localhost:9200/_all/_search?q=*'
输出应包含如下所示的事件:
{"took":66,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":0,"max_score":null,"hits":[]}} {"took":59,"timed_out":false,"_shards":{"tod","_id":"AUwLaKjcnpi39wqZnTXQ","_score":1.0,"_source":{"log":"2015-03-12 00:35:44 +0000 [info]: following tail of /var/lib/docker/containers/6abeb6ec0019b2198ed708315f4770fc7ec6cc44a10705ea59f05fae23b81ee9/6abeb6ec0019b2198ed708315f4770fc7ec6cc44a10705ea59f05fae23b81ee9-json.log\n","stream":"stdout","container_id":"6abeb6ec0019b2198ed708315f4770fc7ec6cc44a10705ea59f05fae23b81ee9","@timestamp":"2015-03-12T00:35:44+00:00"}}]}}
根据您的设置,您可能会记录很多事件。 单个事件应以 {"took":
开头并以时间戳结束。
如该输出所示,Elasticsearch 正在接收数据。 (您的容器 ID 将与上面显示的不同!)
第 8 步 — 将事件日志提升到新的水平
现在您的容器事件已被 Elasticsearch 保存,接下来您应该做什么? Elasticsearch 有很多有用的事情要做。 如果您正在寻找想法,您可能需要查看:
- 基本的 Elasticsearch 操作
- 添加仪表板,以便您可以可视化您的日志
结论
从 Docker 容器收集日志只是使用 Fluentd 的一种方式。 在本节中,我们将介绍 Fluentd 的另外两个常见用例。
用例 1:实时日志搜索和日志归档
许多用户来到 Fluentd 是为了构建一个日志管道,该管道既可以进行实时日志搜索,也可以进行长期存储。 架构如下所示:
这种架构利用了 Fluentd 复制数据流并将其输出到多个存储系统的能力。 在上述设置中,Elasticsearch 用于实时搜索,而 MongoDB 和/或 Hadoop 用于批量分析和长期存储。
用例 2:集中式应用程序日志记录
Web 应用程序会产生大量日志,并且它们通常被任意格式化并存储在本地文件系统中。 这很糟糕,原因有两个:
- 日志很难以编程方式解析(需要大量正则表达式),因此对于那些希望通过统计分析(A/B 测试、欺诈检测等)了解用户行为的人来说不是很容易访问。
- 日志无法实时访问,因为文本日志被批量加载到存储系统中。 此外,如果服务器的磁盘在批量加载之间损坏,日志会丢失或损坏
Fluentd 通过以下方式解决了这些问题:
- 为各种编程语言提供具有一致 API 的记录器库:每个记录器向 Fluentd 发送三个(时间戳、标签、JSON 格式的事件)。 目前,有用于 Ruby、Node.js、Go、Python、Perl、PHP、Java 和 C++ 的记录器库
- 允许应用程序“触发并忘记”:记录器可以异步记录到 Fluentd,Fluentd 反过来会在上传到后端系统之前缓冲日志
资源:
- 了解 统一日志记录层
- Fluentd + Elasticsearch for Kubernetes by Satnam Singh(Kubernetes 提交者)