El problema apareció recientemente y el contenedor que antes estaba en buen estado ahora entra en un ciclo de suspensión cuando se crea una sesión de cierre. El problema ocurre solo en Cloud Run y no localmente.
Código mínimo reproducible:
requirements.txt
Flask==2.0.1 gunicorn==20.1.0 shutit 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 main.py
import os import shutit from flask import Flask, request app = Flask(__name__) # just to prove api works @app.route('/ping', methods=['GET']) def ping(): os.system('echo pong') return 'OK' # issue replication @app.route('/healthcheck', methods=['GET']) def healthcheck(): os.system("echo 'healthcheck'") # hangs inside create_session shell = shutit.create_session(echo=True, loglevel='debug') # never shell.send reached shell.send('echo Hello World', echo=True) # never returned return 'OK' if __name__ == '__main__': app.run(host='127.0.0.1', port=8080, debug=True) cloudbuild.yaml
steps: - id: "build_container" name: "gcr.io/kaniko-project/executor:latest" args: - --destination=gcr.io/$PROJECT_ID/borked-service-debug:latest - --cache=true - --cache-ttl=99h - id: "configure infrastructure" name: "gcr.io/cloud-builders/gcloud" entrypoint: "bash" args: - "-c" - | set -euxo pipefail REGION="europe-west1" CLOUD_RUN_SERVICE="borked-service-debug" SA_NAME="$${CLOUD_RUN_SERVICE}@${PROJECT_ID}.iam.gserviceaccount.com" gcloud beta run deploy $${CLOUD_RUN_SERVICE} \ --service-account "$${SA_NAME}" \ --image gcr.io/${PROJECT_ID}/$${CLOUD_RUN_SERVICE}:latest \ --allow-unauthenticated \ --platform managed \ --concurrency 1 \ --max-instances 10 \ --timeout 1000s \ --cpu 1 \ --memory=1Gi \ --region "$${REGION}"registros de ejecución en la nube que se repiten:
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 1Soluciones alternativas probadas:
--no-cpu-throttling tampoco hizo ninguna diferenciaNo es un reemplazo perfecto, pero puede usar uno de los siguientes en su lugar:
No estoy seguro de cuál es el panorama general, así que agregaré varias opciones
Para las tareas de automatización remota desde un servidor web de Flass, estamos usando paramiko por su simplicidad y configuración rápida, aunque es posible que prefiera algo como pyinfra para proyectos grandes o subprocess para tareas locales pequeñas.
shutit , ejecuta comandos sobre el protocolo ssh.ejemplo:
import paramiko ip='server ip' port=22 # you can also use ssh keys username='username' password='password' cmd='some useful command' ssh=paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(ip,port,username,password) stdin,stdout,stderr=ssh.exec_command(cmd) outlines=stdout.readlines() resp=''.join(outlines) print(resp)ejemplo para instalar un paquete usando apt:
from pyinfra.operations import apt apt.packages( name='Ensure iftop is installed', packages=['iftop'], sudo=True, update=True, )shutit pero funciona de maravillaHe reproducido su problema y hemos discutido varias posibilidades, creo que el problema es que su Cloud Run no puede procesar solicitudes y, por lo tanto, se prepara para cerrar (sigterm). Estoy enumerando algunas posibilidades para que mires y analices.
Una buena razón por la que su servicio Cloud Run no se inicia es que el proceso del servidor dentro del contenedor está configurado para escuchar en la dirección localhost (127.0.0.1). Esto hace referencia a la interfaz de red de bucle invertido, a la que no se puede acceder desde fuera del contenedor y, por lo tanto, no se puede realizar la comprobación de estado de Cloud Run, lo que provoca el error de implementación del servicio. Para resolver esto, configure su aplicación para iniciar el servidor HTTP para escuchar en todas las interfaces de red, comúnmente indicadas como 0.0.0.0.
Mientras buscaba el error de registros en la nube que está recibiendo, encontré esta respuesta y un enlace de GitHub del desarrollador de la biblioteca de shutit que apunta a una técnica para rastrear entradas y salidas en compilaciones de contenedores complejos en sesiones de shutit. Un buen hallazgo del enlace de GitHub, creo que tendrá que pasar session_type en shutit.create_session('bash') o shutit.create_session('docker') que no está especificando en el archivo main.py. Esa puede ser la razón por la que su sesión de cierre está fallando.
Además, este problema podría deberse a alguna característica del kernel de Linux utilizada por esta biblioteca shutit que actualmente no se admite correctamente en gVisor . No estoy seguro de cómo se ejecutó para ti la primera vez. La mayoría de las aplicaciones funcionarán bien, o al menos tan bien como en Docker normal, pero es posible que no brinden una compatibilidad del 100 %.
Las aplicaciones de Cloud Run se ejecutan en el entorno de pruebas del contenedor gVisor (que actualmente solo es compatible con Linux), que ejecuta las llamadas al sistema del kernel de Linux realizadas por su aplicación en el espacio de usuario. gVisor no implementa todas las llamadas al sistema (ver aquí ). Desde este enlace de Github , “Si su aplicación tiene una llamada de sistema de este tipo (bastante raro), no funcionará en Cloud Run. Dicho evento se registra y puede usar strace para determinar cuándo se realizó la llamada al sistema en su aplicación”
Si está ejecutando su código en Linux, instale y habilite strace: sudo apt-get install strace Ejecute su aplicación con strace anteponiendo su invocación habitual con strace -f donde -f significa rastrear todos los subprocesos secundarios. Por ejemplo, si normalmente invoca su aplicación con ./main , puede ejecutarla con strace invocando /usr/bin/strace -f ./main
De esta documentación , “si cree que su problema se debe a una limitación en el entorno de pruebas de Container. En la sección Cloud Logging de GCP Console (no en la pestaña "Registros" de la sección Cloud Run), puede buscar Container Sandbox con una gravedad DEBUG en los registros varlog/system o usar Log Query:
resource.type="cloud_run_revision" logName="projects/PROJECT_ID/logs/run.googleapis.com%2Fvarlog%2Fsystem"
Por ejemplo: Container Sandbox: llamada al sistema no admitida
setockopt(0x3,0x1,0x6,0xc0000753d0,0x4,0x0)”
De forma predeterminada, las instancias de contenedor tienen las instancias mínimas desactivadas, con una configuración de 0. Podemos cambiar este valor predeterminado mediante Cloud Console, la línea de comando de gcloud o un archivo YAML, especificando una cantidad mínima de instancias de contenedor para mantenerlas activas. y listo para atender solicitudes.
También puede echar un vistazo a esta documentación y GitHub Link que habla sobre el comportamiento del tiempo de ejecución del contenedor de Cloud Run y la resolución de problemas como referencia.