AWS(Elastic Beanstalk)にデプロイする(Django編)【続編】

ここまでで Django のチュートリアルで作ったアプリを AWS Elastic Beanstalk を使ってデプロイ(公開)できるようになりました。さらに本格的な運用をするための調整を進めていきます。この内容には、AWS登録後の1年間の無償期間の範囲を超える部分があるため、多少の費用が発生する内容も含まれます。AWS内に “AWS コスト管理” という機能があるので、費用を管理しながら進めてください。

ドメイン名の取得

Djangoアプリにアクセスする際に “http://django-env.xxxx.ap-northeast-1.elasticbeanstalk.com” のように Elastic Beanstalk が機械的に作ったURLを使ってきました。これを本番のサービスで使うような、ドメイン名によるURLに設定します。

ドメイン名は AWS の Route 53 というサービスで購入できます。AWS 以外のドメイン管理会社(レジストラ)で購入・登録して既にドメイン名を持っている場合は、そのドメイン名を AWS Route 53 に移管することもできます。ドメイン名の購入・登録・移管などの手続きは有償です。またドメイン名を維持するためには管理費用(数千円/年ほど)も発生します。Route 53 でのドメイン登録については次のページを参照してください。

新しいドメインの登録 - Amazon Route 53
Amazon Route 53 は、Route 53 で登録したドメインと、他の DNS プロバイダーで登録したドメインで使用できます。DNS プロバイダーに応じて次のいずれかの手順を選択し、Route 53 で新しいドメインを登録して使用...

Route 53 でドメインを登録すると、ドメイン名に対応するホストゾーンがひとつできているはずです。Route 53 のダッシュボードで確認してください。ドメイン名をクリックするとその内容が表示され、レコードが2つ(タイプが NS と SOA のレコード)あれば正常です。ホストゾーンの維持には月あたり少額の費用が発生しますので、ドメインの登録だけで当面利用予定が無い場合はホストゾーンは削除してください。

SSH証明書の発行

“https://” で始まるURLを使うには、AWS Certificate Manager でSSH証明書を発行します。落ち着いて手順をひとつずつ進めてください。”リクエスト” のボタンが何度も出て来ますが、慌てて押してしまうとおかしな状態になってしまいます。

AWS Certificate Manager パブリック証明書 - AWS Certificate Manager
パブリックに信頼できる証明書を ACM からリクエストする方法について説明します。

次のページは画面例が付いていてわかりやすいので参考にしてください。

DNS を使って AWS Certificate Manager の検証を簡単に | Amazon Web Services
Secure Sockets Layer/Transport Layer Security (SSL/TLS)

【重要】ACM(AWS Certificate Manager)の “証明書を一覧” でリクエストした証明書の状態を見ることができます。ステータスが “保留中の検証” になっていたら、時間をおいて上の丸い更新ボタンを押すと状況が更新されます。公式ページには72時間でタイムアウトすると書いてありますが、設定が正しければ普通は5〜10分くらいで検証が終わります。念の為1時間ほど待って、それでもステータスが “発行済み” に変化しなかったら何かおかしい可能性があります。

ステータスが “保留中の検証” から変化しない場合は、証明書をリクエストしたときに “Route 53 でレコードを作成” のボタンを押すという手順を飛ばしてないか再確認してください。ホストゾーンの中には NS と SOA のレコードが最初からありますが、”Route 53 でレコードを作成” のボタンを押すと CNAME というタイプのレコードが追加されているはずです。CNAME のレコードが無ければ手順を間違っています。

それでも検証が終わらない場合は、ホストゾーンの NS レコードに記述された4つのネームサーバーと、登録したドメインに設定されているネームサーバーが一致していることを確認してください。

ホストゾーンを作り直した場合にはネームサーバーが不一致になる可能性があります。登録済みドメインの詳細画面の、ネームサーバーの表示の近くに ”ネームサーバーの追加/編集” というリンクがありますのでここで修正してください。ホストゾーンの方を修正してはいけません。

証明書のステータスが “発行済み” になれば準備OKです。

Djangoアプリとドメイン名を紐付けする

Route 53 を使用してドメイン名へのトラフィックを Elastic Beanstalk にルーティングしてやると、ドメイン名を使ったDjangoアプリへのアクセスが可能になります。その方法は次のドキュメントを参考にしてください。ドメイン名にサブドメインを作ることもこの手順の中で可能です。

AWS Elastic Beanstalk 環境へのトラフィックのルーティング - Amazon Route 53
Route 53 を使用してトラフィックを Elastic Beanstalk 環境にルーティングします。

エイリアスレコードを作成するときの設定画面がわかりにくいので下に画面例を示します。

エイリアスレコード(タイプが “A” のレコード)がホストゾーンに登録されます。設定が反映されるまで数分かかります。ここまで進めば、ドメイン名のURLで動作するはず。ただし、Django プロジェクトの settings.y の ALLOWED_HOSTS にドメイン名を追加するのを忘れないでください。

Elastic Beanstalk の環境ヘルス

さて、このへんで Elastic Beanstalk のダッシュボードで、環境名を選んでその状態を確認してください。エラーがレポートされることがあります。

Elastic Beanstalk のヘルスチェックは対象インスタンスのルート “/” に定期的にアクセスして状態を確認しています。その結果 400(Bad Request) のステータスが返されるとエラーと判断します。ですが、Djangoアプリから 400 が返されるのは正常なので、このヘルスチェックを無効にします。Elastic Beanstalk の環境名の中の “設定” を選んで、カテゴリから “モニタリング” を編集します。ここで “アプリケーション 4xx を無視/有効” をチェックします。適用ボタンを押すと “100.0 % of the requests are erroring with HTTP 4xx.” の方のエラーは無くなります。

まだ Process default has been unhealthy for xxx. のエラーが残っていますので、”設定” のカテゴリから “ロードバランサー” を編集します。プロセスの欄に “default” という項目が登録されているので、これを選択してアクションのプルダウンリストから “編集” を実行します。ヘルスチェックの “HTTPコード/環境内の正常なインスタンスのHTTPステータスコード。” に 400 を入力して保存・適用します。

これでヘルスは正常な状態になるはずです。もしかすると Django の方で 400 を返さないようにする方法があるかもしれませんが調査できていません。

HTTPS を有効にする

次に “https://〜” で動作するように設定を進めます。次のページを参照してください。

Elastic Beanstalk 環境に HTTPS を設定する
ロードバランサーから Amazon Elastic Compute Cloud (Amazon EC2) インスタンスへのデータを暗号化できるように、AWS Elastic Beanstalk 環境に HTTPS を設定したいと考えています...

Elastic Beanstalk で “環境” を選んで “設定” でHTTPSのリスナーを追加するところまで進めてください。ロードバランサの種類によって少し手順が異なります。Application Load Balancer のリスナー追加画面を次に示しておきます。互換性の理由から “SSLポリシー” は “ELBSecurityPolicy-2016-08” が推奨です。

“追加” ボタン、さらに “適用” ボタンを押せば完了です。ロードバランサの設定がこの様になっていればOKです。

以上で “https://〜” で動作するようになったはずなので、実際に動作することを確認してください。

HTTP を HTTPS に転送する(HTTPSの強制)

“https://〜” が動作するようになったら、ユーザー側が “http://〜” でアクセスしてきた場合にも “https://〜” に転送されるようにします。これを “HTTPSの強制” といいます。この設定を行うかどうかはオプションです。

ただし、Elastic Beanstalk の設定で HTTPS を強制する方法は、実はわかっていません。EC2 を直接触って設定する方法が次のページにあります。これは期待通りに動作するのですが、EC2 は Elastic Beanstalk の管理下で動作しているので、EC2 の設定を直接変更してしまうことは懸念事項となります。Elastic Beanstalk 側の変更で設定内容がリセットされてしまうことがあるかもしれません。(無いかもしれません。よくわかっていません。)

Application Load Balancer で HTTP を HTTPS にリダイレクトする
Application Load Balancer のリスナールールを使用して、HTTP リクエストを HTTPS にリダイレクトしたいと考えています。

Application Load Balancer の場合の詳細手順を参考に書いておきます。EC2 のダッシュボードからロードバランサーの設定画面を開き、リスナータブを選ぶと HTTP 80 のリスナーに “ルールの表示/編集” があるのでクリックします。

上の方のペンシルアイコン、ルールの左側に表示されるペンシルアイコンを順にクリックします。

“THEN” のところにある転送先の設定は削除して “アクションの追加” を実行します。

リダイレクト先を HTTPS 443 に設定して更新すれば完了です。

Django アプリの調整

Django プロジェクトの settings.y の ALLOWED_HOSTS に、暫定的に使っていた Elastic Beanstalk の URLが残っていると思います。不正アクセスの可能性を広げてしまうので、ドメイン名でアクセスできるようになったらこれは削除しておきましょう。

コメント