ALB・Fargate(ECS)構成にSorryコンテンツを配置する
ALBおよびFargate(ECS)でシステムを構成している場合、システムメンテナンス等の理由で、一時的にFargateを停止する場合があります。
メンテナンス中にユーザからアクセスがあった場合は、ユーザにその旨を伝える必要があります。
今回はLambda関数でSorryコンテンツを用意し、これをALBに関連付けます。
そしてメンテナンス時は、ユーザからのトラフィックをこちらにルーティングするように設定します。
構築する環境
ALBに2つのコンテンツを関連づけます。
1つ目はFargateです。
ECRリポジトリからイメージをプルし、コンテナを生成します。
2つ目はLambda関数です。
Sorryコンテンツとして動作します。
CloudFormationテンプレートファイル
上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。
https://github.com/awstut-an-r/awstut-fa/tree/main/086
テンプレートファイルのポイント解説
本ページはALB・Fargate構成において、Sorryコンテンツを配置する方法を取り上げます。
プライベートサブネット内のFargate(ECS)をALBにアタッチする方法については、以下のページをご確認ください。
ALBのパスベースルーティングで、複数のターゲットグループにトラフィックを転送する方法については、以下のページをご確認ください。
Lambda等のコンテンツをALBにアタッチする方法については、以下のページをご確認ください。
Lambda関数
Resources:
Function:
Type: AWS::Lambda::Function
Properties:
Architectures:
- !Ref Architecture
Code:
ZipFile: |
import json
def lambda_handler(event, context):
return {
'statusCode': 503,
'isBase64Encoded': False,
'headers': {
'Content-Type': 'text/html; charset=utf-8'
},
'body': 'Sorry Contents from Lambda Function.'
}
FunctionName: !Sub "${Prefix}-function"
Handler: !Ref Handler
Runtime: !Ref Runtime
Role: !GetAtt FunctionRole.Arn
Code language: YAML (yaml)
特別な設定は不要です。
ステータスコード503と共に、「Sorry Contents from Lambda Function.」を返すシンプルな関数です。
ポイントはLambda関数のリソースベースのポリシーです。
Resources:
Permission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref Function
Action: lambda:InvokeFunction
Principal: elasticloadbalancing.amazonaws.com
Code language: YAML (yaml)
本関数をELBが呼び出すことを許可する内容です。
後述のALBがSorryコンテンツを返すための設定です。
ALB
ターゲットグループ
Resources:
ALBTargetGroupFargate:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
...
ALBTargetGroupLambda:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: false
Name: !Sub "${Prefix}-ALBTargetGroupLambda"
Targets:
- Id: !Ref FunctionArn
TargetType: lambda
Code language: YAML (yaml)
ALB関係のリソースとして、ターゲットグループを定義します。
2つのターゲットグループが必要となります。
1つ目はFargate用のグループです。
こちらの説明は割愛します。
2つ目はLambda関数用のグループです。
Targetsプロパティに先述のLambda関数のARNを、TargetTypeプロパティに「lambda」を指定します。
これでALBに着信したトラフィックのルーティング先として、Lambda関数を設定することができました。
リスナールール
Resources:
ALBListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- TargetGroupArn: !Ref ALBTargetGroupFargate
Type: forward
LoadBalancerArn: !Ref ALB
Port: !Ref HTTPPort
Protocol: HTTP
ALBListenerRule1:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- TargetGroupArn: !Ref ALBTargetGroupFargate
Type: forward
Conditions:
- Field: path-pattern
PathPatternConfig:
Values:
- /*
ListenerArn: !Ref ALBListener
Priority: 1
ALBListenerRule2:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- TargetGroupArn: !Ref ALBTargetGroupLambda
Type: forward
Conditions:
- Field: path-pattern
PathPatternConfig:
Values:
- /*
ListenerArn: !Ref ALBListener
Priority: 2
Code language: YAML (yaml)
2つのルールを作成します。
1つ目はFargate用です。
全てのパスにマッチするように設定した上で、Priorityプロパティに「1」を指定します。
これでこのルールが優先的に採用されます。
2つ目はLambda関数用です。
こちらも全てのパスにマッチするように設定した上で、Priorityプロパティに「2」を指定します。
優先度の関係で、通常時は1つ目のFargate用のルールが適用されます。
メンテナンス時は、これらの優先度を手動で調整することで、SorryコンテンツであるLambda関数に、トラフィックをルーティングさせます。
(参考)アプリコンテナ
index.html
<html>
<head>
</head>
<body>
<h1>fa-086 index.html</h1>
</body>
</html>
Code language: HTML, XML (xml)
シンプルなHTMLファイルです。
Dockerfile
FROM nginx:latest
COPY index.html /usr/share/nginx/html
EXPOSE 80
Code language: Dockerfile (dockerfile)
nginxをベースとし、ルートのHTMLファイルを先述のものに差し替えたイメージを作成します。
環境構築
CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。
CloudFormationスタックを作成し、スタック内のリソースを確認する
まずECRリポジトリ用CloudFormationスタックを作成し、作成されたECRにDockerイメージをプッシュします。
この手順の詳細は、以下のページをご確認ください。
イメージの準備が完了した後に、残りのスタックを作成します。
ネストされたスタックの作成および各スタックの確認方法については、以下のページをご確認ください。
各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。
- ALBのDNS名:fa-086-ALB-2131954533.ap-northeast-1.elb.amazonaws.com
- ECRリポジトリ:fa-086
- ECSクラスター:fa-086-cluster
- ECSサービス:fa-086-service
- Lambda関数:fa-086-lambda
AWS Management Consoleから各リソースを確認します。
ALBを確認します。
ALBが正常に作成されていることがわかります。
ALBのターゲットグループも確認します。
2つのターゲットグループが作成されていることがわかります。
それぞれFargateおよびLambda関数用のグループです。
リスナールールを確認します。
Fargate向けのルールが最優先で、その次がLambda関数向けのルールであることがわかります。
動作確認
正常時
準備が整いましたので、ALBにアクセスします。
先ほど確認したALBのドメイン名にアクセスします。
ALB経由でFargate上のコンテナにアクセスできました。
つまり最優先のFargate向けのルールが適用されたということがわかります。
メンテナンス時
続いてメンテナンス時を想定し、Sorryコンテンツを表示させます。
まずAWSマネージメントコンソールから、手動でALBのリスナールールを変更します。
優先順位を変更しました。
Lambda関数向けのルールを最優先に設定しました。
改めてALBのドメイン名にアクセスします。
SorryコンテンツであるLambda関数の文字列が返ってきました。
このようにリスナールールを変更することによって、メンテナンス時にSorryコンテンツを出力することができます。
まとめ
ALBおよびFargate構成において、Lambda関数を用いたSorryコンテンツを配置する方法を確認しました。
リスナールールの優先順位を変更することによって、メンテナンス時に、Sorryコンテンツを表示できることを確認しました。