如何在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 的基础知识。

先决条件

请确保您完成了本教程的这些先决条件。

第 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 有很多有用的事情要做。 如果您正在寻找想法,您可能需要查看:

结论

从 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 反过来会在上传到后端系统之前缓冲日志

资源: