web-dev-qa-db-ja.com

Elastic Beanstalkは、4xx応答に基づいてヘルス状態の変更を無効にします

Elastic Beanstalkで実行しているREST APIがありますが、これは非常に効果的です。アプリケーションのすべてが正常に動作し、期待どおりに動作しています。

アプリケーションは、さまざまなユーザーを検索するために使用されるREST APIです。

example url: http://service.com/user?uid=xxxx&anotherid=xxxx

いずれかのIDを持つユーザーが見つかった場合、APIは200 OKで応答し、そうでない場合は404 Not Foundで応答します。 HTTP/1.1ステータスコードの定義。

私たちのapiが多くのリクエストで404 Not Foundに応答することは珍しくなく、エラスティックBeantalkは環境をOKからWarningまたはDegradedに転送します。 。また、この状態が悪化したため、nginxがアプリケーションへの接続を拒否したようです。 (warningへの30%+およびdegraded状態への50%+のしきい値があるように見えます。これは問題です。アプリケーションは実際に期待どおりに動作していますが、Elastic Beanstalksのデフォルト設定考えるそれは本当にそうでないとき、それは問題です。

誰でも4xx警告のしきい値とEBの状態遷移を編集する方法、またはそれらを完全に無効にする方法を知っていますか?

または、実際に症状の治療を行い、このような呼び出しで404 Not Foundの使用を停止する必要がありますか? (私は本当にこのオプションが好きではありません)

48
Martin Hansen

更新:AWS EBには、このための組み込み設定が最終的に含まれています: https://stackoverflow.com/a/51556599/1123355

旧ソリューション:EBインスタンスに飛び込み、評価のためにEBのヘルスチェックデーモンがステータスコードをEBに実際に報告する場所を探すのに数時間を費やしたとき、最終的にそれを発見し、4xx応答コードが環境をDegraded環境の健全性状態に変えるのを防ぎ、無意味に通知するための完璧な回避策として役立つパッチを思い付きました。このメール:

Environment health has transitioned from Ok to Degraded. 59.2 % of the requests are erroring with HTTP 4xx.

ステータスコードレポートロジックは、healthd-appstat内にあります。Ruby常に/var/log/nginx/access.logを監視し、ステータスコードをEBにレポートするEBチームによって開発されたスクリプト次のパス:

/opt/elasticbeanstalk/lib/Ruby/lib/Ruby/gems/2.2.0/gems/healthd-appstat-1.0.1/lib/healthd-appstat/plugin.rb

次の.ebextensionsファイルは、これにパッチを適用しますRubyスクリプトは4xx応答コードのEBへの報告を回避します。これは、EBが4xxエラーは、それらが発生していることを知らないだけであるため、EB環境の[Health]ページには、0応答コードカウントの4xxが常に表示されます。

container_commands:
    01-patch-healthd:
        command: "Sudo /bin/sed -i 's/\\# normalize units to seconds with millisecond resolution/if status \\&\\& status.index(\"4\") == 0 then next end/g' /opt/elasticbeanstalk/lib/Ruby/lib/Ruby/gems/2.2.0/gems/healthd-appstat-1.0.1/lib/healthd-appstat/plugin.rb"
    02-restart-healthd:
        command: "Sudo /usr/bin/kill $(/bin/ps aux | /bin/grep -e '/bin/bash -c healthd' | /usr/bin/awk '{ print $2 }')"
        ignoreErrors: true

はい、少しいですが、少なくともEBチームが何らかの構成パラメーターを介して4xxエラーを無視する方法を提供するまで、仕事は完了します。プロジェクトのルートディレクトリを基準にした次のパスで、デプロイ時にアプリケーションに含めます。

.ebextensions/ignore_4xx.config

幸運を祈ります。これが助けになったら教えてください!

57
Elad Nava

Ignore HTTP 4xx(スクリーンショットが添付されています)という専用のヘルスモニタリングルールのカスタマイズがあります。有効にすると、EBは4xxエラーでインスタンスのヘルスを低下させません。 enter image description here

25
A G

あなたの答えをありがとう Elad Nava 、私は同じ問題を抱えていて、あなたの解決策は私にとって完璧に働いた!

ただし、AWSサポートセンターでチケットを開いた後、Rubyスクリプトを変更する代わりに、ヘルスチェックで4xxを無視するようにnginx構成を変更することを推奨しました。 、デフォルトの.ebextensionsファイルを上書きするために、nginx.confディレクトリに設定ファイルを追加する必要もありました。

files:
  "/tmp/nginx.conf":
    content: |

      # Elastic Beanstalk Managed

      # Elastic Beanstalk managed configuration file
      # Some configuration of nginx can be by placing files in /etc/nginx/conf.d
      # using Configuration Files.
      # http://docs.amazonwebservices.com/elasticbeanstalk/latest/dg/customize-containers.html
      #
      # Modifications of nginx.conf can be performed using container_commands to modify the staged version
      # located in /tmp/deployment/config/etc#nginx#nginx.conf

      # Elastic_Beanstalk
      # For more information on configuration, see:
      #   * Official English Documentation: http://nginx.org/en/docs/
      #   * Official Russian Documentation: http://nginx.org/ru/docs/

      user  nginx;
      worker_processes  auto;

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

      pid        /var/run/nginx.pid;


      worker_rlimit_nofile 1024;

      events {
          worker_connections  1024;
      }

      http {

          ###############################
          # CUSTOM CONFIG TO IGNORE 4xx #
          ###############################

          map $status $loggable {
            ~^[4]  0;
            default 1;
          }

          map $status $modstatus {
            ~^[4]  200;
            default $status;
          }

          #####################
          # END CUSTOM CONFIG #
          #####################

          port_in_redirect off;
          include       /etc/nginx/mime.types;
          default_type  application/octet-stream;


          # This log format was modified to ignore 4xx status codes!
          log_format  main   '$remote_addr - $remote_user [$time_local] "$request" '
                             '$status $body_bytes_sent "$http_referer" '
                             '"$http_user_agent" "$http_x_forwarded_for"';

          access_log  /var/log/nginx/access.log  main;

          log_format healthd '$msec"$uri"'
                             '$modstatus"$request_time"$upstream_response_time"'
                             '$http_x_forwarded_for' if=$loggable;

          sendfile        on;
          include /etc/nginx/conf.d/*.conf;

          keepalive_timeout  1200;

      }

container_commands:
  01_modify_nginx:
    command: cp /tmp/nginx.conf /tmp/deployment/config/#etc#nginx#nginx.conf

このソリューションは非常に冗長ですが、AWS独自のスクリプトに依存しない限り、実装する方が安全であると個人的に考えています。つまり、何らかの理由でAWSがRubyスクリプト(信じられないかもしれませんが、予告なしにスクリプトを変更するのが大好きです)を削除または変更することに決めた場合、 sedを使用した回避策はもう機能しません。

13
Adriano Valente

Adriano Valenteの答え に基づいたソリューションがあります。 $loggableビットを動作させることができませんでしたが、404のロギングをスキップすることは良い解決策のようです。 .conf変数を定義した新しい$modstatusファイルを作成し、healthdログ形式を上書きして、$modstatusの代わりに$statusを使用しました。この変更では、nginxを再起動する必要がありました。これは、Ruby 2.3(Puma))を実行しているElastic Beanstalkの64ビットAmazon Linux 2016.09 v2.3.1で動作しています。

# .ebextensions/nginx.conf

files:
  "/tmp/nginx.conf":
    content: |

      # Custom config to ignore 4xx in the health file only
      map $status $modstatus {
        ~^[4]  200;
        default $status;
      }

container_commands:
  modify_nginx_1:
    command: "cp /tmp/nginx.conf /etc/nginx/conf.d/custom_status.conf"
  modify_nginx_2:
    command: Sudo sed -r -i 's@\$status@$modstatus@' /opt/elasticbeanstalk/support/conf/webapp_healthd.conf
  modify_nginx_3:
    command: Sudo /etc/init.d/nginx restart
1
littleforest

私は最近、あなたと同じように4xxエラーで攻撃されたという同じ問題に遭遇しました。上記の提案を試しましたが、うまくいきませんでした。私はAWSサポートに連絡しましたが、ここに彼らが提案したものがあり、それが私の問題を解決しました。 2つのインスタンスが実行されているElastic Beanstalkアプリケーションがあります。

  1. .ebextensionsというフォルダーを作成します
  2. このフォルダー内で、nginx.configというファイルを作成します(拡張子が.configであることを確認してください。「。conf」は機能しません!)
  3. Dockerコンテナを使用してアプリケーションをデプロイする場合は、この.ebextensionsフォルダーがデプロイメントバンドルに含まれていることを確認してください。私にとっては、バンドルにはフォルダーとDockerrun.aws.jsonが含まれていました

Nginix.configファイルの内容全体は次のとおりです。

files:
  "/etc/nginx/nginx.conf":
    content: |
      # Elastic Beanstalk Nginx Configuration File
      user  nginx;
      worker_processes  auto;

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

      pid        /var/run/nginx.pid;

      events {
          worker_connections  1024;
      }

      http {

          # Custom config
          # HTTP 4xx ignored.
          map $status $loggable {
            ~^[4]  0;
            default 1;
          }

          # Custom config
          # HTTP 4xx ignored.
          map $status $modstatus {
            ~^[4]  200;
            default $status;
          }

          include       /etc/nginx/mime.types;
          default_type  application/octet-stream;

          access_log    /var/log/nginx/access.log;

          log_format  healthd '$msec"$uri"$modstatus"$request_time"$upstream_response_time"$http_x_forwarded_for';

          include       /etc/nginx/conf.d/*.conf;
          include       /etc/nginx/sites-enabled/*;
      }
0
Qing Xia

2018年4月の時点でAWSサポートによって提供されているソリューション:

 files:
  "/tmp/custom-site-nginx.conf":
    mode: "000664"
    owner: root
    group: root
    content: |
       map $http_upgrade $connection_upgrade {
           default        "upgrade";
           ""            "";
       }
       # Elastic Beanstalk Modification(EB_INCLUDE)
       # Custom config
       # HTTP 4xx ignored.
       map $status $loggable {
                ~^[4]  0;
                default 1;
       }


       server {
           listen 80;

         gzip on;
         gzip_comp_level 4;
         gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

           if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") {
               set $year $1;
               set $month $2;
               set $day $3;
               set $hour $4;
           }
           access_log /var/log/nginx/healthd/application.log.$year-$month-$day-$hour healthd if=$loggable;

           access_log    /var/log/nginx/access.log;

           location / {
               proxy_pass            http://docker;
               proxy_http_version    1.1;

               proxy_set_header    Connection            $connection_upgrade;
               proxy_set_header    Upgrade                $http_upgrade;
               proxy_set_header    Host                $Host;
               proxy_set_header    X-Real-IP            $remote_addr;
               proxy_set_header    X-Forwarded-For        $proxy_add_x_forwarded_for;
           }
       }

 container_commands:
   override_beanstalk_nginx:
     command: "mv -f /tmp/custom-site-nginx.conf /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf"
0
Deepak Puthraya

Elad Nava's Answer に基づいて、killの代わりにelasticbeanstalk healthdの制御スクリプトを直接使用する方が良いと思います:

container_commands:
    01-patch-healthd:
        command: "Sudo /bin/sed -i 's/\\# normalize units to seconds with millisecond resolution/if status \\&\\& status.index(\"4\") == 0 then next end/g' /opt/elasticbeanstalk/lib/Ruby/lib/Ruby/gems/2.2.0/gems/healthd-appstat-1.0.1/lib/healthd-appstat/plugin.rb"
    02-restart-healthd:
        command: "Sudo /opt/elasticbeanstalk/bin/healthd-restart"

最後に、この問題を調査するときに、healthとApacheがステータスコードを変更することに気付きました。私もこれをパッチしました:

    03-healthd-logs:
        command: sed -i 's/^LogFormat.*/LogFormat "%{%s}t\\"%U\\"%>s\\"%D\\"%D\\"%{X-Forwarded-For}i" healthd/g' /etc/httpd/conf.d/healthd.conf
0
Vlassios