使用 Amazon Linux 2 在 Elastic Beanstalk 上输出 JSON 日志

Mic*_*ski 5 amazon-web-services elastic-beanstalk amazon-linux-2

我们正在尝试将我们的 Java 应用程序从当前的 Elastic Beanstalk JDK 8 平台迁移到在 Amazon Linux 2 上运行 Corretto 11 的新平台。该应用程序运行良好,但处理日志的方式发生了变化。Web 进程的输出现在存储在其中/var/log/web.stdout.log,每一行都以时间戳和进程名称为前缀,即:

May 20 17:00:00 ip-10-48-41-129 web: {"timestamp":"2020-05-20T17:00:00.035Z","message":"...","logger":"...","thread":"MessageBroker-2","level":"INFO"}
Run Code Online (Sandbox Code Playgroud)

我们怎样才能摆脱前缀?这些日志被流式传输到 CloudWatch,我们将它们以 JSON 格式输出到标准输出,以便我们稍后可以使用 Logs Insights 查询它们。但是使用前缀,Insights 不会“看到”JSON,只是将整行视为文本 blob。

我在 AWS 上找不到任何相关文档。几乎所有 Elastic Beanstalk 的文档都提到了 Amazon Linux 的第一个版本。

小智 7

我使用Platform Hooks来完成此任务。唯一的问题是/etc/rsyslog.d/web.conf应用程序和配置部署都被替换,因此您需要为两者提供挂钩。

这种方法可以避免弄乱 Elastic Beanstalk 的内部文件/opt/elasticbeanstalk/config/private(自之前的答案以来这些文件已更改 -rsyslog.conf不再存在)。此外,平台挂钩现在比 ebextensions 更受青睐。

如果您使用 CodeBuild,请不要忘记在输出工件中包含platformFiles目录(或放置文件的位置)。

注意:此代码假定进程的名称是web。如果您在 中定义了不同的进程名称Procfile,请改用它。但是,我认为rsyslog 配置应该始终位于,/etc/rsyslog.d/web.conf无论进程名称如何。

确保所有.sh文件都可以使用chmod +x.

.platform/hooks/predeploy/10_logs.sh

#!/bin/sh
sudo platformFiles/setupLogs.sh
Run Code Online (Sandbox Code Playgroud)

.platform/confighooks/predeploy/10_logs.sh

#!/bin/sh
sudo platformFiles/setupLogs.sh
Run Code Online (Sandbox Code Playgroud)

platformFiles/setupLogs.sh

#!/bin/sh
# By default logs output to /var/log/web.stdout.log are prefixed. We want just the raw logs from the app.
# This updates the rsyslog config. Also grants read permissions to the log files.

set -eu

mv platformFiles/rsyslogWebConf.conf /etc/rsyslog.d/web.conf

touch /var/log/web.stdout.log
touch /var/log/web.stderr.log
chmod +r /var/log/web.stdout.log
chmod +r /var/log/web.stderr.log

systemctl restart rsyslog.service
Run Code Online (Sandbox Code Playgroud)

platformFiles/rsyslogWebConf.conf

# This file is created from Elastic Beanstalk platform hooks.

template(name="WebTemplate" type="string" string="%msg%\n")

if $programname == 'web' then {
  *.=warning;*.=err;*.=crit;*.=alert;*.=emerg; /var/log/web.stderr.log;WebTemplate
  *.=info;*.=notice /var/log/web.stdout.log;WebTemplate
}
Run Code Online (Sandbox Code Playgroud)

推测

它看起来/opt/elasticbeanstalk/config/private/rsyslog.conf被替换为/opt/elasticbeanstalk/config/private/rsyslog.conf.template

# This rsyslog file redirects Elastic Beanstalk platform logs.
# Logs are initially sent to syslog, but we also want to divide
# stdout and stderr into separate log files.

{{range .ProcessNames}}if $programname  == '{{.}}' then {
  *.=warning;*.=err;*.=crit;*.=alert;*.=emerg /var/log/{{.}}.stderr.log
  *.=info;*.=notice /var/log/{{.}}.stdout.log
}
{{end}}
Run Code Online (Sandbox Code Playgroud)

基于此,我推测 Elastic Beanstalk 使用此模板生成一个/etc/rsyslog.d/web.conf文件,其中包含每个定义的进程名称的块。由于应用程序和配置部署都可以更改定义的流程,因此在两者之后重新创建此文件是有意义的。


Mic*_*ski 4

我找到了一个足够有效的解决方案,因此我将其发布在这里供后代使用。如果有人可以建议更好的,请这样做。

Amazon Linux 2 上的 Elastic Beanstalk 依赖于rsyslog日志处理和输出。在部署过程中,有一个文件/opt/elasticbeanstalk/config/private/rsyslog.conf被复制到该文件/etc/rsyslog.d/web.conf,该文件将应用程序的所有输出定向web/var/log/web.stdout.log.

该文件不包含任何自定义模板。它依赖于 的rsyslog默认模板,该模板在 any 前面%msg%加上时间戳和$programnameweb在本例中)。

我尝试通过.ebextensionsconfig替换此文件,但这不起作用,因为 Elastic Beanstalk 似乎在.ebextensions运行后覆盖此文件。因此,我添加了一个额外的平台挂钩来删除该文件,并保留我添加的自定义文件。

这是.ebextensions/logs.config文件:

files:
  "/etc/rsyslog.d/web-files.conf":
    mode: "000644"
    owner: root
    group: root
    content: |
      template(name="WebTemplate" type="string" string="%msg%\n")

      if $programname == 'web' then {
        *.=warning;*.=err;*.=crit;*.=alert;*.=emerg; /var/log/web.stderr.log;WebTemplate
        *.=info;*.=notice /var/log/web.stdout.log;WebTemplate
      }

commands:
  remove-.bak-rsyslog:
    command: rm -f *.bak
    cwd: /etc/rsyslog.d
Run Code Online (Sandbox Code Playgroud)

并且.platform/hooks/predeploy/remove-default-rsyslog-conf.sh(确保你chmod +x是这个):

#!/bin/sh
rm /etc/rsyslog.d/web.conf
systemctl restart rsyslog.service
Run Code Online (Sandbox Code Playgroud)