AWS Elastic Beanstalk:将自定义日志添加到 CloudWatch?

AWS Elastic Beanstalk: Add custom logs to CloudWatch?

如何将自定义日志添加到 CloudWatch?默认日志已发送,但如何添加自定义日志?

我已经添加了这样的文件:(在 .ebextensions 中)

files:
  "/opt/elasticbeanstalk/tasks/bundlelogs.d/applogs.conf" :
    mode: "000755"
    owner: root
    group: root
    content: |
      /var/app/current/logs/*

  "/opt/elasticbeanstalk/tasks/taillogs.d/cloud-init.conf" :
    mode: "000755"
    owner: root
    group: root
    content: |
      /var/app/current/logs/*

正如我所做的那样 bundlelogs.d 和 taillogs.d 现在可以从控制台或 Web 跟踪或检索这些自定义日志,这很好,但它们不会持久存在并且不会在 CloudWatch 上发送。

在 CloudWatch 中,我有像
这样的默认日志 /aws/elasticbeanstalk/InstanceName/var/log/eb-activity.log
我想再有一个这样的
/aws/elasticbeanstalk/InstanceName/var/app/current/logs/mycustomlog.log

awslogs 代理在配置文件中查找它应该发送的日志文件。其中有一些默认值。您需要对其进行编辑并指定文件。

您可以检查和编辑位于以下位置的配置文件:

/etc/awslogs/awslogs.conf

确保重启服务:

sudo service awslogs restart

您可以在那里指定自己的文件并创建不同的组等等。

请参考以下link,您将能够立即获得您的日志。

资源:

https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AgentReference.html

编辑:

由于您不想编辑实例上的文件,您可以将相关代码添加到代码根目录下的.ebextensions 文件夹中。例如,这是我的 01_cloudwatch.config :

packages:
  yum:
    awslogs: []

container_commands:
  01_get_awscli_conf_file:
    command: "aws s3 cp s3://project/awscli.conf /etc/awslogs/awscli.conf"
  02_get_awslogs_conf_file:
    command: "aws s3 cp s3://project/awslogs.conf.${NODE_ENV} /etc/awslogs/awslogs.conf"
  03_restart_awslogs:
    command: "sudo service awslogs restart"
  04_start_awslogs_at_system_boot:
    command: "sudo chkconfig awslogs on"

在此配置中,我根据 NODE_ENV 从 S3 存储桶中获取适当的配置文件。你可以在你的配置中做任何你想做的事情。

bundlelogs.dtaillogs.d 都是从管理控制台检索的日志。您要做的是将默认日志(例如 eb-activity.log)扩展到 CloudWatch Logs。为了扩展日志流,需要在/etc/awslogs/config/下再增加一个配置。配置应该遵循Agent Configuration file Format

我已经成功地为我的自定义 ubuntu/nginx/php 平台扩展了我的日志。这是我的 extension file FYI. Here is an official sample 仅供参考。

在你的情况下,它可能像

files:
  "/etc/awslogs/config/my_app_log.conf" :
    mode: "000600"
    owner: root
    group: root
    content: |
      [/var/app/current/logs/xxx.log]
      log_group_name = `{"Fn::Join":["/", ["/aws/elasticbeanstalk", { "Ref":"AWSEBEnvironmentName" }, "var/app/current/logs/xxx.log"]]}`
      log_stream_name = {instance_id}
      file = /var/app/current/logs/xxx.log*

归功于 and

这是我为我们的特定用例 .ebextensions 提出的最终 config 文件。解释某些方面的注释在代码块下方。

files:
  "/etc/awslogs/config/beanstalklogs_custom.conf" :
    mode: "000600"
    owner: root
    group: root
    content: |
      [/var/log/tomcat8/catalina.out]
      log_group_name = `{"Fn::Join":["/", ["/aws/elasticbeanstalk", { "Fn::Select" : [ "1", { "Fn::Split" : [ "-", { "Ref":"AWSEBEnvironmentName" } ] } ] }, "var/log/tomcat8/catalina.out"]]}`
      log_stream_name = `{"Fn::Join":["--", [{ "Ref":"AWSEBEnvironmentName" }, "{instance_id}"]]}`
      file = /var/log/tomcat8/catalina.out*

services:
  sysvinit:
    awslogs:
      files:
        - "/etc/awslogs/config/beanstalklogs_custom.conf"

commands:
  rm_beanstalklogs_custom_bak:
    command: "rm beanstalklogs_custom.conf.bak"
    cwd: "/etc/awslogs/config"
    ignoreErrors: true

log_group_name

我们的 EB 环境有一个标准的命名方案,正好是 environmentName-environmentType。我正在使用 { "Fn::Split" : [ "-", { "Ref":"AWSEBEnvironmentName" } ] } 将其拆分为两个字符串(名称和类型)的数组。

然后我使用 { "Fn::Select" : [ "1", <<SPLIT_OUTPUT>> ] } 来获取类型字符串。您的需求显然会有所不同,因此您可能只需要以下内容:

      log_group_name = `{"Fn::Join":["/", ["/aws/elasticbeanstalk", { "Ref":"AWSEBEnvironmentName" }, "var/log/tomcat8/catalina.out"]]}`

log_stream_name

我正在使用 Fn::Join 函数将 EB 环境名称与实例 ID 结合起来。请注意,实例 ID 模板是一个字符串,它会完全按照给定的方式回显。

服务

部署自定义 conf 文件后,awslogs 服务会自动重新启动。

命令

files 块覆盖现有文件时,它会创建一个备份文件,如 beanstalklogs_custom.conf.bak。此块会删除该备份文件,因为 awslogs 服务读取 两个 文件,可能会导致冲突。

结果

如果您登录到 EC2 实例并 sudo cat 文件,您应该会看到类似这样的内容。请注意,所有 Fn 功能都已解决。如果您发现 Fn 函数没有解析,请检查它是否存在语法错误。

[/var/log/tomcat8/catalina.out]
log_group_name = /aws/elasticbeanstalk/environmentType/var/log/tomcat8/catalina.out
log_stream_name = environmentName-environmentType--{instance_id}
file = /var/log/tomcat8/catalina.out*

查看 AWS 文档并不能立即看出这一点,但您需要做一些事情。

(我们的环境是 Amazon Linux AMI - Rails Ruby 2.6 Puma 平台上的应用程序。

首先,在 IAM 中创建一个策略,使您的 EB 生成的 EC2 实例能够访问 CloudWatch 日志组并流式传输到它们 - 我们将我们的命名为“EB-Cloudwatch-LogStream-Access”。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:DescribeLogStreams",
                "logs:CreateLogGroup",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:log-group:/aws/elasticbeanstalk/*:log-stream:*"
        }
    ]
}

创建此文件后,确保将策略附加(在 IAM > 角色中)到您的 IAM 实例配置文件服务角色 与您的 EB 环境相关联(检查环境的配置页面:Configuration > Security > IAM instance profile | Service Role)。

然后,在您的 .ebextensions 目录中提供一个 .config 文件,例如 setup_stream_to_cloudwatch.config0x_setup_stream_to_cloudwatch.config。在我们的项目中,我们通过为 0x 设置高数字(例如 09_setup_stream_to_cloudwatch.config),使其成为部署期间 运行 的最后一个扩展 .config 文件。

然后,提供以下内容,将 your_log_file 替换为适当的文件名,请记住一些日志文件位于 Amazon Linux AMI 上的 /var/log 中,而一些(例如由您的应用程序生成的)可能存在于 /var/app/current/log:

等路径中
files:
  '/etc/awslogs/config/logs.conf':
    mode: '000600'
    owner: root
    group: root
    content: |
      [/var/app/current/log/your_log_file.log]
      log_group_name = `{"Fn::Join":["/", ["/aws/elasticbeanstalk", { "Ref":"AWSEBEnvironmentName" }, "var/app/current/log/your_log_file.log"]]}`
      log_stream_name = {instance_id}
      file = /var/app/current/log/your_log_file.log*
commands:
  "01":
    command: chkconfig awslogs on
  "02":
    command: service awslogs restart # note that this works for Amazon Linux AMI only - other Linux instances likely use `systemd`

部署您的应用程序,您应该设置好了!

这里已经有一些很好的答案。

我在新的 Medium blog 中详细介绍了这一切的工作原理以及示例 .ebextensions 文件以及放置位置。

以下是您可能会用到的摘录,文章解释了如何确定 folder/file(s) 的直播权。

请注意,如果 /var/app/current/logs/* 包含许多不同的文件,这可能不起作用,例如如果你有

database.log app.log random.log

那么你应该考虑为每个添加一个流,但是如果你有

app.2021-10-18.log 应用程序.2021-10-17.log app.2021-10-16.log

然后就可以使用/var/app/current/logs/app.*

packages:
  yum:
    awslogs: []

option_settings:
  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: StreamLogs
    value: true
  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: DeleteOnTerminate
    value: false
  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: RetentionInDays
    value: 90

files:
  "/etc/awslogs/awscli.conf" :
    mode: "000600"
    owner: root
    group: root
    content: |
      [plugins]
      cwlogs = cwlogs
      [default]
      region = `{"Ref":"AWS::Region"}`

  "/etc/awslogs/config/logs.conf" :
    mode: "000600"
    owner: root
    group: root
    content: |
      [/var/app/current/logs]
      log_group_name = `{"Fn::Join":["/", ["/aws/elasticbeanstalk", { "Ref":"AWSEBEnvironmentName" }, "/var/app/current/logs"]]}`
      log_stream_name = {instance_id}
      file = /var/app/current/logs/*

commands:
  "01":
    command: systemctl enable awslogsd.service
  "02":
    command: systemctl restart awslogsd