簡體   English   中英

AWS SageMaker Pipeline Model 端點部署失敗

[英]AWS SageMaker Pipeline Model endpoint deployment failing

我想部署一個具有 2 個容器的 Sagemaker Pipeline Model。 我指的是這個:鏈接: https://sagemaker.readthedocs.io/en/stable/api/inference/pipeline.html

第一個容器將包含圖像預處理代碼,第二個容器將包含 model 推理代碼。 我已將兩個容器的 docker 文件更新為具有以下行:

# Set a docker label to enable container to use SAGEMAKER_BIND_TO_PORT environment variable if present
LABEL com.amazonaws.sagemaker.capabilities.accept-bind-to-port=true

我通過使用單個容器部署正常端點來分別測試了 2 個容器。 兩個端點都按預期部署和工作。 但是,當我嘗試部署管道 model 時,端點未部署並出現以下錯誤:

UnexpectedStatusException: Error hosting endpoint sagemaker-inference-pipeline-endpoint: Failed.
Reason:  The container-1,container-2 for production variant AllTraffic did not pass the ping health check. 
Please check CloudWatch logs for this endpoint..

我已經檢查了兩個容器的 cloudwatch 日志,沒有顯示與“健康檢查”失敗相關的錯誤。 請查看 1 個容器的 cloudwatch 日志(第二個也一樣):

Starting the inference server with 2 workers.
[2022-11-20 14:50:44 +0000] [15] [INFO] Starting gunicorn 20.1.0
[2022-11-20 14:50:44 +0000] [15] [INFO] Listening at: unix:/tmp/gunicorn.sock (15)
[2022-11-20 14:50:44 +0000] [15] [INFO] Using worker: sync
[2022-11-20 14:50:44 +0000] [18] [INFO] Booting worker with pid: 18
[2022-11-20 14:50:44 +0000] [19] [INFO] Booting worker with pid: 19

請注意:出於測試目的,現在我還更新了執行以下操作的代碼:

  • 始終將健康檢查返回為 True(狀態 200)
  • 每個輸入輸出內容類型都是:“文本/純文本”

請指導我在不知不覺中遺漏了什么或在某處犯了錯誤。 非常感謝。

我嘗試過的事情的總結:

  1. 分別測試了兩個容器作為端點部署。 兩個容器都被部署為端點
  2. 我已經閱讀了文檔部分並且知道我們需要告訴 docker 關於端口綁定。 在 dockerfile 中添加了以下行:
# Set a docker label to enable container to use SAGEMAKER_BIND_TO_PORT environment variable if present
LABEL com.amazonaws.sagemaker.capabilities.accept-bind-to-port=true
  1. 更新了兩個容器各自代碼文件中的代碼,以始終返回健康檢查通過(狀態:200)
  2. 每個輸入輸出內容類型都更新為:“text/plain”(這樣即使在容器間通信中也不會出現異常)

更新:我能夠解決這個問題


實際問題是端點無法ping通容器。 這是因為,當有多個容器時,每個容器都使用一些動態端口進行通信,端點需要知道每個容器使用哪個端口。 因此,我們需要編寫自定義代碼,用 ['SAGEMAKER_BIND_TO_PORT'] 環境變量中的值替換 nginx.conf 文件中的端口值 [8080]。

從這個 sagemker 示例中引用了執行上述操作的代碼: https://github.com/aws/amazon-sagemaker-examples/tree/main/contrib/inference_pipeline_custom_containers/containers

在服務文件中,使用下面的start_server() function:

def start_server():
    print('Starting the inference server with {} workers.'.format(model_server_workers))

    # link the log streams to stdout/err so they will be logged to the container logs
    subprocess.check_call(['ln', '-sf', '/dev/stdout', '/var/log/nginx/access.log'])
    subprocess.check_call(['ln', '-sf', '/dev/stderr', '/var/log/nginx/error.log'])
    
    port = os.environ.get("SAGEMAKER_BIND_TO_PORT", 8080)
    print("using port: ", port)
    with open("nginx.conf.template") as nginx_template:
        template = Template(nginx_template.read())    
    nginx_conf = open("/opt/program/nginx.conf", "w")
    nginx_conf.write(template.substitute(port=port))
    nginx_conf.close()

    nginx = subprocess.Popen(['nginx', '-c', '/opt/program/nginx.conf'])
    gunicorn = subprocess.Popen(['gunicorn',
                                 '--timeout', str(model_server_timeout),
                                 '-k', 'sync',
                                 '-b', 'unix:/tmp/gunicorn.sock',
                                 '-w', str(model_server_workers),
                                 'wsgi:app'])

    signal.signal(signal.SIGTERM, lambda a, b: sigterm_handler(nginx.pid, gunicorn.pid))

    # If either subprocess exits, so do we.
    pids = set([nginx.pid, gunicorn.pid])
    while True:
        pid, _ = os.wait()
        if pid in pids:
            break

    sigterm_handler(nginx.pid, gunicorn.pid)
    print('Inference server exiting')

而不是 nginx.conf 使用 nginx.conf.template 這將反過來創建具有適當端口的 nginx.conf 文件:

worker_processes 1;
daemon off; # Prevent forking


pid /tmp/nginx.pid;
error_log /var/log/nginx/error.log;

events {
  # defaults
}

http {
  include /etc/nginx/mime.types;
  default_type application/octet-stream;
  access_log /var/log/nginx/access.log combined;
  
  upstream gunicorn {
    server unix:/tmp/gunicorn.sock;
  }

  server {
    listen $port deferred;
    client_max_body_size 5m;

    keepalive_timeout 5;
    proxy_read_timeout 1200s;

    location ~ ^/(ping|invocations) {
      proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
      proxy_set_header Host $$http_host;
      proxy_redirect off;
      proxy_pass http://gunicorn;
    }

    location / {
      return 404 "{}";
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM