はじめに
ALB経由からLambdaにアクセスの挙動を確認する際に毎回手動でポチポチしている自分に嫌気がさしまして、一念発起。
CloudFormationで再現性のある構築を少しでも残していきたいと思いまして、簡単な構築ですがハンズオンしていきます。
構成図
ハンズオン
構築の流れ
1.VPC作成
2.Lambda作成
3.ALB作成
上記の順番で構築を行なっていきます。
最終的に下記画像がALBのDNSを入力することで、画面に表示されるようになります。
1.VPC作成
以前記載したブログCloudFormationを使ってVPC構築に沿って、VPCを構築していきます。
2.Lambda作成
ALBから呼び出されるLambdaを作成します。
コールドスタートの影響もあるため、デプロイ直後にALBから呼び出しをするとタイムアウトになったりするので、タイムアウト値を多め(180秒)に設定
Lambda関数にALBトリガーを追加するリソースベースポリシーは、次項の3.ALB作成
で構築していきます。
AWSTemplateFormatVersion: '2010-09-09'
Description:
Lambda Create
# ------------------------------------------------------------#
# Metadata
# ------------------------------------------------------------#
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "Lambda Configuration"
Parameters:
- FunctionName
- Description
- Handler
- MemorySize
- Runtime
- Timeout
# ------------------------------------------------------------#
# InputParameters
# ------------------------------------------------------------#
Parameters:
FunctionName:
Type: String
Default: "cfn-lmd-inamura"
Description:
Type: String
Default: "cfn-lmd-inamura"
Handler:
Type: String
Default: "index.lambda_handler"
MemorySize:
Type: String
Default: "128"
Runtime:
Type: String
Default: "python3.9"
Timeout:
Type: String
Default: "180"
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
Resources:
# ------------------------------------------------------------#
# Lambda
# ------------------------------------------------------------#
Lambda:
Type: 'AWS::Lambda::Function'
Properties:
Code:
ZipFile: |
def lambda_handler(event, context):
response = {
"statusCode": 200,
"statusDescription": "200 OK",
"isBase64Encoded": False,
"headers": {
"Content-Type": "text/html; charset=utf-8"
}
}
response['body'] = """<html>
<head>
<title>sample-lambda</title>
<style>
html, body {
margin: 0; padding: 0;
font-family: arial; font-weight: 100; font-size: 1em;
text-align: center;
}
</style>
</head>
<body>
<p>Hellow sample-lambda!!</p>
</body>
</html>"""
return response
Description: !Ref Description
FunctionName: !Ref FunctionName
Handler: !Ref Handler
MemorySize: !Ref MemorySize
Runtime: !Ref Runtime
Timeout: !Ref Timeout
Role: !GetAtt LambdaRole.Arn
LambdaRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${FunctionName}-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action: "sts:AssumeRole"
Principal:
Service: lambda.amazonaws.com
Policies:
- PolicyName: !Sub "${FunctionName}-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "logs:CreateLogStream"
- "logs:PutLogEvents"
Resource: !Sub "arn:${AWS::Partition}:logs:*:*:*"
# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
LambdaArn:
Value: !GetAtt Lambda.Arn
Export:
Name: !Sub "${FunctionName}-arn"
3.ALB作成
ALB-EC2とALB-Lambdaの記述方法が異なることを知らずにハマりました。公式ドキュメントの読みなしで解決。
そして、リソースベースポリシーとTargetGroupとListenerの構築順番でもハマりました。DependsOn
を利用して解決。
AWSTemplateFormatVersion: "2010-09-09"
Description:
ALB Create
# ------------------------------------------------------------#
# Metadata
# ------------------------------------------------------------#
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "ALB Configuration"
Parameters:
- ALBName
- Type
- Scheme
- IpAddressType
- label:
default: "ALB TargetGroup"
Parameters:
- TGName
- TargetType
- label:
default: "ALB SecurityGroup"
Parameters:
- GroupName
# ------------------------------------------------------------#
# InputParameters
# ------------------------------------------------------------#
Parameters:
ALBName:
Type: String
Default: "cfn-alb-inamura"
Type:
Type: String
Default: "application"
Scheme:
Type: String
Default: "internet-facing"
IpAddressType:
Type: String
Default: "ipv4"
TGName:
Type: String
Default: "cfn-tgg-inamura"
TargetType:
Type: String
Default: "lambda"
GroupName:
Type: String
Default: "cfn-sg-alb-inamura"
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
Resources:
# ------------------------------------------------------------#
# ALB
# ------------------------------------------------------------#
ALB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Ref ALBName
Type: !Ref Type
Scheme: !Ref Scheme
IpAddressType: !Ref IpAddressType
Subnets:
- !ImportValue cfn-inamura-public-subneta
- !ImportValue cfn-inamura-public-subnetc
SecurityGroups:
- !Ref ALBSecurityGroup
ListenerHTTP:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref TargetGroup
LoadBalancerArn: !Ref ALB
Port: 80
Protocol: HTTP
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
DependsOn: LambdaInvokePermission
Properties:
Name: !Ref TGName
TargetType: !Ref TargetType
Targets:
- Id: !ImportValue cfn-lmd-inamura-arn
# ------------------------------------------------------------#
# ALB SG
# ------------------------------------------------------------#
ALBSecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: "ALB SG"
GroupName: !Ref GroupName
VpcId: !ImportValue cfn-inamura-vpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
# ------------------------------------------------------------#
# リソースベースポリシー
# ------------------------------------------------------------#
LambdaInvokePermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !ImportValue cfn-lmd-inamura-arn
Action: lambda:InvokeFunction
Principal: elasticloadbalancing.amazonaws.com
# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
ALBURL:
Description: ALB endpoint URL
Value: !Join
- ""
- - http://
- !GetAtt ALB.DNSName
挙動の確認
②インターネットブラウザにDNS name
を入力して、Lambdaで設定した画面が表示される。
※コールドスタートの場合、体感で1~2分程度表示に時間がかかりました。
さいごに
気軽に始めましたがCloudFormationに慣れていないことや、そもそものALBにどんな設定値が必要なのかなど、調べてみると分かっていないことが多く構築に時間がかかりました。ただ今後ALBの設定を毎回スクラッチすることからは、少しだけ解放されたかと思うと悪くない時間でした。
途中で気づいたEC2での設定や、Lambdaを修繕中の際のエラーページの表示など、まだまだ検証していくこと多めなので手を動かして知見を増やせればと思います。