Elastic Beanstalkで稼働しているアプリケーション(Ruby, Sinatra)をAmazon Linux AMIからAmazon Linux2へ移行

Systems ManagerのメンテナンスウィンドウでAWS-RunPatchBaselineというSSMドキュメントにより、インスタンスにパッチ適用を定期的に実行するようにしていました。 管理している一部のインフラ内にセキュリティチェックを導入したのですが、一部のサーバーのみセキュリティ要件に引っかかり続けている状態が発生しました。理由はOS内の各種ライブラリが最新版になっていないことによるものでした。

これはAmazon Linux AMIを使用し続けており、サポートが終了していることが理由でした。サポートされないパッケージのリンクを確認すると、たしかにいずれもDeprecated Packagesに含まれているものでした。

Amazon Linux AMI は、2020 年 12 月 31 日をもって標準サポートを終了しました。現在、メンテナンスサポート段階にあります。サポートされるパッケージとサポートされないパッケージの詳細なリストはこちらにあります。

アップデートできなかったのは、放置し続けていたため、当然といえば当然ですね。

これらのサーバーはElastic Beanstalkで管理しているものでした。PlatformとしてPuma with Ruby 2.6 running on 64bit Amazon Linuxとして元々稼働していました。これをRuby 2.7 running on 64bit Amazon Linux 2に移行することにしました。

Elastic Beanstalkの公式ドキュメントにはAmazon Linux AMIからAmazon Linux 2に移行するためのガイドが用意されています。

本当は上記ドキュメントを先に読んでおくべきでしたが、先走って以下のように進めていきました。 Sinatraのアプリケーションを動かしていたのですが、単純にPlatformを置き換えて、アプリケーションをzipファイルとして圧縮してデプロイすると、/var/log/eb-engine.logで以下のエラーが発生しました。

2021/09/29 11:53:18.758807 [ERROR] An error occurred during execution of command [app-deploy] - [stage ruby application]. Stop running the command. Error: install dependencies in Gemfile failed with error Command /bin/sh -c bundle config set --local deployment true failed with error exit status 1. Stderr:/opt/rubies/ruby-2.7.4/lib/ruby/site_ruby/2.7.0/rubygems.rb:281:in `find_spec_for_exe': Could not find 'bundler' (1.17.2) required by your /var/app/staging/Gemfile.lock. (Gem::GemNotFoundException)To update to the latest version installed on your system, run `bundle update --bundler`.To install the missing version, run `gem install bundler:1.17.2`        from /opt/rubies/ruby-2.7.4/lib/ruby/site_ruby/2.7.0/rubygems.rb:300:in `activate_bin_path'        from /opt/elasticbeanstalk/.rbenv/versions/2.7.4/bin/bundle:23:in `<main>'

現状のBundlerのバージョンを確認すると以下のようになっていました。

$ bundle --version 
Bundler version 2.1.4

ローカルで以下を実行して新しいGemfile.lockを生成しました。

$ gem install bundler
$ bundle update --bundler
$ bundle install

アップデート後のBundlerのバージョンを確認のようになりました。

$ rbenv exec bundle --version
Bundler version 2.2.28

再度、アプリケーションをzipファイルに固めてアップロードしたところ、Nginxのデフォルトページが表示される状態になりました。

/var/log/puma/puma.logで以下のエラーが繰り返し出ている状況であることを確認しました。

[2105] ! Unable to start worker
[2105] /opt/rubies/ruby-2.7.4/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'
[2105] Early termination of worker
[2107] + Gemfile in context: /var/app/current/Gemfile

調べてみたところ、類似の事例に遭遇している方をこちら(Amazon Linux 2 - Ruby 2.6 - Puma: Early Termination of Workers)でお見かけし、対処方法を参考にしました。

Gemfileに以下を追加。

gem 'puma', '4.3.8'

Procfileを作成し、以下を追記。

web: bundle exec puma -C /opt/elasticbeanstalk/config/private/pumaconf.rb 

Procfileはこちらを参照。

すると、無事一通りの動作確認もできるようになりました。

ここでAmazon Linux 2への移行ガイドが公式ドキュメントにあることを認知し、一読しました。 諸々書いてありますが、.ebextensions/nginxディレクトリに置かれているプロキシの設定ファイルを.platform/nginxディレクトリに移動する必要があります。

そのため、.ebextensions以下にあった以下のようなすべての設定ファイルを削除しました。

  • .ebextensions/nginx/conf.d/00_elastic_beanstalk_proxy.conf
    upstream my_app {
    server unix:///var/run/puma/my_app.sock;
    }
    
    log_format healthd '$msec"$uri"'
                    '$status"$request_time"$upstream_response_time"'
                    '$http_x_forwarded_for';
    
  • .ebextensions/nginx/conf.d/elasticbeanstalk/01_elastic_beanstalk_server.conf
    server_name _ localhost; # need to listen to localhost for worker tier
    
    # Hide server information
    server_tokens off;
    
    # Add secure header
    add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
    add_header Content-Security-Policy "default-src 'none'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; font-src 'self';";
    
    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;
    
    location / {
    proxy_pass http://my_app; # match the name of upstream directive which is defined above
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    
    location /assets {
    alias /var/app/current/public/assets;
    gzip_static on;
    gzip on;
    expires max;
    add_header Cache-Control public;
    }
    
    location /public {
    alias /var/app/current/public;
    gzip_static on;
    gzip on;
    expires max;
    add_header Cache-Control public;
    }
    

代わりに.platform以下にあった不要な設定をこれを機に削除して、以下の設定ファイルを追加しました。

  • .platform/nginx/conf.d/sec_requirement.conf
    # Hide server information
    server_tokens off;
    
    # Add secure header
    add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
    add_header Content-Security-Policy "default-src 'none'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; font-src 'self';";
    

Errors

Creating load balancer named: arn:aws:elasticloadbalancing:ap-northeast-1:012345678901:loadbalancer/app/awseb-AWSEB-XXXXXXXXXXXXX/xxxxxxxxxxxxxxxx failed Reason: The value of 'access_logs.s3.prefix' cannot start or end with '/' (Service: AmazonElasticLoadBalancing; Status Code: 400; Error Code: ValidationError; Request ID: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; Proxy: null)

Elastic BeantalkでELB(ALB)の設定をする際に、アクセスログのパス名の先頭および最後に/を含めてはいけないにも関わらず設定されていて、Beanstalkの環境のセットアップに失敗していました。 そこで編集しようとしても、Environment named **** is in an invalid state for this operation. Must be Ready.というエラーで編集できない状態が発生しました。

そのため、環境を再作成で対応しました。

My Twitter & RSS

Leave a Reply

Your email address will not be published. Required fields are marked *