Сбой развертывания конечной точки AWS SageMaker Pipeline Model

Я хочу развернуть конвейерную модель Sagemaker с двумя контейнерами. Я имею в виду это: Ссылка: https://sagemaker.readthedocs.io/en/stable/api/inference/pipeline.html.

Первый контейнер будет содержать код предварительной обработки изображения, а второй контейнер будет содержать код вывода модели. Я обновил файлы докеров обоих контейнеров, добавив следующую строку:

# 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 контейнера по отдельности, развернув обычные конечные точки с одним контейнером. Обе конечные точки развертываются и работают по назначению. Но когда я пытаюсь развернуть модель конвейера, конечная точка не развертывается и выдает следующую ошибку:

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 для обоих контейнеров, и не было обнаружено ошибок, связанных с ошибкой «проверки работоспособности». Пожалуйста, взгляните на журнал cloudwatch 1 контейнера (2-й тоже такой же):

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. Я прочитал часть документации и узнал, что нам нужно сообщить докеру о привязке портов. Добавил следующую строку в 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. Каждый тип содержимого ввода-вывода обновлен до: «текстовый/обычный» (чтобы не было аномалий даже в межконтейнерной связи)
Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
1
0
74
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Обновление: мне удалось решить эту проблему


Фактическая проблема заключается в том, что конечная точка не может пропинговать контейнер. Это связано с тем, что при наличии нескольких контейнеров каждый контейнер использует некоторый динамический порт для связи, и конечной точке необходимо знать, какой порт использует каждый контейнер. Следовательно, нам нужно написать собственный код для замены значения порта [8080] в файле nginx.conf значением, которое находится внутри переменной окружения ['SAGEMAKER_BIND_TO_PORT'].

Код для выполнения вышеуказанной операции взят из этого примера sagemker: https://github.com/aws/amazon-sagemaker-examples/tree/main/contrib/inference_pipeline_custom_containers/containers

В файле подачи используйте приведенную ниже функцию start_server():

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 "{}";
    }
  }
}

Другие вопросы по теме