【Laravel & AWS】Elastic BeanstalkでHTTPSに対応する & StorageをEFSに置き換える【3日目】

AWSのサービス縛りでコスト最適で弾力性のあるLaravelアプリケーションのインフラを作ろうという企画の3日目です。
前回はRDBに接続できる様にしてcronでタスクスケジュールが起動される様にしました。
今回は「storageフォルダにシンボリックリンクを作成する」と「storageをEFSに置き換える」「HTTPSに対応する」をやっていきます!
ちなみにやりたい事の一覧は以下の通り(やればやるほど増える不思議🤔)

  • アプリケーションサーバの構築 (1日目)
  • ビルド・デプロイの自動化 (1日目)
  • RDBに接続できる (2日目)
  • cronを使える様にする(Laravelのタスクスケジュールのトリガー) (2日目)
  • HTTPS対応
  • storageフォルダにシンボリックリンクを作成する
  • storageをEFSに置き換える
  • フロントのリソースのビルド(node, npm)に対応
  • テストの自動化
  • アプリケーションサーバのオートスケール&ロードバランシング
  • Redisに接続できる
  • リソースをCDNから配信する
  • RDSのバックアップ/リストア
  • RDSの容量のオートスケール
  • CodePipelineで、承認しないとデプロイされないようにする
  • ビルド完了時のslack通知

storageフォルダにシンボリックリンクを作成する

Laravelアプリケーションは最初にstorageディレクトリに書き込み権限を付与したりpublic/storageからstorage/app/publicシンボリックリンクを作成したりしなければいけない。
これはソースコードに含める事は出来ないのでebextensionsで環境構築時に設定する様にする。
なお、書き込み権限については、CodePipelineがソースコードの所有者をwebappに設定してくれる様なので不要みたい。(セキュリティ的に微妙じゃない?というのは置いといて)

まずは、storageの動作確認をするために画像をアップロード&表示する機能を追加した。
ローカルで表示するとこんな感じ。
画像があると華やかでいいね!🤟

Laravelアプリケーションに画像をアップロード&表示する機能を追加した図

デプロイ時にシンボリックリンクを作成するために、ebextensionsコンテナコマンドを記載してPushする。
コンテナコマンドは、アプリケーションコードに影響するコマンドを記述できる
以下の様に記述した。

container_commands:
    00_laravel_setup:
        command: |
            ln -s ../storage/app/public public/storage

Beanstalk環境で動作確認する。
画像のアップロード&表示が出来たのでシンボリックリンクがちゃんと作成されている事がわかる。

Beanstalk環境で画像アップロード&表示を確認している図

storageをEFSに置き換える

AWS Elastic File System (EFS) Summary - Absolute Zero - Medium
EFSのアイコン

デプロイする度にstorageフォルダが削除されてしまうのは困るので、storageディレクトリをNAS(Elastic File System)に置き換えます
また、アプリケーションサーバを水平スケール(スケールアウト)させた時にアップロードされた画像やセッション情報などを複数サーバで共有できます。
ドキュメントを参考にすすめていく。
まずはEFSのインスタンスを作る

EFSインスタンス一覧画面

ebextensionsにstorage-efs-mountfilesystem.configを追加してデプロイする
デプロイでエラーが発生した。

CodePipelineでデプロイが失敗している状態
Deployment completed, but with errors: Failed to deploy application. Service:AmazonCloudFormation, Message:Template format error: Unresolved resource dependencies [FileSystem] in the Resources block of the template

どうやらstorage-efs-mountfilesystem.configファイルシステムIDを指定する必要があるらしい。
以下の様にFILE_SYSTEM_IDにファイルシステムIDを、MOUNT_DIRECTORYにマウント先のディレクトリを指定した。

option_settings:
  aws:elasticbeanstalk:application:environment:
    FILE_SYSTEM_ID: 'fs-XXXX'
    MOUNT_DIRECTORY: '/efs/storage'

EFSがマウント出来たのでシンボリックリンクの張り方を変更して、storageフォルダへのアクセスをFESへのアクセスにする。

container_commands:
    00_laravel_setup:
        command: |
            rm -rf storage
            ln -s /efs/storage storage
            ln -s /efs/storage/app/public public/storage

ちなみに、MOUNT_DIRECTORYを書き換えた際は、Beanstalk環境を作り直さないとマウントポイントがどんどん増えていってしまう点に注意。
この仕様に気づかなくて/efs/efs/storageに同じEFSインスタンスをマウントしてしまって変な挙動になってハマった。

EFSの料金体系は?

いちおう料金を調べておく。
ストレージの使用容量に応じて課金されるとの事。
標準速度のストレージを10GB使うと400円/月程度。

HTTPSに対応させる

Beanstalkが提供してくれるURLに接続すると「保護されていない通信」、つまりHTTP接続になっているので、HTTPS接続出来るようにする

Route53でドメインを取得する

Route53のドメイン一覧画面

Certificate Managerでサーバ証明書を発行する

AWS Certificate Managerの証明書一覧画面

Beanstalkの「設定」→「容量」から環境タイプを「負荷分散」に変更してロードバランサーを有効化する

Beanstalkの環境タイプを変更している図

「設定」→「ロードバランサー」からリスナーを追加する
リスナー側はHTTPSで暗号化、インスタンス側はHTTP(80)で平文通信にする。

Beanstalkのロードバランサのリスナーの一覧
Beanstalkのロードバランサのリスナーを追加している図

DNSレコードを追加してドメイン名からロードバランサのIPが解決できる様にする
エイリアス先にはロードバランサのインスタンスを指定する。

Route53でAレコードを追加している図

ドメインにアクセスすると画面が表示された。
しかし、「保護されていない通信」になってしまう
証明書は読み込まれているが、httpでリソースにアクセスしている要素があるため保護されないらしい。

chromeでアクセスして保護されていない通信になっている状態

ソースコードを書き換える。
AppServiceProvider.phpURL::forceSchemeを実行して、全てのスキーマをhttpsに固定する。

    public function boot()
    {
        //
        if (App::environment('production')) {
            URL::forceScheme('https');
        }
    }

改めて確認するとHTTPSになった!

chromeで確認してHTTPSになっている状態

今日はここまで!🤙

「【Laravel & AWS】Elastic BeanstalkでHTTPSに対応する & StorageをEFSに置き換える【3日目】」への2件のフィードバック

コメントする