Статьи

Запуск HTTP Traffic Replayer на AWS Elastic Beanstalk

Gor — отличная утилита для репликации (подмножества) рабочего трафика в промежуточную / тестовую среду. Запуск его в AWS Elastic Beanstalk (EB) сопряжен с некоторыми трудностями, в основном из-за того, что он не поддерживает запуск в качестве демона и что для этого нет документации / примеров. Ну, вот решение:

# File: .ebextensions/10gor.config
# Config Gor to copy a sample of Prod http traffice to staging
files:
  # Utility for daemonizing binaries such as gor; see http://libslack.org/daemon
  /opt/daemon.rpm:
    source: "https://s3-eu-west-1.amazonaws.com/elasticbeanstalk-eu-west-1-<our>/our_fileserver/daemon-0.6.4-1.x86_64.rpm"
    authentication: S3Access # See AWS::CloudFormation::Authentication below
    owner: root
    group: root

  # daemon config so that we don't need to repeat these command line options and
  # can just use the service's name ("gor")
  # We need to intercept the port 8080, not 80 (that iptables redirect to 8080)
  /etc/daemon.conf:
    # Troubleshooting tips:
    # 1) Send stderr/out output of both daemon and the service to a file - see the commented-out line
    #    (it should be also possible to send it to syslog but that did not work for me)
    # 2) Add "foreground" to the options and start the service manually on the server
    content: |
      gor  respawn,command=/opt/gor --input-raw :8080 --output-http 'https://our-staging.example.com|1'
      #gor  output=/var/log/gor.log,respawn,command=/opt/gor --stats --output-http-stats --input-raw :8080 --output-http 'https://our-staging.example.com|1'
      #gor  errlog=/var/log/daemonapp.log,dbglog=/var/log/daemonapp.log,output=/var/log/gor.log,verbose,debug,respawn,command=/opt/gor --verbose --stats --output-http-stats --input-raw :8080 --output-http 'https://our-staging.example.com|1'
    # Use the commented-out line to enable stats logging to syslog (/var/log/messages) every 5s for troubleshooting
    content: |
      gor  respawn,command=/opt/gor --input-raw :8080 --output-http 'https://our-staging.example.com|1'
      #gor  respawn,output=gor.info,command=/opt/gor --stats --output-http-stats --input-raw :8080 --output-http 'https://our-staging.example.com|1'
  # HTTP traffic replicator; see https://github.com/buger/gor
  /opt/gor:
    source: "https://s3-eu-west-1.amazonaws.com/elasticbeanstalk-eu-west-1-<our>/our_fileserver/gor"
    authentication: S3Access
    mode: "000755"
    owner: root
    group: root

  # System V service that supports chkconfig
  /etc/init.d/gor:
    mode: "000755"
    owner: root
    group: root
    content: |
      ## The chkconfig <levels> <startup order> <stop order> + descr. needed to
      ## support ensureRunning
      # chkconfig: 345 92 08
      # description: Gor copies traffic to staging
      ### BEGIN INIT INFO
      # Provides: gor
      # Short-Description: Start Gor to copy traffic to staging
      ### END INIT INFO
      # See how we were called.
      case "$1" in
        start)
              /usr/local/bin/daemon --name gor
              ;;
        stop)
              /usr/local/bin/daemon --name gor --stop
              ;;
        status)
              if ! /usr/local/bin/daemon --name gor --running; then
                  echo "gor is stopped"; exit 3
              fi
              ;;
        restart)
              /usr/local/bin/daemon --name gor --stop
              /usr/local/bin/daemon --name gor
              ;;
        *)
              echo $"Usage: $0 {start|stop|restart}"
              exit 2
      esac
      exit 0
commands:
  "Install daemon":
    command: rpm -i /opt/daemon.rpm
    test: /bin/sh -c "! rpm -q daemon" # It seems 'test: ! rpm -q daemon' ignores the !

services:
  sysvinit:
    gor:
      enabled: true
      ensureRunning: true

  # Allow files: to access our S3 bucket
  # See https://forums.aws.amazon.com/thread.jspa?messageID=557993
  # BEWARE: We have to explicitely allow access to any subdirectory by
  # editing the S3 bucket's policy and adding the subdir to the allowed Resources
  AWSEBAutoScalingGroup:
    Metadata:
      AWS::CloudFormation::Authentication:
        "S3Access": # reference this in the "authentication" property
          type: S3
          roleName: aws-elasticbeanstalk-ec2-role
          buckets: elasticbeanstalk-eu-west-1-<our id>

Особенности

  1. Мы хотим запускать Gor как сервис (а не просто команду background + nohup), потому что это единственный способ гарантировать, что он будет работать, даже когда EB добавляет и удаляет узлы.
  2. Используйте утилиту daemon для запуска Gor как демона (который он не поддерживает «из коробки»). Демон маленький и хорошо работает. Он проигнорирует вывод gor и автоматически перезапустит его, если умрет.
  3. Создайте скрипт init.d для gor. Для поддержки ebextensions ensureRunning, он должен поддерживать chkconfig
  4. Проверка того, установлен ли демон, не может быть простой, ! rpm -q daemonно должна быть /bin/sh -c "! rpm -q daemon"; testкажется, что для выполнения свойства требуется одна команда
  5. Файлы загружаются из частного хранилища S3 (которое должно быть доступно используемой роли EC2 и иметь политику, разрешающую доступ к рассматриваемым файлам)

Примечание

Первоначально я хотел запустить Gor только на одном узле, используя container_command с leader_only, чтобы включить его только на этом узле. Однако это не работает, потому что это выполняется только тогда, когда приложение развернуто, но не когда автоматическое масштабирование добавляет новые узлы (например, после убийства некоторых старых — обычно начиная с лидера). Новые узлы несколько клонируются из существующих, поэтому у них есть пакет, служба и т. Д., Но команда там не запускается. И нет никакой концепции «лидера» вне процесса развертывания EB. Таким образом, единственный вариант — запустить Gor на всех узлах.