基于 ECS 的容器日志解决方案

阅读数:36 2019 年 10 月 30 日 08:00

基于ECS的容器日志解决方案

摘要

ECS 是 AWS 发布的容器集群管理和调度服务。通过 ECS 容器集群管理服务,用户可以很方便地管理成百上千个容器组成的业务系统,而无需运维容器集群管理、调度及状态存储等相关管理组件。相比于虚拟机,容器技术拥有诸多优势,使得近年来越来越多的用户选择拥抱容器技术。

容器技术的优势:

· 更有效的资源利用

· 更快的启动和销毁速度

· 捆绑应用代码和运行依赖

· 版本化管理容器镜像

· 非常适合微服务的场景

尽管容器技术优势很多,但却无法解决应用程序的故障,传统虚机场景下的监控、日志搜集等应用在容器场景下同样需要。本文主要针对于运行在 AWS ECS 容器集群管理服务上的容器应用,来为大家详解相关的日志解决方案,具体包括:日志搜集、搜索和分析等,并为大家解答在使用 AWS 相关日志搜集服务时候的一些常见问题,例如:

· 如何更方便地搜集容器日志

· 如何将多行显示的日志汇聚成一条搜集

· 如何从互联网访问 VPC 内部的 Elasticsearch 和 Kibana 服务

· 如何为 Kibana 应用添加用户登入认证功能

· 如何设置 index 的默认 primary shard 以更好地适配日志量

· 如何定期删除 Elasticsearch 中的老旧日志

下图是本文使用的整体架构图:

基于ECS的容器日志解决方案

流程介绍

我们先简单介绍一下这个架构中各个组件的功能以及日志从生成到处理的流程:

· ECS 是 AWS 的容器管理及调度平台,用于管理我们的应用容器

· 应用容器通过 awslogs driver 将日志输出到 CloudWatch logs 中

· 输出到 CloudWatch logs 中的日志可以实时地导入到 AWS Elasticsearch 集群中

· 用户可以通过 CloudWatch logs 界面可以对日志进行关键字匹配方式的简单搜索

· 用户也可以通过 nginx 代理调用 Elasticsearch API 或者登入 Kibana 对日志进行更为丰富地搜索和分析

· Nginx 代理服务器为 internet 上的用户提供代理及登入认证功能,Route 53 服务为 internet 访问提供 DNS 解析服务,同时对 nginx server 进行健康检查并在必要的时候进行故障切换

· CloudWatch logs 中的日志也可以定期批量导入到 S3 中通过 Athena,Redshift,EMR 等大数据分析工具分析,并通过 QuickSight 做展示 (这部分内容不作为本文介绍的重点)

· 用户可以通过 Cloud 9 IDE 开发 lambda 程序,该 lambda 由 CloudWatch Events 每天触发用于根据自定义策略清理 Elasticsearch 中的老旧日志,全量日志保存在 CloudWatch logs 及 S3 中

ECS 支持多种 docker logs driver 将容器中的日志输出,比如:awslogs、fluentd、json-file 等。其中,awslogs 相比于其他 driver 有如下优势:

· 天然集成 CloudWatch logs 对日志进行搜索、查看,并能根据需要产生 metrics,进而基于日志产生事件告警

· 默认启用,无需通过 user data 修改 ECS 实例的配置

· 默认安装,无需通过 user data 或者自定义 AMI 安装

· 输出到 CloudWatch logs 中的日志以 task id 而非 container id 进行分类,便于追溯

· 配置简单

通过 awslogs driver,我们可以很方便地将 ECS 运行的容器内日志集中传输到 CloudWatch logs 中进行收集查看,具体的配置非常简单,在创建 task definition 的时候,为 container 选择 awslogs driver,并且设置输出的 awslogs-group,awslogs-region 和 awslogs-stream-prefix 即可,之后就可以在 CloudWatch logs 中对应的 log group 下看到以 task id 标识的 log stream。

基于ECS的容器日志解决方案

需要注意的是,有些应用得一条日志内容可能会被分成多行输出,最典型的场景就是 tomcat 的错误日志,如下图所示,默认该条日志在 CloudWatch logs 中也会分成多个日志条目,这将不便于我们进行日志搜索和故障分析。

基于ECS的容器日志解决方案

基于ECS的容器日志解决方案

所以,对于这种类型的应用,我们需要做额外的设置:设置 awslogs-datetime-format 来匹配多行日志中的开头日期,这样以该格式日期开始的多行日志就会被记录成 CloudWatch logs 中的一条日志而非多条。

基于ECS的容器日志解决方案

我们可以看到日志在 CloudWatch logs 中已经以时间为标志,显示为一行了:

基于ECS的容器日志解决方案

CloudWatch logs 的界面提供了一个过滤栏,我们可以通过简单的关键字匹配的方式过滤出符合条件的日志,美中不足的是目前 CloudWatch logs 主要支持关键字匹配的过滤条件,还不支持诸如通配符等高级的过滤方式,有该需求或者希望能够对日志进行分析统计展示的用户可以很方便地将 CloudWatch logs 中的日志实时地导入 Elasticsearch 中并结合 Kibana 进行更为细致地搜索和分析,同时,CloudWatch logs 界面也支持将日志导出到 S3 中,结合 EMR,Athena,Redshift 等大数据分析服务进行分析,这一部分内容不作为本文的重点,有兴趣的读者可以通过 AWS 官网了解相关的大数据处理服务,下面我们主要介绍如何将 CloudWatch logs 中的日志导入到 Elasticsearch 中。

将 CloudWatch logs 中的日志导入 Elasticsearch

首先我们来创建 Elasticsearch 集群

点击创建一个新的 domain,我们可以注意到目前 AWS 托管的 Elasticsearch 集群支持两种 Endpoint:VPC 和 Internet。我们将会在下文具体的配置页面中做相应的介绍。

基于ECS的容器日志解决方案

为集群起一个名字并选择相应的版本:

基于ECS的容器日志解决方案

在之后的配置集群页面中,我们需要设置集群节点的机型、数量以及是否需要专门的 master 节点。大家可以参考 AWS Elasticsearch 的官方文档来查看这些选项的最佳实践。通常对于 master 节点我们推荐采用计算优化型实例,而对于计算节点我们推荐采用 IO 优化型实例。同时,我们也建议开启 zone awareness 功能(要求计算节点为偶数),这将使节点分布在两个可用区中,实现可用区级别的冗余。

基于ECS的容器日志解决方案

另外可以根据需要启用数据加密并且设定自动做快照的时间:

基于ECS的容器日志解决方案

之后我们需要选择使用 VPC 还是 Internet 的接入方式,如果选择 Internet 接入方式,那么 ES 的节点会被分配至公网 IP,在策略允许的情况下可以通过公网访问 ES 及 Kibana;如果选择 VPC 接入方式,那么 ES 的节点会被分配私有 IP,在策略允许的情况下可以有如下几种访问方式:

  1. 复制代码
    如果将 ES 作为搜索引擎使用,那么 VPC 内部的应用服务器可以通过私网直接对 ES 进行 API 的调用访问
  2. 复制代码
    如果本地站点和 AWS 的 VPC 建有 VPN 或者 DX 连接,那么本地设备可以通过 VPN 或者 DX 使用私网 IP 访问 ES 及 Kibana
  3. 复制代码
    如果需要通过公网访问 ES 及 Kibana,可以通过在 EC2 上部署反向代理实现

本次案例我们使用的是 VPC 的接入方式,并且通过部署反向代理实现公网访问 ES 及 Kibana。这样做有一个额外的好处:由于 Kibana 本身并没有集成账号登入的功能,默认我们可以通过安全组对 IP 进行控制,通过反向代理我们可以额外地增加用户名密码的登入认证功能,增加一层安全防护。

基于ECS的容器日志解决方案

由于我们使用 VPC 的接入方式,访问策略可以选择通过安全组做相关的控制。

基于ECS的容器日志解决方案

创建完集群后,我们可以在控制台中看到 ES 和 Kibana 的 endpoint 信息。

基于ECS的容器日志解决方案

配置 nginx 代理服务器

下面我们来配置 nginx 代理服务器,这边略去创建 EC2 的过程,需要注意将该 EC2 放到公有子网中并且建议分配弹性 IP。

首先通过 yum 工具安装 nginx,然后创建如下配置文件,注意将 ELASTIC-IP 修改成 EC2 的 EIP,并且修改 ES 的 endpoint 以及 server_name:

Html

复制代码
/etc/nginx/conf.d/elasticsearch.conf

基于ECS的容器日志解决方案

Html

复制代码
/etc/nginx/conf.d/kibana.conf

基于ECS的容器日志解决方案

接下来为 HTTP 基本认证生成用户账号,首先利用 yum 工具安装 httpd,然后生成账号并启动 nginx:

基于ECS的容器日志解决方案

为了更简便地给大家进行介绍,本文中为 Kibana 的访问只启用了 HTTP 的基本认证,可以用相同的方法为 ES 的 API 访问启用基本认证。

为了能够从公网访问到 ES 和 Kibana,我们需要为 nginx 配置文件中的 server_name 设置 DNS 解析,可以使用 route 53 来将 server_name 解析到 EC2 的 EIP,用户也可以通过跨 AZ 部署多台 EC2 nginx 代理结合 route 53 的 health check 功能,就能够很方便地实现代理服务器的高可用设计。

基于ECS的容器日志解决方案

接下来我们可以在浏览器中输入 kibana.ivanyu.tech 来测试下基本认证:

基于ECS的容器日志解决方案

我们需要输入用户名密码后,才能访问到 Kibana 的页面:

基于ECS的容器日志解决方案

并且我们能够通过 ES 的 API 来访问 ES 集群:

基于ECS的容器日志解决方案

以上我们就完成了 ES 集群的创建,以及通过 nginx 代理实现公网访问 ES 及 Kibana,并且为 Kibana 的访问增添了基本的用户认证功能。

在将日志传入 ES 之前,我们需要调整其设置,对于 AWS 托管的 ES 集群,默认每个 index 会有 5 个 shard,而每个 shard 会有 1 个 replica,CloudWatch logs 中的日志会以天为单位在 ES 中创建名字如 cwl-2018.01.23 的 index。官方推荐将一个 shard 的数据量控制在 50GB 以下,对于 PB 级别的 index 建议一个 shard 的数据量至少为 100GB 以上,由于一个 index 的 primary shard 数量在 index 创建后不能简单地在线修改,我们需要通过创建 template 模板,为 CloudWatch logs 日志生成的 index 设置默认的 primary shard 和 replica,我们通过如下 API 为 CloudWatch logs 日志对应的 index 设置 10 个 primary shard 和 1 个 replica。基于ECS的容器日志解决方案

将 CloudWatch logs 中的日志 streaming 到 ES 集群

下面我们介绍如何将 CloudWatch logs 中的日志 streaming 到 ES 集群中,首先在 CloudWatch logs 界面选择应用日志打入的 log group,选择 Stream to Amazon Elasticsearch Service。

基于ECS的容器日志解决方案

选择之前创建的 ES 集群,由于我们会通过 lambda 实现日志从 CloudWatch logs 到 ES 集群的导入,需要为 lambda 函数分配 IAM role,可以选择创建一个新的 role 或者选择一个已有的 role,该 role 需要满足如下条件和策略:

基于ECS的容器日志解决方案

基于ECS的容器日志解决方案

点击下一步,由于 tomcat 生成的日志以空格分隔,所以我们选择 Space Delimited 的日志格式,设置 Filter Pattern 为日志设置 schema,点击 Test Pattern 查看匹配效果。

基于ECS的容器日志解决方案

我们可以看到日志被正确地匹配并生成了相应的 schema,方便之后在 Kibana 中基于字段做搜索。

基于ECS的容器日志解决方案

点击下一步后可以开始 Streaming,我们可以登入 Kibana 界面,创建相应的 index 来进行日志的搜索,Kibana 能够支持比 CloudWatch logs 界面更丰富的搜索功能,比如支持通配符方式的搜索。

基于ECS的容器日志解决方案

基于ECS的容器日志解决方案

通过 ES API 我们也能够对 index 的信息做查看:

基于ECS的容器日志解决方案

在通过日志搜索来排查问题的应用场景中,我们经常只会对近几天的日志感兴趣,在不宕机的情况下 AWS ES 可以很方便地添加新的节点,最多能够支持到 1.5PB,100 个节点的规模,但是考虑到成本及具体场景,我们可以通过 curator cli 或者 API 实现 ES 中老旧的日志 index 的定期清理。在使用 curator cli 的情况下,我们需要通过一台 EC2 运行 cron 定时任务,这里我们选择使用 curator python API,通过 CloudWatch event 结合 lambda 构建无服务器的定时任务。

本文中,我们通过 AWS Cloud9 云端 IDE 来编写代码,Cloud9 能方便地创建并部署 lambda,我们首先创建一个 Cloud9 环境,Cloud9 环境的创建非常简单,只需要选取机型及 VPC、subnet 即可

基于ECS的容器日志解决方案

创建完环境后,会自动跳转到代码编写界面,点击创建 lambda:

基于ECS的容器日志解决方案

配置 lambda 函数名字:

基于ECS的容器日志解决方案

选择 python2.7 并任意选择一个模板:

基于ECS的容器日志解决方案

我们暂时不设置触发器,先简单地为 lambda 分配 admin 权限:

基于ECS的容器日志解决方案

基于ECS的容器日志解决方案

修改 lambda 代码如下,并在 CLI 界面使用 pip 工具安装 elasticsearch-curator package,本例用于匹配并删除以“cwl-”开头创建于 1 天之前的 index,可以根据需要修改相应参数。

基于ECS的容器日志解决方案

通过 Cloud9 我们可以简单测试一下代码的功能:

基于ECS的容器日志解决方案

调试完成后,我们可以通过 Cloud9 一键部署 lambda:

基于ECS的容器日志解决方案

接下来我们利用 CloudWatch event 配置定时任务,定时运行 lambda 函数对 ES 中的日志进行清理。在这里,我们进入 CloudWatch event 界面,创建一个规则:

基于ECS的容器日志解决方案

设置每天运行一次 lambda 函数:

基于ECS的容器日志解决方案

通过 CloudWatch 查看 lambda 触发事件及相关日志:

基于ECS的容器日志解决方案

基于ECS的容器日志解决方案

以上即为针对 AWS ECS 容器集群管理服务的容器日志的解决方案,并包括日志产生后,整个生命周期中的搜集、汇聚、展示、搜索、清理、分析等实现。希望这些内容可以帮助大家更好的使用 ECS 集群管理服务,更好的应用容器技术。

参考资料:

调整 AWS ES 默认的 shard 配置: http://www.havingatinker.uk/aws-elasticsearch-service-woes.html

Cloudwatch logging driver 参数: https://docs.docker.com/engine/admin/logging/awslogs/

设置 Kibana 代理服务器及基本认证: http://blog.ruanbekker.com/blog/2017/09/16/nginx-reverse-proxy-for-elasticsearch-and-kibana-5-on-aws/

Curator Python API: https://curator.readthedocs.io/en/latest/

本文转载自 AWS 技术博客。

原文链接:
https://amazonaws-china.com/cn/blogs/china/container-logging-solution-based-on-ecs/

欲了解 AWS 的更多信息,请访问【AWS 技术专区】

评论

发布