如何从运行 Fargate ECS 任务中查看 Python 打印语句?

Posted

技术标签:

【中文标题】如何从运行 Fargate ECS 任务中查看 Python 打印语句?【英文标题】:How to see Python print statements from running Fargate ECS task? 【发布时间】:2021-01-17 09:12:12 【问题描述】:

我有一个 Fargate ECS 容器,用于通过 ECS 中的任务运行 Docker 容器。任务启动时,会调用一个sh脚本,runner.sh

#!/bin/sh
echo "this line will get logged to ECS..."
python3 src/my_python_script.py # however print statements from this Python script are not logged to ECS

这又会启动一个长时间运行的 Python 脚本 my_python_script.py。我知道 Python 脚本运行良好,因为它完成了它需要做的事情,但我看不到 Python 脚本的输出。

my_python_script.py 内部有几个print() 语句。在我的 ECS Fargate 任务的 CloudWatch 日志中,我看到了 sh 脚本 ("this line will get logged to ECS...") 的输出,但没有看到 Python 脚本中的 print() 语句的输出。

这是我的任务定义中的日志配置:


    "ipcMode": null,
    "executionRoleArn": "myecsTaskExecutionRolearn",
    "containerDefinitions": [
        
            "dnsSearchDomains": null,
            "environmentFiles": null,
            "logConfiguration": 
                "logDriver": "awslogs",
                "secretOptions": null,
                "options": 
                    "awslogs-group": "/ecs/mylogsgroup",
                    "awslogs-region": "eu-west-1",
                    "awslogs-stream-prefix": "ecs"
                
            ,
            "entryPoint": null,
            "portMappings": [],
            "command": null,
            "linuxParameters": null,
            "cpu": 0,
            "environment": [],
            "resourceRequirements": null,
            "ulimits": null,
            "dnsServers": null,
            "mountPoints": [],
            "workingDirectory": null,
            "secrets": null,
            "dockerSecurityOptions": null,
            "memory": null,
            "memoryReservation": null,
            "volumesFrom": [],
            "stopTimeout": null,
            "image": "1234567.dck.aws.com/mydockerimage",
            "startTimeout": null,
            "firelensConfiguration": null,
            "dependsOn": null,
            "disableNetworking": null,
            "interactive": null,
            "healthCheck": null,
            "essential": true,
            "links": null,
            "hostname": null,
            "extraHosts": null,
            "pseudoTerminal": null,
            "user": null,
            "readonlyRootFilesystem": null,
            "dockerLabels": null,
            "systemControls": null,
            "privileged": null,
            "name": "my-task-definition-name"
        
    ],
    "memory": "4096",
    "taskRoleArn": "myecsTaskRolearn",
    "family": "my-task-definition-name",
    "pidMode": null,
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "networkMode": "awsvpc",
    "cpu": "2048",
    "inferenceAccelerators": [],
    "proxyConfiguration": null,
    "volumes": [],
    "tags": []

Dockerfile:


FROM rocker/verse:3.6.0
ENV DEBIAN_FRONTEND noninteractive

RUN install2.r --error \
    jsonlite

RUN echo "deb http://ftp.de.debian.org/debian testing main" >> /etc/apt/sources.list
RUN echo 'APT::Default-Release "stable";' | tee -a /etc/apt/apt.conf.d/00local
RUN apt-get update && apt-get -t testing install -y --force-yes python3.6
RUN apt-get update && apt-get -t testing install -y libmagick++-dev python3-pip python-setuptools 

RUN mkdir /app
WORKDIR /app
COPY ./src /app/src

RUN pip3 install --trusted-host pypi.python.org -r /app/requirements.txt

CMD /app/runner.sh

我想我正在遵循 https://docs.aws.amazon.com/AmazonECS/latest/userguide/using_awslogs.html 的 awslogs 说明,但也许不是?我是否需要做一些明显的事情来确保 Python 脚本中的 print() 语句被捕获到我的 ECS 任务的 CloudWatch 日志中?

【问题讨论】:

你能发布剩下的任务定义和构建镜像的 Dockerfile 吗? @alexandre-juma 我已经编辑了我的问题以添加我的任务定义和 Dockerfile。谢谢 您可以尝试将 Dockerfile CMD 语句更改为 exec 格式 CMD ["/app/runner.sh"] 并添加更改您的帮助脚本,例如 exec python3 src/my_python_script.py 吗?在此之后,请以交互方式登录到容器并检查 PID 1 是否被您的 python 脚本持有以确保。 这是一个长镜头,但也许日志驱动程序吓坏了,因为您的 PID 1 是一个包装外壳(您没有在 exec 模式下运行 CMD),然后调用另一个外壳脚本 /app/runner .sh 然后调用python解释器和脚本。 【参考方案1】:

在我看来,您可以在这里处理几件事情。

第一个是 Python 的默认缓冲行为,它可以阻止输出显示。你需要阻止它。

您可以通过在 CMD 之前插入以下内容来正确设置 PYTHONUNBUFFERED env var:

ENV PYTHONUNBUFFERED=1

其次,引用您链接的 Using the awslogs driver 文档:

任务中容器记录的信息类型主要取决于它们的 ENTRYPOINT 命令。默认情况下,如果您在本地运行容器,捕获的日志会显示您通常会在交互式终端中看到的命令输出,即 STDOUT 和 STDERR I/O 流。 awslogs 日志驱动程序只是将这些日志从 Docker 传递到 CloudWatch Logs。有关如何处理 Docker 日志的更多信息,包括捕获不同文件数据或流的替代方法,请参阅 Docker 文档中的查看容器或服务的日志。

因此,按照the Exec form of ENTRYPOINT,我将用以下内容替换 CMD 行:

ENTRYPOINT ["/app/runner.sh"]

这应该用于连接您的 shell 脚本的 STDOUT 和 STDERR I/O 流,并希望您的 Python 脚本连接到容器日志记录。

【讨论】:

以上是关于如何从运行 Fargate ECS 任务中查看 Python 打印语句?的主要内容,如果未能解决你的问题,请参考以下文章

Auto-Scaling 移除 ECS 服务中正在运行的任务 (FARGATE)

如何在 AWS ECS 服务中查看每晚自动缩放后的任务计数历史记录

如何诊断 ECS Fargate 任务启动失败?

如何在 ECS Fargate 任务定义中配置主机名

AWS ECS Fargate - 任务未运行

AWS ECS Fargate 任务的静态出站 IP