ECS Fargate: возвращает код выхода основного контейнера(ов)

Объяснение

В настоящее время я использую Fargate на Amazon ECS. В моей настройке есть определение задачи, которое включает в себя два контейнера:

  1. Контейнер кода Python: выполняет основную логику приложения.
  2. Эфемерный сервисный контейнер: поддерживает код Python, предоставляя временный сервис, от которого зависит код Python (Selenium-hub).

Проблема

Я хочу следующее поведение:

  • Когда код Python завершит свое выполнение, он должен завершиться без проблем.
  • Одновременно с этим следует завершить работу эфемерного сервисного контейнера.

Однако у меня возникла проблема с тем, как ECS обрабатывает свойство essential в определении задачи. Когда я устанавливаю essential на true для контейнера Python, ECS отправляет сигнал SIGTERM в эфемерный сервисный контейнер после завершения работы контейнера Python. В результате контейнер эфемерной службы возвращает ненулевой код завершения, что нежелательно.

Желаемое поведение

Мне нужно, чтобы ECS логически AND возвращал коды возврата только основных контейнеров, а это означает, что коды завершения второстепенных контейнеров не должны влиять на общий статус задачи. В частности, я хочу, чтобы задача учитывала только код завершения контейнера Python, игнорируя код завершения эфемерного сервисного контейнера при определении того, выполнена ли задача успешно или нет.

Вопрос

Есть ли какой-нибудь способ или сложное решение для решения этой проблемы?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Это ожидаемое поведение, поскольку вы отметили свой контейнер Python как важный, отсюда :

ECS завершает второстепенные задачи, отправляя SIGTERM в необязательные контейнеры. По истечении тайм-аута в 30 секунд (тайм-аут по умолчанию) он отправляет SIGKILL для принудительной остановки контейнера.

Итак, вам нужно обработать сигнал SIGTERM в ваших «необязательных» контейнерах и сделать все необходимое для правильной очистки и выхода. Короче говоря, вам нужно что-то вроде этого примера с Python из здесь:

def shutdown_handler(signal: int, frame: FrameType) -> None:
    """Gracefully shutdown app."""
    logger.info("Signal received, safely shutting down.")
    database.shutdown()
    middleware.logging_flush()
    print("Exiting process.", flush=True)
    sys.exit(0)


if __name__ == "__main__":
    # handles Ctrl-C locally
    signal.signal(signal.SIGINT, shutdown_handler)

    app.run(host = "127.0.0.1", port=8080, debug=True)
else:
    # handles Cloud Run container termination
    signal.signal(signal.SIGTERM, shutdown_handler)

А также поручите ECS передавать сигналы для обработки внутри конатинеров, включив initProcessEnabled проверить документацию здесь

Интересный пост об AWS по обработке сигналов с помощью ECS.

Спасибо за ваш ответ. Я не хочу изменять образ второго контейнера по умолчанию. Есть ли какое-либо решение для этой цели?

Mostafa Ghadimi 29.08.2024 12:56

Включите initProcessEnabled во втором контейнере, чтобы позволить процессу перехватывать сигнал SIGTERM, и надейтесь, что ваш процесс в контейнере сможет обработать это по умолчанию, в противном случае я не вижу никаких альтернатив, поскольку именно так работают процессы и сигналы.

Med Agou 29.08.2024 13:07

Позвольте мне попробовать. Второй контейнер — Docker-Selenium.

Mostafa Ghadimi 29.08.2024 13:11

К сожалению, это не работает! :(

Mostafa Ghadimi 29.08.2024 14:14

Можете ли вы установить значение false для этого контейнера? Docker-Selenium и оставить значение true для контейнера Python?

Med Agou 29.08.2024 14:40

Я сделал то же самое. Код Python важен и зависит от того, находится ли код Selenium в начальном состоянии.

Mostafa Ghadimi 29.08.2024 14:44

Я просто публикую ответ на него и ссылаюсь на ваш пост. Спасибо за помощь.

Mostafa Ghadimi 01.09.2024 14:54
Ответ принят как подходящий

Как уже упоминалось @MedAgou, не существует простого способа справиться с этим конкретным сценарием (т. е. управлять сигналами или изменять код выхода в несущественном дополнительном контейнере).

Вот два подхода к решению этой проблемы при использовании контейнеров selenium-hub и Python code:

  1. Создание собственного образа. Вы можете создать собственный образ Docker, сочетающий в себе функциональность обоих контейнеров. Однако такой подход увеличивает сложность системы и создает тесно связанную кодовую базу, что обычно не рекомендуется.

  2. Изменение точки входа контейнера Selenium Hub. Более гибкое решение предполагает изменение точки входа контейнера selenium-hub. Я исследовал этот репозиторий и адаптировал скрипт enter_point.sh следующим образом:

    #!/usr/bin/env bash
    
    NODE_CONFIG_DIRECTORY=${NODE_CONFIG_DIRECTORY:-"/opt/bin"}
    #==============================================
    # OpenShift or non-sudo environments support
    # https://docs.openshift.com/container-platform/3.11/creating_images/guidelines.html#openshift-specific-guidelines
    #==============================================
    
    if ! whoami &> /dev/null; then
      if [ -w /etc/passwd ]; then
        echo "${USER_NAME:-default}:x:$(id -u):0:${USER_NAME:-default} user:${HOME}:/sbin/nologin" >> /etc/passwd
      fi
    fi
    
    /usr/bin/supervisord --configuration /etc/supervisord.conf &
    
    SUPERVISOR_PID=$!
    
    function shutdown {
        echo "The following line does the trick!"
        exit 0
    }
    
    trap shutdown SIGTERM SIGINT
    wait ${SUPERVISOR_PID}
    

    Докерфайл:

    ARG IMAGE_TAG=4.23.1-20240820
    FROM selenium/standalone-chrome:${IMAGE_TAG}
    
    LABEL maintainer = "Mostafa"
    
    COPY modified-entry-point.sh /opt/bin/modified-entry-point.sh
    RUN chmod +x /opt/bin/modified-entry-point.sh
    ENTRYPOINT ["/opt/bin/modified-entry-point.sh"]
    

Этот сценарий гарантирует, что при выходе из контейнера Python контейнер selenium-hub корректно обработает завершение, не вызывая ненулевой код выхода. Такой подход сохраняет слабую связь между вашими сервисами и обеспечивает желаемое поведение ECS.

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