howto:弹性beanstalk +部署docker + graceful shutdown

sam*_*amz 10 deployment redeploy docker amazon-elastic-beanstalk

嗨伟大的stackoverflow人,

在EB上托管一个docker容器,并在其上运行基于nodejs的代码.重新部署我们的docker容器时,我们希望旧的容器能够正常关闭.

我找到了关于我们的代码如何接收'docker stop'命令产生的sigterm信号的帮助和指南.

然而,对运行码头工具的EB机器的进一步调查 /opt/elasticbeanstalk/hooks/appdeploy/enact/01flip.sh 表明,当从当前"翻转"到新的分段容器时,旧的机器被"docker kill"杀死

有没有办法将此行为更改为docker stop?
或者一般来说,一种推荐的方法来处理旧容器的正常关闭?

谢谢!

sam*_*amz 6

自我回答,因为我找到了适合我们的解决方案:

tl; dr:使用.ebextensions脚本在01flip之前运行你的脚本,你的脚本将确保在docker内部正常关闭whatevers

首先,你的应用程序(或者你在docker中运行的任何东西)必须能够捕获一个信号,例如SIGINT,然后优雅地关闭它.
这与Docker完全无关,你可以测试它在哪里运行(例如本地)有很多关于在网上为不同类型的应用程序完成这种行为的信息(无论是ruby,node.js等等. .)

其次,基于EB/Docker的项目可以有一个.ebextensions文件夹,该文件夹包含部署时要执行的所有类型的脚本.我们将2个自定义脚本放入其中,gracefulshutdown_01.config和gracefulshutdown_02.config文件看起来像这样:

# gracefulshutdown_01.config
commands:
  backup-original-flip-hook:
    command: cp -f /opt/elasticbeanstalk/hooks/appdeploy/enact/01flip.sh /opt/elasticbeanstalk/hooks/appdeploy/01flip.sh.bak
    test: '[ ! -f /opt/elasticbeanstalk/hooks/appdeploy/01flip.sh.bak ]'
  cleanup-custom-hooks:
    command: rm -f 05gracefulshutdown.sh
    cwd: /opt/elasticbeanstalk/hooks/appdeploy/enact
    ignoreErrors: true
Run Code Online (Sandbox Code Playgroud)

和:

# gracefulshutdown_02.config
commands:
  reorder-original-flip-hook:
    command: mv /opt/elasticbeanstalk/hooks/appdeploy/enact/01flip.sh /opt/elasticbeanstalk/hooks/appdeploy/enact/10flip.sh
    test: '[ -f /opt/elasticbeanstalk/hooks/appdeploy/enact/01flip.sh ]'

files:
  "/opt/elasticbeanstalk/hooks/appdeploy/enact/05gracefulshutdown.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/bin/sh

      # find currently running docker
          EB_CONFIG_DOCKER_CURRENT_APP_FILE=$(/opt/elasticbeanstalk/bin/get-config container -k app_deploy_file)
      EB_CONFIG_DOCKER_CURRENT_APP=""

      if [ -f $EB_CONFIG_DOCKER_CURRENT_APP_FILE ]; then
        EB_CONFIG_DOCKER_CURRENT_APP=`cat $EB_CONFIG_DOCKER_CURRENT_APP_FILE | cut -c 1-12`
        echo "Graceful shutdown on app container: $EB_CONFIG_DOCKER_CURRENT_APP"
      else
        echo "NO CURRENT APP TO GRACEFUL SHUTDOWN FOUND"
        exit 0
      fi

      # give graceful kill command to all running .js files (not stats!!)
      docker exec $EB_CONFIG_DOCKER_CURRENT_APP sh -c "ps x -o pid,command | grep -E 'workers' | grep -v -E 'forever|grep' " |  awk '{print $1}' | xargs docker exec $EB_CONFIG_DOCKER_CURRENT_APP kill -s SIGINT
      echo "sent kill signals"

      # wait (max 5 mins) until processes are done and terminate themselves
      TRIES=100
      until [ $TRIES -eq 0 ]; do
        PIDS=`docker exec $EB_CONFIG_DOCKER_CURRENT_APP sh -c "ps x -o pid,command | grep -E 'workers' | grep -v -E 'forever|grep' " | awk '{print $1}' | cat`
        echo TRIES $TRIES PIDS $PIDS
        if [ -z "$PIDS" ]; then
          echo "finished graceful shutdown of docker $EB_CONFIG_DOCKER_CURRENT_APP"
          exit 0
        else
          let TRIES-=1
          sleep 3
        fi
      done

      echo "failed to graceful shutdown, please investigate manually"
      exit 1
Run Code Online (Sandbox Code Playgroud)

gracefulshutdown_01.config是一个小的util,它备份原始的flip01并删除(如果存在)我们的自定义脚本.

gracefulshutdown_02.config是魔术发生的地方.它会创建一个05gracefulshutdown enact脚本,并确保之后将其重命名为10flip.

05gracefulshutdown,自定义脚本,基本上这样做:

  • 找到当前正在运行的docker
  • 找到需要发送SIGINT的所有进程(对于我们的进程,名称中包含'workers'
  • 向上述进程发送一个sigint
  • 环:
  • 检查之前的进程是否被杀死
  • 继续循环尝试一定数量
  • 如果尝试结束,退出状态为"1"并且不继续10翻转,则需要手动干扰.

这假设您在机器上只运行了一个docker,并且您可以手动跳转以检查它失败的情况是否错误(对于我们从未发生过).
我想它也可以在很多方面得到改善,所以玩得开心.