メモ > サーバ > サービス: AWS > ロードバランサー
ロードバランサー
※ロードバランサーを作成できる。
ロードバランサーってなんやねん
https://zenn.dev/mi_01_24fu/articles/load-balancer_2024_07_13
※以前は「標準ロードバランサー」のみだったが、後から「Application Load Balancer」が追加された。
「標準ロードバランサー」は現在は「Classic Load Balancer」と呼ばれている。
「Application Load Balancer」は「L7のルーティング」「HTTP2対応」「WebSocketのサポート」など、色々と強化されている。
今新規にロードバランサーを作成する場合、「Application Load Balancer」を選択すればいい。
AWS Application Load Balancer のフロントエンド機能が凄すぎる件 | あぱーブログ
https://blog.apar.jp/web/6603/
「Application Load Balancer」に移行したからと言って、コストが跳ね上がることは無さそう。むしろ安くなるかも。
計算方法自体が変わるので要確認。(ELBはデータ転送量に対して課金、ALBは帯域幅に対して課金。)
[AWS]CLBからALBへ移行してコストを安くする[ELB] | Developers.IO
https://dev.classmethod.jp/cloud/clb-to-alb/
※さらに後から「Network Load Balancer」が追加された。
ELBは秒間2,000アクセスがいったんの限界だったが、NLBは秒間数百万リクエストに簡単に対応できるらしい。
(東京リージョンでも使えるようになっている。)
固定IPありとか送信元IPアドレスの保持とか暖機運転不要とか、少し見た限りではとても良さそう。
SSLアクセラレーションがない、セキュリティグループの扱いが異なるなど、ALBに置き換わるものでは無いみたいが、CLBは不要になりそう。
https://dev.classmethod.jp/cloud/aws/elb-network-load-balancer-static-ip-adress/
実際に導入する場合、SSLで何か問題がないかなど要確認。
https://aws.amazon.com/jp/blogs/news/new-network-load-balancer-effortless-scaling-to-millions-of-req...
EC2 → ロードバランサー → ロードバランサーの作成 → Application Load Balancer
1. ロードバランサーの設定
名前: Develop
VPC: (配置したい場所に応じて選択する。)
アベイラビリティゾーン: (AZが異なる複数のサブネットを選択する。基本的に、Webサーバ用のすべてのサブネットを選択すればいい。)
2. セキュリティ設定の構成
必要に応じて設定する。
3. セキュリティグループの割り当て
必要に応じて、あらかじめ設定しておいた Security Group を選択。
4. ルーティングの設定
適当な名前を設定する。
5. ターゲットの登録
ロードバランサーから処理を振り分けるEC2インスタンスを選択。(Web1とWeb2、など。)
6. 確認
内容を確認して、問題なければ作成。
EC2 → ロードバランサー → に、作成したロードバランサーが表示される。
DNS Name でアクセスできるようになるので、セッションやデータベースを共有できているか確認する。
(アクセスできるようになるまで数分かかる。)
Application Load Balancer の場合、追加したインスタンスの状態は
「EC2 → ターゲットグループ」
から確認できる。
以下のようにして、ロードバランサー経由でWebサーバにアクセスできる
http://develop-123456789.ap-northeast-1.elb.amazonaws.com/
http://develop-123456789.ap-northeast-1.elb.amazonaws.com/pdo_mysql.php
Webサーバ1とWebサーバ2にセッションを扱うプログラムをテスト設置する
http://ec2-203-0-113-0.ap-northeast-1.compute.amazonaws.com/session.php
http://ec2-203-0-113-1.ap-northeast-1.compute.amazonaws.com/session.php
それぞれに、ロードバランサーを経由してアクセスする
http://develop-123456789.ap-northeast-1.elb.amazonaws.com/session.php
ELBでスケールアウトする
http://www.atmarkit.co.jp/ait/articles/1407/15/news006.html
ELB配下のEC2アクセスログについてあれこれ
http://dev.classmethod.jp/etc/elb-ec2-log-x-forwarded-for/
Elastic Load Balancerの配下にApacheをぶら下げたときのログ設定
http://qiita.com/skyriser/items/a5461c726a1030ac0aa1
■プレウォーミング
もっとELB(Elastic Load Balancing)を活用する
http://dev.classmethod.jp/cloud/aws/more-elb/
> まずゆるやかにトラフィックが変化する場合ですが、これはELBが得意とするパターンなので、特段の考慮事項は必要ありません。
> 対してピーク性の高いトラフィックを想定した負荷試験は、予めELBを最大規模に合わせてpre-warmしておく必要があります。
大量同時アクセスに備えて ELB を Pre-warming 状態にしておく
http://im-sei.tumblr.com/post/71162021812/%E5%A4%A7%E9%87%8F%E5%90%8C%E6%99%82%E3%82%A2%E3%82%AF%E3%...
> 自分が試した限りでは、HTTPリクエストは 2000 req/s くらいしか捌けませんでした。
> また、転送量も 800 Mbps (100 MB/sec) くらいしか稼げませんでした。
> AWS のビジネス以上のサポートプランに入ることで、ELB を Pre-warming (暖機) 状態にしておくサポートが受けられるようになります。
同時大量アクセスに備えて ELB を Pre-warming 状態にしておく
http://blog.uniba.jp/post/71165745511/%E5%90%8C%E6%99%82%E5%A4%A7%E9%87%8F%E3%82%A2%E3%82%AF%E3%82%B...
> 転送量にもよりますが、ざっくり目安で 1500 ~ 3000 req/s くらいしか捌けません。
> また、公式のドキュメントによると、スケールするのに 1〜7 分かかるらしく、これまたざっくりしています。
Pre-warming した複数の ELB を Route 53 で DNS ラウンドロビンする
http://im-sei.tumblr.com/post/73601591352/pre-warming-%E3%81%97%E3%81%9F%E8%A4%87%E6%95%B0%E3%81%AE-...
「大量同時アクセスに備えて ELB を Pre-warming 状態にしておく」を参照すると
「リクエスト数 5 万 req/s、スループット 160 Mbps」で申請できたらしい。
これでも足りない場合、Route53でDNSラウンドロビンを設定して、複数のELBにトラフィックを分散するという手がある。
また、SSL証明書設定時にELBが止まったり…はあるので、マネージドサービスとは言え可用性の向上として有効かも。
ELBの暖機運転申請
http://qiita.com/Yuki_BB3/items/d7ad81cc238b23e6fce9
アクセス数が予測できない場合は、「ELBに参加しているインスタンスの能力いっぱいまで」という依頼を行うことも可能です。
http://www.atmarkit.co.jp/ait/articles/1407/15/news006.html
AWS ALBの運用豆知識
http://blog.father.gedow.net/2017/07/19/aws-alb-knowledge/
■アクセス元IP
初期設定では、Webサーバーに記録されるアクセス元IPアドレスは、ロードバランサーのものになるので注意。
(アクセス元をログに記録するには httpd.conf の編集が必要。
PHPからは HTTP_X_FORWARDED_FOR でアクセス元のIPアドレスを取得できる。)
/etc/httpd/conf/httpd.conf で
LogFormat "%h %l %u %t \"%!414r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
のように設定している箇所を以下のように変更。
(「リクエスト処理時間」「本来のアクセス元IP」「プロトコル」を記録。)
LogFormat "%h %l %u %t \"%!414r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D %{X-Forwarded-For}i %{X-Forwarded-Proto}i" combined
■Basic認証
Basic認証を使用する場合、ロードバランサーからアクセスできるようにする必要があるので注意。
ヘルスチェック用のファイルを、Basic認証の対象外にするなどの作業が必要になる。
もしくは、以下のようにALBとLambdaでBasic認証をかけるという方法もある。
ALB + Lambdaでお手軽3分ベーシック認証 - Qiita
https://qiita.com/shonansurvivors/items/422924e720eb3465b865
※HTTPとHTTPSの両方でアクセスされる可能性があるサイトの場合、
ALBのリスナー設定でHTTPとHTTPSの両方に設定する必要があるので注意。
以下、実際にBasic認証の設定を試したときのメモ。
ただし現在はランタイムが「Node.js 18.x」になる都合上、Lambda関数のコードを若干変更している。(詳細は後述。)
Lambda → 関数 → 関数の作成
関数名: BasicAuth
ランタイム: Node.js 18.x
実行ロール: 基本的なLambdaアクセス権限で新しいロールを作成
「関数の作成」ボタンをクリック。
index.mjsに以下を入力。(ロードバランサーにALBを使っていても、ユーザーエージェントは以下のままでいい。)
export const handler = async(event, context) => {
const headers = event.headers || {};
// ALB Health check
if (headers['user-agent'] === 'ELB-HealthChecker/2.0') {
return {
statusCode: 200,
statusDescription: '200 OK',
isBase64Encoded: false,
headers: {
'Content-Type': 'text/html'
}
};
}
return {
statusCode: 401,
statusDescription: '401 Unauthorized',
body: 'Authorization Required',
isBase64Encoded: false,
headers: {
'WWW-Authenticate': 'Basic',
'Content-Type': 'text/html'
}
};
};
なお参考までに、デフォルトでは以下が入力されていた。
export const handler = async(event) => {
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
古い解説では以下のようなコードになっているかもしれないが、これは古い書き方のようなので注意。(関数がエラーになる。)
exports.handler = async (event, context) => {
// 略
};
ページ中ほどにある「Deploy」ボタンをクリック。
EC2 → ターゲットグループ → Create target group
Choose a target type: Lambda function
Target group name: basic-auth
Health checks Enable: On
Health check path: /
「Next」ボタンをクリック。
Lambda function: BasicAuth(先ほど作成したものを選択。)
Version: $LATEST
「Create target group」ボタンをクリック。
以下のとおり、Basic認証のユーザ名とパスワードをBase64エンコードしたものを用意しておく。
$ echo -n 'refirio:staging' | base64
cmVmaXJpbzpzdGFnaW5n
EC2 → ロードバランサー → Refirio-Staging-ALB → Listeners → HTTP:80 → Rules → Manage rules
画面上部の「+」をクリック。
「ルールの挿入」をクリック。
IF: HTTPヘッダー...
Specify header type...: Authorization
値: Basic cmVmaXJpbzpzdGFnaW5n (「Basic 」に続けて、先ほど作成したものを入力。)
THEN: 転送先
ターゲットグループ: Refirio-Staging-ALB-TargetGroup
画面上部の「保存」ボタンをクリック。
画面上部のペンアイコンをクリック。
最後のルールの左側に表示されているペンアイコンをクリック。
「THEN」に表示されているペンアイコンをクリック。
転送先として先ほど作成したターゲットグループ(basic-auth)を選択。
画面上部の「更新」ボタンをクリック。
ブラウザからロードバランサーにアクセスし、Basic認証の動作を確認する。
■Basic認証(特定のユーザーエージェントなら素通りさせる)
「ChromiumからのアクセスならBasic認証を素通り」とする方法。
「HTTPS:80」「HTTPS:443」の両方に対して、以下のルールを追加する。(「HTTPS:443」だけでもいいかもしれない。)
なお既存のルールを編集して追加すると「AおよびB」という設定になり、両方のルールを満たす必要があるので注意。
・ルールで「HTTPヘッダー」「User-Agent」「*HeadlessChrome*」を設定。
・ターゲットグループで「Refirio-Staging-ALB-TargetGroup に転送」を設定。
・優先度で「3」を設定。(状況に合わせて設定する。)
外部のサーバから、以下のリクエストを送ってアクセスできることを確認できる。
$ curl -H "User-Agent: HeadlessChrome" https://test.refirio.net/
■ヘルスチェックのログ
初期設定では、ヘルスチェックのログが大量に記録される。
Apacheの場合、httpd.confで
SetEnvIf Remote_Addr 127.0.0.1 no_log
このように設定している箇所の後に以下を追加する。
(ELBからのヘルスチェックをログに記録しない。)
SetEnvIf User-Agent "ELB-HealthChecker" no_log
Route53も含めて以下で除外すると良さそう。
SetEnvIf User-Agent "ELB-HealthChecker" no_log
SetEnvIf User-Agent "Amazon Route 53 Health Check Service" no_log
nginxの場合、nginx.confで以下のような設定を追加する。(ファイル名は環境に合わせる。)
location = /health_check.html {
access_log off;
break;
}
ELBのヘルスチェックログを出力しない | technote
http://tech.withsin.net/2016/11/16/elb-healthcheck-nginx/
もしくは以下のような対応も有効。余計なファイルを作らない分スマートか。
http {
〜 略 〜
map $http_user_agent $loggable {
~ELB-HealthChecker 0;
default 1;
}
access_log /var/log/nginx/access.log main if=$loggable;
〜 略 〜
}
Nginx で ELB のヘルスチェックのログを出力させない - 長生村本郷Engineers'Blog
https://kenzo0107.github.io/2021/05/19/2021-05-20-nginx-no-logging-at-elb-healthcheck/
NginxでAWS ELBのHealth Checkログを出力させない方法 - Qiita
https://qiita.com/homoluctus/items/7f81ef8e7d23f3c18ffe
NginxのアクセスログからELBのヘルスチェックを除外する方法 - Qiita
https://qiita.com/masa1246/items/a79051a280ee2a6734c4
■アクセスログの有効化
ロードバランサーへのアクセスログをS3に保存する。
ロードバランサーを選択し、「説明 → 属性 → アクセスログ → アクセスログの設定」で
・アクセスログの有効化
・間隔:5分
・s3の場所:s3://refirio-log/alb-logs
として保存する。
■ドメイン割り当て前のアクセステスト
AWSのロードバランサーは負荷状況によってインスタンス数が増えるため、固定IPアドレスを持たない。
よって、Windowsのhostsファイルを編集するなどしてロードバランサーにアクセスしたい場合、その時点のIPアドレスを調べる必要がある。
例えばロードバランサーのURLが
develop-123456789.ap-northeast-1.elb.amazonaws.com
でブラウザから
http://develop-123456789.ap-northeast-1.elb.amazonaws.com/
でアクセスできる場合、nslookupコマンドを使って以下のようにすればロードバランサーのIPアドレスを調べることができる。(digコマンドでも可。)
$ nslookup develop-123456789.ap-northeast-1.elb.amazonaws.com
Server: 172.31.0.2
Address: 172.31.0.2#53
Non-authoritative answer:
Name: develop-123456789.ap-northeast-1.elb.amazonaws.com
Address: 203.0.113.1
Name: develop-123456789.ap-northeast-1.elb.amazonaws.com
Address: 203.0.113.2
この場合、ロードバランサーは 203.0.113.1 と 203.0.113.2 のIPアドレスを持つ。
よって、Windowsのhostsファイルなどで
C:/windows/System32/drivers/etc/hosts
203.0.113.1 refirio.net
このように設定すると、http://refirio.net/ でアクセスしたときにロードバランサー経由でアクセスできる。
(203.0.113.1 と 203.0.113.2 のどちらを指定してもいい。)
■SSLに対応させる
※無料SSL証明書を実際に試したときのメモは「Certificate Manager」を参照。
※購入した証明書を使用する場合も、いったんACM(AWS Certificate Manager)に証明書をインポートしてから適用する方が良さそう。
(ロードバランサーに直接登録すると、何故かエラーになることが多い。何度か試すと成功するが心臓に悪い。)
詳細は、このファイル内の「Certificate Manager」内の「証明書のインポート」を参照。
※SSLを有効にすると、「HTTP/2」を無効にしないとiOSでロードバランサーにアクセスできなくなる。
詳細はこのファイルの「iPhoneでAWSのロードバランサーにSSLでアクセスできない場合」を参照。
ELBでは、EC2ではなくロードバランサーに対して証明書の設定を行う。
443ポートでアクセスするので、まずはロードバランサーのセキュリティグループで443ポートへのアクセスを許可しておく。
「EC2」 → 「セキュリティグループ」 → 設定したいセキュリティグループを選択して「インバウンド」から設定。
設定できたら引き続き、ロードバランサーにSSL証明書を登録する。
「EC2」 → 「ロードバランサー」 → 設定したいロードバランサーを選択して「リスナーの編集」。
「HTTPS」を追加。
ロードバランサーのプロトコル : HTTPS
ロードバランサーのポート : 443
インスタンスのプロトコル : HTTPS
インスタンスのポート : 80
※ポートは「443→80」なので、Webサーバ自体にSSL証明書は不要ただし.htaccessやPHPなどでSSLの判定ができないので注意。
「443→443」にする場合、Webサーバ自体に証明書の設定などが必要になると思われるので、特に理由がなければ「443→80」でいい。
と設定する。さらに「SSL証明書」列の「変更」を選択。
証明書タイプ : 新規のSSL証明書をアップロードする
証明書名 : refirio.net-20161224
プライベートキー : 秘密鍵
証明書本文 : 証明書 SHA256
証明書チェーン : 中間CA証明書
※一度設定しようとするとエラーになった。
エラー内容は以下のとおり。
既存のリスナーを更新しています
既存のポートのポリシーを取得します: 443。
ポートのリスナーを削除しました: 443。
次の SSL 証明書を作成しました: refirio.net-20170410。
ポートのリスナーを作成できませんでした: 443。 Server Certificate not found for the key: arn:aws:iam::580506097674:server-certificate/refirio.net-20170410
ロールバックしています
SSL 証明書をロールバックできませんでしたarn:aws:iam::580506097674:server-certificate/refirio.net-20170410: The specified value for serverCertificateName is invalid. It must contain only alphanumeric characters and/or the following: +=,.@_-
ロールバックが失敗しました
リスナーの変更をロールバックしようとしてエラーが発生しました。ロードバランサーが不整合な状態である可能性があります。
この時点で、サイトにSSL経由でアクセスできなくなった。
再度はじめから行うと、今度は以下のエラーが表示された。
SSL 証明書を作成できませんでした: refirio.net-20170410. The Server Certificate with name refirio.net-20170410 already exists.
リスナーの更新が失敗しました。
変更は正常にロールバックされました。
ページ全体を再読み込みし、再度「リスナーの編集」で「SSL証明書」列の「変更」を選択すると、先ほどアップロードした証明書を選択できるようになった。
選択して「保存」すると、SSL経由でアクセスできるようになった。
証明書をアップロードしてから実際に使えるようになるまで、若干のタイムラグがあるとか?証明書登録後、5分程度時間を置いてから証明書を選択するとどうか。
右クリックで「リスナーの編集」ではなく、ロードバランサーを選択して画面下の「リスナー」から設定するといいとか?
2019年5月時点でも上記の問題が発生するが、原因は特定できていない。
【初心者向け】ELBにSSL証明書をインストールする
http://dev.classmethod.jp/cloud/aws/aws-beginner-elb-ssl/
AWSのELBでSSLの証明書を設定する方法(2015年5月版)
http://liginc.co.jp/web/programming/server/164756
どうやら現時点では、コマンドラインからでないと確実に更新できないみたい?
それでも何度も試すとできることがあるのは謎。
既存の ELB に SSL 証明書を追加しようとすると Server Certificate not found for the key というエラーになる件の解決方法
http://qiita.com/ynii/items/694d60614b98f73f780f
ELBに証明書を登録できない時はAWS CLIを試す
https://saku.io/use-aws-cli-to-upload-certs-on-elb/
■複数ドメインのSSL証明書を扱う
ALBは対応可、ELBは対応不可…みたい。
ALBでの複数証明書は今は対応しているが、設定反映には若干のタイムラグがあるかもしれない。(10〜20分程度反映されないことがあったが、他の要因の可能性もある。)
ALBで複数SSL証明書 - ナレコムAWSレシピ
https://recipe.kc-cloud.jp/archives/10771
ALBで複数のSSL/TLS証明書を設定できるSNIに対応しました | Developers.IO
https://dev.classmethod.jp/articles/alb-support-sni/
Application Load BalancerがSNIを利用した複数のTLS証明書のスマートセレクションをサポートしました | Amazon Web Services ブログ
https://aws.amazon.com/jp/blogs/news/new-application-load-balancer-sni/
ACM を使用して ELB に複数ドメインの証明書をアップロードする
https://aws.amazon.com/jp/premiumsupport/knowledge-center/acm-add-domain-certificates-elb/
複数ドメインのSSL証明書を1つのELB上で扱えますか?
https://forums.aws.amazon.com/thread.jspa?threadID=239338
複数の証明書を1つのELB上で扱うことはできない。ワイルドカードの証明書を使うなどする必要がある
■iPhoneでAWSのロードバランサーにSSLでアクセスできない場合
ALBにてSSLを有効にすると、iOS・macOSでのみ一部画像が読み込めなかったりそもそもページが表示されなかったりする。
Apache から出力された Upgrade header がプロキシ経由でブラウザに届くと、失敗したりコネクションを破棄したりしてしまうらしい。
解決方法としては、Upgrade header を送らないようにすればいい。
EC2 → ロードバランサー → ロードバランサーを選択
説明タブの「属性」で「HTTP/2」が有効になっていたら無効にする。
AWS(Amazon Web Services) - iPhoneでAWS上のサイトが見れない|teratail
https://teratail.com/questions/163592
AWSで構築したWebサイトがiPhoneで開けないときに試すこと - Qiita
https://qiita.com/lmatsul/items/b221455b3fd31ac1cc3b
iOS 11, macOS Hight Sierra で The operation couldn't be completed. Protocol error が出る場合の対処 - Qiita
https://qiita.com/ameyamashiro/items/8d4be0f11ffe12472052
■複数のSSL証明書を設定する
Etcetera.txt の「1サーバに複数のSSL証明書を設定する」を参照。
■SSLにリダイレクトさせる(CloudFront)
このファイルの「CloudFront」の「SSLにリダイレクトさせる」を参照。
■SSLにリダイレクトさせる(ALB)
今はALBだけでSSLの強制ができる。
リダイレクトループなどに悩まされることも無いので、この方法で設定するのが無難そう。
EC2 → ロードバランサー → ロードバランサーを選択 → リスナー
「HTTP: 80」の「ルールの表示/編集」。
「+」をクリックし、表示された「ルールの挿入」をクリック。
「IF」で「パス」を選択して「*」を入力。
「THEN」で「リダイレクト先」を選択して「HTTPS」「443」「デフォルトホスト、パス、クエリを使用」「301 - 完全に移動しました」を選択。
ひととおり設定したら、画面上部の「保存」をクリックする。
すぐにリダイレクトが反映された。
$ curl -I http://refirio.net/
HTTP/1.1 200 OK
Date: Mon, 15 Apr 2019 02:15:54 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Server: Apache/2.4.37 ()
X-Powered-By: PHP/7.1.25
Upgrade: h2,h2c
$ curl -I http://refirio.net/
HTTP/1.1 301 Moved Permanently
Server: awselb/2.0
Date: Mon, 15 Apr 2019 02:17:50 GMT
Content-Type: text/html
Content-Length: 150
Connection: keep-alive
Location: https://refirio.net:443/
[新機能]Webサーバでの実装不要!ALBだけでリダイレクト出来るようになりました! | DevelopersIO
https://dev.classmethod.jp/cloud/aws/alb-redirects/
■SSLにリダイレクトさせる(Apache)
一台構成のサーバなら、以下のような .htaccess で対応できる。
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
ただしELBを使う場合、上記の方法ではリダイレクトループになる。
代わりに、以下のような .htaccess で対応できる。
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Port} !^443$
RewriteCond %{HTTP_USER_AGENT} !^ELB-HealthChecker
RewriteCond %{REQUEST_URI} !=/server-status
RewriteCond %{HTTP:X-FORWARDED-FOR} !^$
RewriteRule ^(.*)?$ https://%{HTTP_HOST}$1 [R=301,L]
ELB配下のApacheで外部はHTTPSにリダイレクトし、内部のサーバのみHTTPで通信させる - Qiita
https://qiita.com/wapa5pow/items/a5c4fc188e5da0ddde1d
AWS EC2で常時SSLを実現する際の注意点 - Qiita
https://qiita.com/michimani/items/88973c5e2ae76a8e84aa
AWSのELBとNginxでhttpアクセスをhttpsにリダイレクトしたい - Qiita
https://qiita.com/snoguchi/items/f5ccb67592f87942480d
■SSLにリダイレクトさせる(nginx)
一台構成のサーバなら、nginxの設定ファイルに以下のような設定を追加して対応できる。
# vi /etc/nginx/nginx.conf
nginx で http でのアクセスを https にリダイレクト - Qiita
https://qiita.com/kga/items/e30d668ec1ac5e30025b
ELBを使う場合、nginxの設定ファイルに以下のような設定を追加して対応できる。
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443;
ssl on;
# ...
}
# vi /etc/nginx/nginx.conf
ELBを使用してHTTPトラフィックをHTTPSにリダイレクトする
https://aws.amazon.com/jp/premiumsupport/knowledge-center/redirect-http-https-elb/
■外部サイトにリダイレクトさせる
EC2側で行わなくても、ALBだけで別ドメインや別ディレクトリにリダイレクトできる。
ロードバランサーはマネージドサービスなので、サーバの死活監視などが不要な分使い勝手が良さそう。
以下は www.refirio.net にアクセスされたときに、refirio.net へリダイレクトさせる例。
EC2 → ロードバランサー → ロードバランサーを選択 → リスナー
「HTTP: 443」の「ルールの表示/編集」。
「+」をクリックし、表示された「ルールの挿入」をクリック。
「IF」で「ホストヘッダー」を選択して「www.refirio.net」を入力。
「THEN」で「リダイレクト先」を選択して「HTTPS」「443」「カスタムホスト、パス、クエリを使用」を選択。
「ホスト」に「refirio.net」を入力。「パス」と「クエリ」は変更せず。
「301 - 完全に移動しました」を選択。
ひととおり設定したら、画面上部の「保存」をクリックする。
すぐにリダイレクトが反映された。
[新機能]Webサーバでの実装不要!ALBだけでリダイレクト出来るようになりました! | Developers.IO
https://dev.classmethod.jp/articles/alb-redirects/
[AWS]ALBだけで別ドメインにリダイレクトする - ADACHIN SERVER LABO
https://blog.adachin.me/archives/10697
ALBでwwwなし→wwwありへのリダイレクトを設定する - ハマログ
https://blog.e2info.co.jp/2020/06/13/alb%E3%81%A7http%E2%86%92https%E3%81%B8%E3%81%AE%E3%83%AA%E3%83...
【AWS】ALBのリスナールールでリダイレクトを設定する - ポンコツ.log
https://www.ponkotsu-log.com/entry/2019/04/27/012155
■外部サイトにリダイレクトさせる(詳細検証)
色々な設定を試した際のメモ。
具体的には、refirio.net において以下のような設定を試す。
・/redirect_to/ にアクセスしたら https://www.example.com/ にリダイレクト。
・/redirect_to/net/ 配下にアクセスしたら https://www.example.net/ にリダイレクト。
・/redirect_to/org/ 配下にアクセスしたら https://www.example.org/ にリダイレクト。
「EC2 → ロードバランサー → (対象のロードバランサー) → リスナーとルール」で「HTTPS:443」にある「1 のルール」をクリックする。
今回は、以下のルールのみが登録されていることを確認できた。
優先度: 最後 (デフォルト)
名前タグ: デフォルト
条件 (If): 他のルールが適用されない場合
アクション (その時): ターゲットグループへ転送(Develop-ALB-TargetGroup)
条件で「ルールを追加する」をクリックし、条件にある「条件の追加」をクリック。
以下のとおり2つの条件を設定する。
・「ホストヘッダー」を選択して「refirio.net」を入力
・「パス」を選択して「/redirect_to/」を入力
アクションで「URL にリダイレクト」をクリック。
以下のとおり設定する。
・URLにリダイレクト: 完全なURL
・完全なURL: https://www.example.com/
・ステータスコード: 301
「次へ」をクリック。
ルールの優先度を設定する画面になるので、今回のルールに「1」を入力。
「次へ」をクリックし、内容に問題無ければ「作成」をクリック。
https://refirio.net/ には変化なし。
https://refirio.net/redirect_to/ にアクセスすると https://www.example.com/ へリダイレクトされた。
同様に以下の設定も行った。
・「/redirect_to/net/*」にアクセスしたら「https://www.example.net/」へリダイレクト(優先度「2」)
・「/redirect_to/org/*」にアクセスしたら「https://www.example.org/」へリダイレクト(優先度「3」)
以下のとおり、リダイレクトされるようになった。
https://refirio.net/ → リダイレクトせず
https://refirio.net/redirect_to/ → https://www.example.com/
https://refirio.net/redirect_to/net/ → https://www.example.net/
https://refirio.net/redirect_to/net/test → https://www.example.net/
https://refirio.net/redirect_to/org/ → https://www.example.org/
https://refirio.net/redirect_to/org/test → https://www.example.org/
補足:
SSL対応URLからリダイレクトさせる場合、「完全なURL」にはSSLのURLを入力しないと「無効なプロトコル値」というエラーになった。
■外部サイトにリダイレクトさせる(対応していないURL)
以下のように「#」を含むURLをリダイレクト先にすると
https://refirio.net/info#about
以下のエラーになった。
server {
listen 80 default_server;
listen [::]:80 default_server;
#server_name localhost;
server_name refirio.net;
#root /usr/share/nginx/html;
root /var/www/vhosts/refirio/html;
if ($http_x_forwarded_proto = 'http') {
return 301 https://$server_name$request_uri;
}
The Path parameter must be a valid path, should start with a '/', and may contain up to one of each of these placeholders: '#{path}', '#{host}', '#{port}'.
調べても対処方法が見つからないので、ChatGPTに確認すると
結論からいうと ALB(Application Load Balancer)のリダイレクト設定では、#(フラグメント)は扱えません。
HTTP(S) リクエストがサーバに届く時点では、#(フラグメント)は ブラウザ側だけの情報 であり、サーバや ALB には送信されません。
とのこと。
どうしても対応したいなら
サーバには /info へリダイレクトさせ、遷移後のページで JS によって location.hash = "#about"; を付与する。
<script>
window.location.hash = "about";
</script>
のような方法になるみたい。
■リダイレクトされた回数を確認する
※実態に合った正確な数字なのかは未検証なので注意。
リダイレクト時に専用のクエリを付与して、リダイレクト先のアクセスログを解析すると確実かもしれない。
Application Load Balancer の CloudWatch メトリクス - エラスティックロードバランシング
https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-cloudwatch-m...
EC2 → ロードバランサー → ロードバランサーを選択 → モニタリング → HTTPリダイレクト数
拡大表示して「メトリクスで表示」
表示が
統計: 合計
期間: 1分
となっている。
これを
統計: 合計
期間: 1時間
とすると、今回の場合は1時間あたり30〜35回ほど転送されていると表示された。
■スティッキーセッション
セッションをElastiCacheやデータベースに保存できない場合、一度アクセスしたサーバに一定時間アクセスさせ続ける必要がある。
その場合はスティッキーセッションを有効にする。
「EC2 → ターゲットグループ → 設定したいグループを選択して → 説明 → 属性の編集」
「維持設定」を「ロードバランサーによって生成された Cookie の維持を有効化」に変更。
「維持設定の期間」は、「1日間」のままで保存。
反映まで1分ほどのタイムラグがあるみたい。
Classic Load Balancer の場合は設定箇所が違うので、以下を参照。
【基礎から学ぶ】ELBのスティッキーセッションについてまとめてみた - サーバーワークスエンジニアブログ
http://blog.serverworks.co.jp/tech/2017/01/05/elb-sticky/
■セキュリティポリシーを変更する
※未検証。
デフォルトでは「ELBSecurityPolicy-2016-08」が選択されているが、
例えばTLSバージョンを1.2に固定したければ「ELBSecurityPolicy-TLS-1-2-2017-01」に変更する。
(ただしTLS1.0しか使えないブラウザではアクセスできなくなるので、要件に合わせて慎重に検討する
最近のブラウザはTLS1.2に対応しているが、古いブラウザでは対応していないものがある。)
変更する場合、
「EC2 → ロードバランサー → 設定したいロードバランサーを選択して → リスナー → 『HTTPS : 443』を編集」
とし、リスナーの編集画面で「セキュリティポリシー」を変更する。
ELB のセキュリティポリシー変更はブラウザの対応プロトコルを考慮して慎重に | DevelopersIO
https://dev.classmethod.jp/articles/sugano-028-security/
AWS Classic Load BalancerのTLSバージョンを1.2に固定する方法 - 株式会社Japonline
https://www.japon-line.co.jp/tech/aws-elastic-load-balancer%E3%81%AEtls%E3%83%90%E3%83%BC%E3%82%B8%E...
Template:ウェブブラウザにおけるTLS/SSLの対応状況の変化 - Wikipedia
https://ja.wikipedia.org/wiki/Template:%E3%82%A6%E3%82%A7%E3%83%96%E3%83%96%E3%83%A9%E3%82%A6%E3%82%...
■タイムアウト時間を調整する
Webアプリケーションからの巨大ファイルのアップロードなどで、処理がタイムアウトしてしまう問題について。
・PHPの設定を変更しても、その上位で60秒の制限があるので解除が必要。
・nginxに制限があるが、設定を変更することで600秒などに伸ばすことが可能。
・ロードバランサーにも制限があるが、設定を変更することで600秒などに伸ばすことが可能。
・CloudFrontにも制限があるが、デフォルトで30秒。これは60秒以上に伸ばすことができない。
ALBの場合、「EC2 → ロードバランサー → (対象のロードバランサーを選択) → 属性」から設定できる。
デフォルトでは「接続アイドルタイムアウト: 60秒」となっているので、これを300秒に変更する。
504 Gateway Time-out が出たので ALB の アイドルタイムアウト 設定変更する #error - Qiita
https://qiita.com/nagaakihoshi/items/f7326978221ee053d208
504 Gateway Time-out が出た際は Elastic Load Balancing の設定にも注意しよう - Qiita
https://qiita.com/kotarella1110/items/169ddcef03983f5d64b2
【AWS】ALBでタイムアウト値を変更する方法 - 気ままに
https://unot13.hatenablog.com/entry/2018/02/01/145834
CloudFrontについては、「CloudFront」の「タイムアウト時間を調整する」を参照。
■カナリアリリース
※未検証。
[激アツアップデート]ALBだけでカナリアリリース(重み付け)ができるようになりました! | Developers.IO
https://dev.classmethod.jp/cloud/aws/alb-blue-green-deployment/
近年のデプロイ手法について|clonos|Google Cloud Platform の導入支援、構築、監視、運用代行
https://clonos.jp/knowledge/detail14/
■キャッシュ
対応していないので、nginxを併用するなどが必要。
Nginx + WordPress ロードバランサー篇
http://blog.serverworks.co.jp/tech/2012/09/28/nginx-04/
■Network Load Balancer(NLB)
※未検証。
FargateでのIPアドレス固定のためにも、NLBを使うのは有効か。
以下はロードバランサーの違いについて、参考になるかもしれない記事。
L4とL7ロードバランサーの違い
https://zenn.dev/axpensive/articles/d80e4d102eefb4