弹性Beanstalk环境的Cloudwatch日志组中没有日志记录。

8

我有一个弹性Beanstalk环境,它运行着一个具有Node.js API的Docker容器。在AWS控制台中,如果我选择我的环境,然后转到配置/软件,我会看到以下内容:

  • 日志组:/aws/elasticbeanstalk/my-environment
  • 日志流: 启用
  • 保留期限: 3天
  • 生命周期: 在终止之后保留

然而,如果我在Cloudwatch控制台上点击该日志组,我会看到几周前的最后事件时间(我认为这对应于环境创建时的时间),并且日志中没有任何内容。

由于这是一个docker化的应用程序,服务器自身的日志应该位于/aws/elasticbeanstalk/my-environment/var/log/eb-docker/containers/eb-current-app/stdouterr.log。 如果我改为通过再次进入我的EB环境,点击“日志”,然后“请求最后100行”来直接从实例获取日志,则记录正在正确地进行。只是在使用CloudWatch时我什么也看不到。

欢迎提供任何帮助。


你是否一直在重新部署你的应用,即启动一个新的容器?如果是这样,我认为你的问题与 https://stackoverflow.com/questions/57464585/elastic-beanstalk-log-path-not-updating-when-docker-container-changes 有关。 - kierans
是的,看起来相关,但不幸的是那里没有答案。如果我检查我的CloudWatch日志组,我有类似以下的内容:/aws/elasticbeanstalk/my-env/var/log/eb-docker/containers/eb-current-app/stdouterr.log然而,如果我直接拉取日志,我会观察到以下内容:/var/log/eb-docker/containers/eb-current-app/eb-"hexstring"-stdouterr.log - Farid Hajnal
2个回答

10

我成功解决了这个问题。 因此,CloudWatch根据日志文件的第一行和日志流键生成哈希值,问题在于我的stdouterr.log文件的第一行实际上是空行!

经过几天的尝试并得到AWS支持团队的帮助后,我首先通过SSH连接到与EB环境关联的EC2实例,然后需要在/etc/awslogs/config/beanstalklogs.conf文件中在“file=/var/log/eb-docker/containers/eb-current-app/stdouterr.log”行后添加以下行:

file_fingerprint_lines=1-20

这样,您就告诉AWS服务应使用日志文件的第1到20行计算哈希值。您可以根据日志内容将20更改为较大或较小的数字。但是,我不知道该值是否有上限。

这样做后,您需要在实例上重新启动AWS Logs Service

要执行此操作,您需要执行以下操作:

  • sudo service awslogs stop
  • sudo service awslogs start

或者更简单地:

sudo service awslogs restart

完成这些步骤后,我开始使用我的环境,日志现在可以正确地流式传输到CloudWatch控制台! 但是,如果进行新的部署,EC2实例被替换或自动可伸缩组产生另一个实例,则无法解决此问题。

为了解决这个问题,可以通过.ebextensions目录添加日志配置,在部署之前将其放在应用程序的根目录下。

我在新创建的.ebextensions目录中添加了一个名为logs.config的文件,并放置了以下内容:

files:
  "/etc/awslogs/config/beanstalklogs.conf":
    mode: "000644"
    user: root
    group: root
    content: |
      [/var/log/eb-docker/containers/eb-current-app/stdouterr.log]
      log_group_name=/aws/elasticbeanstalk/EB-ENV-NAME/var/log/eb-docker/containers/eb-current-app/stdouterr.log
      log_stream_name={instance_id}
      file=/var/log/eb-docker/containers/eb-current-app/*stdouterr.log
      file_fingerprint_lines=1-20

commands:
  01_remove_eb_stream_config:
    command: 'rm /etc/awslogs/config/beanstalklogs.conf.bak'
  02_restart_log_agent:
    command: 'service awslogs restart'

更改环境名称为EB中的课程EB-ENV-NAME

希望能帮到其他人!


做得好,解决了这个问题,我也遇到了同样的问题。你的日志语句包含时间戳吗?有人建议我更改应用程序日志配置,使日志消息具有时间戳。因为任何哈希值都将始终不同,您无需提供任何额外的Beanstalk日志配置,就像您所做的那样。 - kierans
1
@kierans 我所知道的也是这样解决问题的。问题在于我正在使用一个框架,它默认将日志的第一行输出为空行,因此我猜测这是与 AWS 日志代理进行比较的那一行,这就是为什么我不得不依靠修改“file_fingerprint_lines”的原因。 - Farid Hajnal
@FaridHajnal 这个配置应该会移除 beanstalklogs.conf 中现有的日志设置吗? - titus
1
这对我的NodeJS单个Docker实例没有起作用(Docker运行在64位Amazon Linux 2/3.0.3上)。 - Ariel Frischer
@ArielFrischer 你好。我正在使用 NestJs 框架来构建我的服务器应用程序,该应用程序也在单个 Docker 实例环境中运行。 - Farid Hajnal
@Farid Hajnal,您有什么问题吗?此外,我想补充一下之前的脚本未能运行是因为它导致了一个部署错误。我目前正在与 AWS 支持团队尝试一些修复方法,如果有成果,我将在下面回报。 - Ariel Frischer

7

对于64位的Amazon Linux 2,设置略有不同。

用于传递日志的AWS CloudWatch Agent被安装在/opt/aws/amazon-cloudwatch-agent中,而Elastic Beanstalk配置则在/opt/aws/amazon-cloudwatch-agent/etc/beanstalk.json中。它被设置为记录容器的输出,假设存在名为stdouterr.log的文件,以下是配置的一部分:

{
  "file_path": "/var/log/eb-docker/containers/eb-current-app/stdouterr.log",
  "log_group_name": "/aws/elasticbeanstalk/EB-ENV-NAME/var/log/eb-docker/containers/eb-current-app/stdouterr.log",
  "log_stream_name": "{instance_id}"
}

然而当我查找file_path时,它并不存在,相反我有一个文件路径编码为当前 Docker 容器 ID /var/log/eb-docker/containers/eb-current-app/eb-e4e26c0bc464-stdouterr.log

这个日志文件是由脚本/opt/elasticbeanstalk/config/private/eb-docker-log-start创建的,该脚本由eb-docker-log服务启动,此文件的默认内容如下:

EB_CONFIG_DOCKER_CURRENT_APP=`cat /opt/elasticbeanstalk/deployment/.aws_beanstalk.current-container-id | cut -c 1-12`
mkdir -p /var/log/eb-docker/containers/eb-current-app/
docker logs -f $EB_CONFIG_DOCKER_CURRENT_APP >> /var/log/eb-docker/containers/eb-current-app/eb-$EB_CONFIG_DOCKER_CURRENT_APP-stdouterr.log 2>&1

为了暂时修复日志问题,您可以手动运行以下命令(替换docker ID),然后日志将开始在CloudWatch中出现:
ln -sf /var/log/eb-docker/containers/eb-current-app/eb-e4e26c0bc464-stdouterr.log /var/log/eb-docker/containers/eb-current-app/stdouterr.log

为使此更改永久生效,我添加了一个 .ebextension 来修复 eb-docker-log 服务,以便重新创建此链接。在您的源代码中创建一个名为 fix-cloudwatch-logging.config 的文件,并将其放置在 .ebextensions 目录下,然后设置其内容为:
files:
  "/opt/elasticbeanstalk/config/private/eb-docker-log-start" :
    mode: "000755"
    owner: root
    group: root
    content: |
      EB_CONFIG_DOCKER_CURRENT_APP=`cat /opt/elasticbeanstalk/deployment/.aws_beanstalk.current-container-id | cut -c 1-12`
      mkdir -p /var/log/eb-docker/containers/eb-current-app/
      ln -sf /var/log/eb-docker/containers/eb-current-app/eb-$EB_CONFIG_DOCKER_CURRENT_APP-stdouterr.log /var/log/eb-docker/containers/eb-current-app/stdouterr.log
      docker logs -f $EB_CONFIG_DOCKER_CURRENT_APP >> /var/log/eb-docker/containers/eb-current-app/eb-$EB_CONFIG_DOCKER_CURRENT_APP-stdouterr.log 2>&1
commands:
  fix_logging:
    command: systemctl restart eb-docker-log.service
    cwd: /home/ec2-user
    test: "[ ! -L /var/log/eb-docker/containers/eb-current-app/stdouterr.log ] && systemctl is-active --quiet eb-docker-log"

这对我有用!为了澄清一下,我将.ebextensions目录放在了项目目录中,而不是.elasticbeanstalk目录中。 - abogaard
我已经删除了对elasticbeanstalk的引用,这是因为我本地安排项目的方式,感谢您指出这一点。 - Matthew Buckett
好的,有时候AWS会修复这个问题,并且在“Amazon Linux 2/3.2.3”中不再需要它。我不知道确切的修复时间。 - Matthew Buckett
1
每当它被修复后,他们都会在“file_path”:“/var/log/eb-docker/containers/eb-current-app/*stdouterr.log”中添加一个*。不过,了解他们记录此类修复的位置仍然很酷。 - nelsonjchen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接