こんにちは。毎日 島の整備に忙しい ENECHANGE の gamenechange と申します。今回は AWS Elastic Beanstalk(以下、EB)において、使用される Ruby のバージョンを指定する方法および各方法の特徴について書かせて頂きます。
Rails アプリをデプロイしている前提となります。
準備: EB で使用される Ruby のバージョンを確認する
まず、EB で使用される Ruby のバージョンを確かめてみます。
次のように $ eb ssh
を行ってから RUBY_VERSION
を調べることで Ruby のバージョンを確かめることができます。root
で実行する必要があるので注意しましょう。
$ eb ssh _____ _ _ _ ____ _ _ _ | ____| | __ _ ___| |_(_) ___| __ ) ___ __ _ _ __ ___| |_ __ _| | | __ | _| | |/ _` / __| __| |/ __| _ \ / _ \/ _` | '_ \/ __| __/ _` | | |/ / | |___| | (_| \__ \ |_| | (__| |_) | __/ (_| | | | \__ \ || (_| | | < |_____|_|\__,_|___/\__|_|\___|____/ \___|\__,_|_| |_|___/\__\__,_|_|_|\_\ Amazon Linux AMI $ sudo su # cd /var/app/current # bin/rails console Loading production environment (Rails 6.0.1) irb(main):001:0> RUBY_VERSION => "2.6.4"
EB で用いられる Ruby のバージョンはどこで指定するのか
上記の例では、EB で用いられている Ruby のバージョンは 2.6.4
です。この Ruby のバージョンはどこで指定するのでしょうか。
指定に際しては以下の2つの方法があります。
1. Gemfile 内で指定する
Gemfile
内で ruby '2.6.5'
のように記述すると*1、$ bundle install
を行った際に Gemfile.lock
に Ruby のバージョン情報が記載されます。
Gemfile
source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.5'
Gemfile.lock
RUBY VERSION ruby 2.6.5p114
これらのファイルを含んで EB にデプロイすると、Gemfile
内で記述したバージョンが使用されます。
2. EB の Platform がサポートするバージョンを用いる
1.
では Gemfile
内に Ruby のバージョンを記述することで、EB での Ruby のバージョンを指定しました。一方でこの記述を削除することで、「EB の Platform がサポートする Ruby のバージョン(後述)」を用いることができます。
具体的には、Gemfile
から ruby '2.6.5'
の行を削除し、$ bundle install
をして、EB にデプロイします。すると、EB の Platform がサポートしている Ruby のバージョンが、使用される Ruby のバージョンになります。
どのバージョンの Platform がどのバージョンの Ruby をサポートしているかについては次の公式ドキュメントをご覧ください。
EB へのデプロイが失敗するケース
EB での Ruby のバージョンを指定する方法は上記のとおりです。いずれの方法を用いるにしろ狙いどおりにデプロイが成功すれば問題ないのですが、「1. Gemfile
内で指定する」の場合は特定の状況ではデプロイに失敗します。
どのような状況で失敗するかというと、「デプロイ先の EB の Platform が、Gemfile
に記述した Ruby のバージョンをサポートしていない場合」です。
以下に例を挙げます。Gemfile
内では 2.6.4
を指定しているところ、Platform 側で対応しているバージョンが 2.6.5
のケースです。
$ eb deploy Creating application version archive "XXXXXXXXXX". Uploading XXXXXXXXXX.zip to S3. This may take a while. Upload Complete. 2020-03-26 06:57:15 INFO Environment update is starting. 2020-03-26 06:58:00 INFO Deploying new version to instance(s). + bundle install Your Ruby version is 2.6.5, but your Gemfile specified 2.6.4. 2020-03-26 06:58:17 ERROR Failed to deploy application. ERROR: ServiceError - Failed to deploy application.
それぞれの方法のメリットとデメリット
上記の2つの方法を用いる際のメリットとデメリットを考えてみます。
「1. Gemfile 内で指定する」場合のメリットとデメリット
メリット
「1. Gemfile 内で指定する」場合のメリットは、「指定したバージョンでデプロイされることが保証されること」です。前述のように、EB の Platform 上での Ruby のバージョンと Gemfile での Ruby のバージョンが完全一致しない場合にはデプロイが失敗します。したがって、意図しないバージョンが実行されることがありません。
また、EB の Platform の自動アップデートにもちゃんと失敗してくれますので、その点でも意図しないバージョンが使われることがありません。
デメリット
上記のメリットはデメリットにもなります。つまり、Ruby のバージョンを上げる場合には Gemfile
の記述を変更することはもちろん、EB の Platform も対応している Platform のバージョンにアップグレードする必要があるということです。Gemfile
の記述の変更は容易ですが、Platform のバージョンをアップグレードすることは簡単ではない場合も多いでしょう。
また、環境を作り直した際などに Platform のバージョンが意図せず上がってしまった場合には、バージョンの不一致によりデプロイに失敗することがあります。
「2. EB の Platform がサポートするバージョンを用いる」場合のメリットとデメリット
メリット
「2. EB の Platform がサポートするバージョンを用いる」場合のメリットは、開発者は Ruby のバージョンを意識する必要がない、という点です*2。
デメリット
他方、デメリットは「開発環境と EB 側の環境で Ruby のバージョンが異なる場合がある」ことです。
開発環境で用いる Ruby のバージョンは .ruby-version
で指定すると思います*3。しかし、EB で用いられる Ruby のバージョンは Platform がサポートするバージョンです*4。
開発環境で用いているバージョン*5と EB で使用されるバージョンが異なる場合でも、Gemfile
内で Ruby のバージョンの指定はしていませんので、デプロイに失敗することはありません。その結果、開発環境と EB 側の環境で意図しないバージョンの相違が起きる可能性があります。
一つの例としては、EB の Platform の自動アップデートを有効にしている場合です。Platform の自動アップデートが有効の場合は、Platform がアップデートされた際にサポートする Ruby のバージョンも自動で上がっていきます。そうなったとしてもデプロイは失敗しないため、開発環境とのバージョンの差分が発生している可能性があります*6。差分をなくすためには、適宜 .ruby-version
を更新していく必要があります。
もう一つの相違が起きる例としては、.ruby-version
をアップグレードして開発をする場合です。この場合、アップグレードしたバージョンが EB 側では使われないケースがあります*7。.ruby-version
を書き換えても、EB 側のバージョンには影響がないからです*8。この場合は .ruby-version
のバージョンに合致するように Platform をアップグレードする必要があります。
どちらの方法で Ruby のバージョンを指定すればいいのか
ではどちらの方法で Ruby のバージョンを指定すればいいのでしょうか。結論から言うと、アプリやプロダクトの方針によると思います。
Ruby のバージョンをガッチリと固定して厳格に運用したい場合には「1.」の方法を採ることになるでしょう。ただし、バージョンアップ時のコストがかかりますし、開発者間でのEBの知見の共有も必要でしょう。いざというときにデプロイ自体が成功しない可能性があるということは、少なからず怖いものです。
他方、そこまで厳格に運用する必要性がない場合には「2.」の方法を採ることになるでしょう。.ruby-version
を適宜更新していく必要がありますが、特段の意識をせずに誰でも EB にデプロイすることができます。
ENECHANGE株式会社ではエネルギーの未来を作る仲間を募集しています
ENECHANGE株式会社では、EBの問題からエネルギーの問題まで、幅広く解決をしたいエンジニアを募集しております。詳しくは採用情報のページをご覧ください。
参考: EB にインストールされている Ruby のバージョンを確認する方法
EB にインストールされている Ruby のバージョンを確認するためには、$ eb ssh
をした後に、/opt/rubies
配下を見てみましょう。
$ eb ssh _____ _ _ _ ____ _ _ _ | ____| | __ _ ___| |_(_) ___| __ ) ___ __ _ _ __ ___| |_ __ _| | | __ | _| | |/ _` / __| __| |/ __| _ \ / _ \/ _` | '_ \/ __| __/ _` | | |/ / | |___| | (_| \__ \ |_| | (__| |_) | __/ (_| | | | \__ \ || (_| | | < |_____|_|\__,_|___/\__|_|\___|____/ \___|\__,_|_| |_|___/\__\__,_|_|_|\_\ Amazon Linux AMI $ cd /opt/rubies $ ls -la 合計 40 drwxr-xr-x 10 root root 4096 3月 27 08:31 . drwxr-xr-x 6 root root 4096 3月 27 08:31 .. drwxr-xr-x 6 root root 4096 10月 13 2017 ruby-1.9.3-p551 drwxr-xr-x 6 root root 4096 10月 13 2017 ruby-2.0.0-p648 drwxr-xr-x 6 root root 4096 10月 13 2017 ruby-2.1.10 drwxr-xr-x 6 root root 4096 4月 12 2018 ruby-2.2.10 drwxr-xr-x 6 root root 4096 10月 19 2018 ruby-2.3.8 drwxr-xr-x 6 root root 4096 10月 3 20:39 ruby-2.4.9 drwxr-xr-x 6 root root 4096 10月 3 20:35 ruby-2.5.7 drwxr-xr-x 6 root root 4096 10月 3 20:31 ruby-2.6.5 lrwxrwxrwx 1 root root 22 3月 27 08:31 ruby-current -> /opt/rubies/ruby-2.6.5