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

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

Systems Managerのメンテナンスウィンドウで[AWS-RunPatchBaseline](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/patch-manager-about-aws-runpatchbaseline.html)というSSMドキュメントにより、インスタンスにパッチ適用を定期的に実行するようにしていました。\
管理している一部のインフラ内にセキュリティチェックを導入したのですが、一部のサーバーのみセキュリティ要件に引っかかり続けている状態が発生しました。理由はOS内の各種ライブラリが最新版になっていないことによるものでした。

これは[Amazon Linux AMI](https://aws.amazon.com/jp/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に移行するためのガイドが用意されています。

* [Elastic Beanstalk Linux アプリケーションを Amazon Linux 2 に移行する](https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/using-features.migration-al.html)

本当は上記ドキュメントを先に読んでおくべきでしたが、先走って以下のように進めていきました。\
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](https://forums.aws.amazon.com/thread.jspa?messageID=950008)）でお見かけし、対処方法を参考にしました。　

Gemfileに以下を追加。

```
gem 'puma', '4.3.8'
```

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

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

Procfileは[こちら](https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/ruby-platform-procfile.html)を参照。

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

ここで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.`というエラーで編集できない状態が発生しました。

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

* References
  * [aws beanstalk for sinatra app - Could not find 'bundler' (2.0.2) required by your /var/app/ondeck/Gemfile.lock](https://stackoverflow.com/questions/59474609/aws-beanstalk-for-sinatra-app-could-not-find-bundler-2-0-2-required-by-you)
  * [Find \_ spec for \_ exe & # 39; : can & # 39; t find Gem bundler (> = 0. a) with executable bundle (Gem: : : GemNotFoundException)](https://bibibug.com/question/Find__spec_for__exe__39_can__39_t_find_Gem_bundler__0)
  * [AWS: Environment named \*\*\* is in an invalid state for this operation. Must be Ready](https://serverfault.com/questions/720039/aws-environment-named-is-in-an-invalid-state-for-this-operation-must-be-re)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hayashier.gitbook.io/article/aws/beanstalk-migrate-alami-to-alami2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
