はじめに
こんにちは、nayaaaa です。
最近お試しでEKS上にRailsアプリとNginxをデプロイしてみました。その際にいくつかハマりポイントがあったので、備忘録も兼ねてまとめます。
ハマった箇所
- VPCルートテーブルがブラックホール状態になっていた
- 本番環境では
credentials
の設定が必須だった -
assets:precompile
を忘れて500
エラーが出た
VPCルートテーブルがブラックホール状態
最初にハマったのは、VPCルートテーブルの「ブラックホール」状態です。
AWS では、ルートのターゲットに指定したリソース(IGW, NATGatewayなど)が削除されたり到達不能になると、そのルートが「ブラックホール」と表示されます。今回はおそらく以下のいずれかが原因でした。
- VPC にまだアタッチしていない IGW を選んでしまった
- 別の VPC 用 IGW を誤ってターゲットに設定した
この状態になると当然ながら外部通信ができず、Podが外部にアクセスできません。
■参考リンク
本番環境はcredentialsが必須
次にハマったのがRailsのcredentials
設定です。
開発環境では特に気にせずともアプリが動いていましたが、本番環境では必ず config/master.key
とconfig/credentials.yml.enc
のセットが必要になります。これがないとRailsが秘密情報を読み込めず、データベースの接続に失敗します。
以下の手順で対応しました。
# master.keyを生成(ない場合)
openssl rand -hex 16 > config/master.key
chmod 600 config/master.key
# credentialsを編集
EDITOR="vim" bin/rails credentials:edit
これでconfig/credentials.yml.enc
が生成され、config/master.key
で復号できるようになります。本番環境ではcredentialsのDBパスワードやsecret_key_baseを設定することでDBへの接続を行います。
Kubernetes上ではSecretとして管理し、Pod起動時にマウントするか環境変数で注入することが必要です。
■ 参考リンク
assets:precompileを忘れて500エラー
最後にハマったのはassets:precompile
の実行忘れです。
Railsではconfig.assets.compile
のデフォルト値が環境によって異なります。
development: true
→ リクエスト時に必要に応じてコンパイル
production: false
→ 事前にコンパイル済みのファイルを参照
そのため、本番環境で事前のコンパイルを忘れると、Nginx経由でリクエストが来た際に500エラーを返してしまいます。Ingress → Service → Podのリクエストまでは動いていても、最終的にRailsが静的アセットを返せず落ちる、という状態です。
解決策は、CI/CD
やDockerfile
の中で以下を実行しておくことです。
RAILS_ENV=production bin/rails assets:precompile
これを入れないと、Podを起動/再起動してもエラーが続きます。EKS上でRailsを本番環境で動かす際はほぼ必須の設定です。
■ 参考リンク
まとめ
今回、EKS上でRailsとNginxを動かすにあたり、
VPCのルートテーブルがブラックホール状態であったり、Rails特有の本番設定(credentials, assets:precompile)という両方にハマりました。
開発環境では気づかない部分が、本番環境で試してみると色々あるのだなと実感しました。
以上、ありがとうございました!!