Spring Boot に入門した話〜架空のキャンプ場の予約アプリを Elastic Beanstalk にデプロイするまで〜③デプロイ編

前回の記事「②開発編」の続きです。 今回でこの記事は最後になります。前回と同様、メモみたいな感じですので、よろしくお願いします。

デプロイ

インフラ方針

  • 元々、AWS Elastic Beanstalk を試してみたかったので、今回はそちらにデプロイしています。
  • なるべく手軽に、最小の構成を選択し、可用性は求めません。
  • URLは、DNSを使って名前解決します。
  • HTTPSアクセスを基本とし、HTTPの場合はHTTPSにリダイレクトさせます。

インフラ構成図

  • ロードバランサーの接続先としてAZ-1bを用意していますが、基本的には使用しません。Elastic Beanstalkで作成したロードバランサーは少なくとも2つのAZにまたがる必要があるため用意しています。
  • RDSはElastic Beanstalk上でも作成できますが、アプリケーションを終了させるとRDSも消えてしまいます。DBのライフサイクルはアプリケーションと分けておきたいので、RDSは個別に作成していきます。

Image from Gyazo

Spring Boot側の設定

Elastic Beanstalk用の設定ファイルを用意しておくと便利

application.propertiesをコピーして、application-beanstalk.propertiesというファイルを作成しておきます。こちらにElastic Beanstalk用の設定を書いておけば、環境変数で切り替えることができるので便利です。

APサーバのポートは5000

Elastic Beanstalkで作成した環境では、nginxがリバースプロキシとして稼働しており、APサーバのポート5000に転送しています。APサーバの側のポートを変更するため、application-beanstalk.propertiesに以下の記述を追加します。
参照:Java SE プラットフォームの使用

server.port=5000

Tomcatでリダイレクト時にHTTPSを使用する

Spring Boot で、Tomcatを使用してHTTPS化を行う場合、デフォルトだとリダイレクト時にHTTPアクセスに変わってしまいます。そのため、埋め込みTomcatを例にすると、以下の設定をapplication-beanstalk.propertiesに追加します。
参照:13.3. プロキシサーバーの背後で実行するときに HTTPS を有効にする

server.tomcat.remoteip.remote-ip-header=x-forwarded-for
server.tomcat.remoteip.protocol-header=x-forwarded-proto

DBの初期化スクリプトをオフ

DBとアプリケーションのライフサイクルを切り離すため、DBの初期化スクリプトが流れないように設定を変更します。

spring.sql.init.mode=never

デプロイ手順

デプロイまでの大まかな手順です。今回はマネジメントコンソールを使用しています。「AZ-1a」は適宜お使いのリージョンのものに読み替えてください。また、独自ドメインは、既に取得済みの想定です。
 

EC2のキーペアを作成

  • Elastic Beanstalk環境のEC2に紐付けるキーペアを作成しておきます。すでに作成済みの場合は不要です。

VPC作成

  1. VPCを作成します。
  2. パプリックサブネットをAZ-1aとAZ-1bに一つずつ作成します。
  3. プライベートサブネットをAZ-1aとAZ-1bに一つずつ作成します。
  4. プライベートサブネット用にルートテーブルを作成し、プライベートサブネット2つを関連付けます。こちらはIGWに接続しません。
  5. プライベートサブネットに配置するRDS用にセキュリティグループを作成します。インバウンドにPostgreSQLを追加します。
  6. インターネットゲートウェイを作成し、1のVPCにアタッチします。
  7. パブリックサブネットのルートテーブルにIGWを追加します。

RDS作成

  1. サブネットグループを作成します。プライベートサブネットの2つを関連付けます。
  2. RDSのタイムゾーン設定をUTCから変更するため、パラメータグループを作成します。「パラメータグループファミリー」にpostgresql 13を選択し、グループ名を付けます。
  3. パラメータグループを選択し、「変更」からtimezoneパラメータをAsia/Tokyoに変更します。
  4. データベースを作成します。
    • エンジンはPostgreSQL、バージョンは13.3-R1を選択。
    • DB インスタンスクラスとストレージは最小構成。
    • マルチAZ配置はオフ。
    • VPCに、事前に作成したVPCを選択。
    • サブネットグループに、1で作成したサブネットグループ(AZ-1a側)を選択。
    • パブリックアクセスは、なしを選択。
    • 既存の VPC セキュリティグループに、事前に作成したセキュリティグループを選択。
    • 追加設定を開き、最初のデータベース名を設定。
    • 同じく追加設定より、DB パラメータグループに事前に作成したパラメータグループを選択。

Spring BootのJarファイル作成

  1. application-beanstalk.propertiesのDBデータソース情報をRDSの情報に書き換えます。
  2. Fat Jarを作成します。

Elastic Beanstalk環境作成

環境設定
  • プラットフォームに、Javaを選択。
  • アプリケーションコードは、コードのアップロードを選択し、Jarファイルをアップロード。
  • より多くのオプションの設定を選択し、プリセットを高可用性(スポットインスタンスとオンデマンドインスタンスを使用)を選択。
    • 解説:単一インスタンス環境を選択すると、ロードバランサーを選択することができなくなります。SSLACMを使用して、終端をELBに設定するお手軽コースで済ませたかったので高可用性を選択しています。

【ソフトウェア】

  • S3 ログストレージを有効。
  • ログのストリーミングを有効。
  • 環境プロパティに、名前:SPRING_PROFILES_ACTIVE、値:beanstalkを設定。

【容量】

【セキュリティ】

  • EC2キーペアは、事前に作成したキーペアを選択。

【ネットワーク】

  • VPCは、事前に作成したVPCを選択。
  • ロードバランサーのサブネットは、事前に作成したパブリックサブネット2つを選択。
  • インスタンスの設定の、パブリック IP アドレスをON。
  • インスタンスサブネットは、事前に作成したパブリックサブネット2つを選択。

上記の内容で、一旦アプリケーションを作成します(後ほど変更を加えます)。

PostgreSQLの設定変更

  1. Elastic Beanstalkで作成したEC2に、秘密鍵を使用してsshで乗り込みます。
  2. sudo yum -y install postgresql.x86_64を実行します。
  3. psqlコマンドでRDSのPostgreSQLに接続します。
    • psql -h エンドポイント -p 5432 -U ユーザ名 -d postgres
  4. \lを実行し、RDSの作成時に指定した「最初のデータベース」のCollateCtypeの値が、en_US.UTF-8になっていることを確認します。
  5. 「最初のデータベース」を削除します。
  6. create database 最初のデータベース名 with template template0 encoding 'utf8' lc_collate 'c' lc_ctype 'c';を実行し、データベースを作り直します。
  7. schema.sqldata.sql(マスタデータのみ)を実行します。

Route 53 設定

  1. ホストゾーンを作成します。
  2. NS レコードの値を、ドメイン登録事業者側で設定します。
  3. レコードを作成します。

Certificate Managerの設定

  1. 証明書をリクエストします。
    • 検証方法は、DNSの検証を選択。

完了すると、Route 53 のホストゾーンにCNAMEレコードが追加されます。

Elastic Beanstalk環境の設定変更

  1. ロードバランサーにリスナーを追加します。
    • ポートは、443を設定。
    • プロトコルは、HTTPSを選択。
    • SSL 証明書はACMの作成した証明書を選択。
    • SSL ポリシーは、ELBSecurityPolicy-2016-08を選択。

ロードバランサーの設定

  1. リスナーのHTTP:80のルールを編集します。
    • ルールを追加し、条件:パスが* リダイレクト先:HTTPS: 443 を設定します。
       

以上でデプロイ完了です。