ala*_*nah 6 python flask docker google-cloud-platform google-cloud-run
这个问题最近出现了,之前健康的容器现在在创建 shutdown 会话时进入睡眠循环。该问题仅发生在 Cloud Run 上,而不是本地。
最小可重现代码:
requirements.txt
Flask==2.0.1
gunicorn==20.1.0
shutit
Run Code Online (Sandbox Code Playgroud)
Dockerfile
FROM python:3.9
# Allow statements and log messages to immediately appear in the Cloud Run logs
ENV PYTHONUNBUFFERED True
COPY requirements.txt ./
RUN pip install -r requirements.txt
# Copy local code to the container image.
ENV APP_HOME /myapp
WORKDIR $APP_HOME
COPY . ./
CMD exec gunicorn \
--bind :$PORT \
--worker-class "sync" \
--workers 1 \
--threads 1 \
--timeout 0 \
main:app
Run Code Online (Sandbox Code Playgroud)
main.py
Flask==2.0.1
gunicorn==20.1.0
shutit
Run Code Online (Sandbox Code Playgroud)
cloudbuild.yaml
FROM python:3.9
# Allow statements and log messages to immediately appear in the Cloud Run logs
ENV PYTHONUNBUFFERED True
COPY requirements.txt ./
RUN pip install -r requirements.txt
# Copy local code to the container image.
ENV APP_HOME /myapp
WORKDIR $APP_HOME
COPY . ./
CMD exec gunicorn \
--bind :$PORT \
--worker-class "sync" \
--workers 1 \
--threads 1 \
--timeout 0 \
main:app
Run Code Online (Sandbox Code Playgroud)
循环的云运行日志:
Setting up prompt
In session: host_child, trying to send: export PS1_ORIGIN_ENV=$PS1 && PS1='OR''IGIN_ENV:rkkfQQ2y# ' && PROMPT_COMMAND='sleep .05||sleep 1'
================================================================================
Sending>>> export PS1_ORIGIN_ENV=$PS1 && PS1='OR''IGIN_ENV:rkkfQQ2y# ' && PROMPT_COMMAND='sleep .05||sleep 1'<<<, expecting>>>['\r\nORIGIN_ENV:rkkfQQ2y# ']<<<
Sending in pexpect session (68242035994000): export PS1_ORIGIN_ENV=$PS1 && PS1='OR''IGIN_ENV:rkkfQQ2y# ' && PROMPT_COMMAND='sleep .05||sleep 1'
Expecting: ['\r\nORIGIN_ENV:rkkfQQ2y# ']
export PS1_ORIGIN_ENV=$PS1 && PS1='OR''IGIN_ENV:rkkfQQ2y# ' && PROMPT_COMMAND='sleep .05||sleep 1'
root@localhost:/myapp# export PS1_ORIGIN_ENV=$PS1 && PS1='OR''IGIN_ENV:rkkfQQ2y# ' && PROMPT_COMMAND='sleep .05||sleep 1'
Stopped sleep .05
Stopped sleep 1
pexpect: buffer: b'' before: b'cm9vdEBsb2NhbGhvc3Q6L3B1YnN1YiMgIGV4cx' after: b'DQpPUklHSU5fRU5WOnJra2ZRUTJ5IyA='
Resetting default expect to: ORIGIN_ENV:rkkfQQ2y#
In session: host_child, trying to send: stty cols 65535
================================================================================
Sending>>> stty cols 65535<<<, expecting>>>ORIGIN_ENV:rkkfQQ2y# <<<
Sending in pexpect session (68242035994000): stty cols 65535
Expecting: ORIGIN_ENV:rkkfQQ2y#
ORIGIN_ENV:rkkfQQ2y# stty cols 65535
stty cols 65535
Stopped stty cols 65535
Stopped sleep .05
Stopped sleep 1
Run Code Online (Sandbox Code Playgroud)
尝试过的解决方法:
--no-cpu-throttling也没有什么区别我已经重现了您的问题,并且我们讨论了几种可能性,我认为问题是您的 Cloud Run 无法处理请求,因此准备关闭(sigterm)。\n我列出了一些可能性供您查看和分析。
\nCloud Run 服务无法启动的一个很好的原因是容器内的\n服务器进程被配置为侦听\nlocalhost (127.0.0.1) 地址。指环回网络接口,该接口无法从容器外部访问,因此无法进行Cloud Run健康检查,导致服务部署失败。要解决此问题,请配置您的应用程序以启动 HTTP 服务器以侦听所有网络接口(通常表示为 0.0.0.0)。
\n在搜索您遇到的云日志错误时,我\n发现了这个答案和来自shutit库\n开发者的GitHub链接,它指出了一种在shutit会话中跟踪复杂容器构建中的输入和输出的技术。来自 GitHub 链接的一个很好的发现,我认为您必须传递您未在 main.py 文件中指定的session_type\ninshutit.create_session(\xe2\x80\x98bash\xe2\x80\x99)或\n。shutit.create_session(\xe2\x80\x98docker\xe2\x80\x99)这可能是\n您的 shutdown 会话失败的原因。
此外,此问题可能是由于此 shutdownit 库使用的某些 Linux 内核功能造成的,而 gVisor 目前未正确支持该功能。我不确定第一次是如何为您执行的。\n 大多数应用程序都可以正常运行,或者至少在常规 Docker 中运行良好,但可能无法提供 100% 的兼容性。
\nCloud Run 应用程序在 gVisor 容器沙盒(当前仅支持 Linux)上运行,该沙盒执行您的应用程序在用户空间中进行的 Linux 内核系统调用。gVisor 不实现所有\n系统调用(请参阅此处)。从这个Github 链接来看,\xe2\x80\x9c如果你的\n应用程序有这样的系统调用(非常罕见),它将无法在 Cloud\nRun 上运行。此类事件会被记录下来,您可以使用strace \n确定您的应用\xe2\x80\x9d 中何时进行系统调用
\n如果您在 Linux 上运行代码,请安装并启用 strace:\nsudo apt-get install strace通过在常用调用前加上 strace -f 来运行您的应用程序,其中 -f 表示跟踪所有子线程。例如,如果您通常使用\n调用应用程序./main,则可以通过调用 strace 来运行它/usr/bin/strace -f ./main
根据本文档,\xe2\x80\x9c 如果您认为问题是由容器沙箱中的限制引起的。在 GCP Console 的 Cloud Logging 部分(而不是 Cloud Run 部分的“日志”选项卡中),\n您可以在日志中查找\n严重性Container Sandbox或使用日志查询:DEBUGvarlog/system
\n\nRun Code Online (Sandbox Code Playgroud)\nresource.type="cloud_run_revision"\nlogName="projects/PROJECT_ID/logs/run.googleapis.com%2Fvarlog%2Fsystem"\n
\n\n例如:容器沙箱:不支持的系统调用
\n
\nsetsockopt(0x3,0x1,0x6,0xc0000753d0,0x4,0x0)\xe2\x80\x9d
默认情况下,容器实例的最小实例数处于关闭状态,设置为 0。我们可以使用 Cloud Console、gcloud 命令行或 YAML 文件来更改此默认设置,方法是指定要保温的最小容器实例数并准备好满足请求。
\n您还可以查看此文档和GitHub 链接,其中讨论了 Cloud Run 容器运行时行为和故障排除以供参考。
\n