0.はじめに
今年の7月にAWSアソシをギリで取得した初心者が、AWSでそれっぽいことをする奮闘記の続きの更に続き。
CloudFormationの便利さは勿論、そこまでの道のりも整備されていて、感動。
1. やりたいこと
みんなが楽して、セキュアな仕組みを確実に実装できるようにしたい。
これがすべて。
- 楽して:これでも充分楽なんだけど、それでももっと楽したいのが人間。
- Lambdaに参考となるPythonコードをコピペしてきて…
- VPCとかサブネットの設定もして…
- API-GWも作成して…
- おっと、APIのデプロイもしなきゃ…
- 確実に実装:
- 設定するVPCとか間違えそう
- サブネットとか設定しなそう。
それを実現してくれるのが、CloudFormationくん。
AWSアソシにはちらっと登場してくる彼。
便利そうってことは知ってたけど、どのくらい便利かは知らなかった。
いざ。
2. できたもの(構成図+α)
構成図に手順を含めるとこんな感じ。
青枠部分が今回楽して作りたいAPIGWとLambda。
① 青枠のLambdaをテンプレ化して、
② それをS3にぶち込んで(※1)、
③ それをスタック作る際のインプットとする。:★
※1 構成管理ってなら、CodeCommitなんだろう。。
ユーザは★をやるだけ。
そうすると、テンプレに従って、青枠の部分が勝手に作られる、そんな動き。
3. どんな風に作ってったか。
元となるLambdaとAPI-GWは前の旅で、作成済の状態。ざっとこんな状態。
まずは、①のテンプレの元ネタを作ろう!
上記のLambdaの管理コンソール画面で、[アクション]→[関数のエクスポート]を選択すると、
以下2種類の形式でダウンロードできる。
ざっくり言うと、
- AWS SAMファイル:上の設定した環境変数やタグといった設定値が、超絶シンプルまとまって記載されたテンプートファイル
- デプロイパッケージ:ソースコードがZip化されたもの
今回は両方使う。
元ネタとしては、これで準備OK。
さらっと書いてるけど、これがあるのとないとでは、大違い。綺麗な道のり整備、助かります!
ちょっとだけカスタマイズする。
いくつかコネコネする。
なお、前の手順でダウンロードしたSAMファイルはこんな状態。
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: An AWS Serverless Specification template describing your function.
Resources:
slackwebfiltertry:
Type: 'AWS::Serverless::Function'
Properties:
Handler: lambda_function.lambda_handler
Runtime: python3.8
CodeUri: .
Description: ''
MemorySize: 128
Timeout: 3
Role: >-
arn:aws:iam::0000000000:role/service-role/slack-webfilter-try-role-xxxxxxx
Events:
Api1:
Type: Api
Properties:
Path: /slack-webfilter-try
Method: POST
VpcConfig:
SecurityGroupIds:
- sg-xxxxxxxxxxxxxxx
SubnetIds:
- subnet-xxxxxxxxxxxxxxx
- subnet-xxxxxxxxxxxxxxx
Environment:
Variables:
POST_SLACKAPI_URL: >-
https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.amazonaws.com/xxxxxxxxxxxxxxxxxx/share-postanytoslack-api
WEB_HOOK_URL: >-
https://hooks.slack.com/services/xxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxx
Tags:
slack: 'true'
レッツ、コネコネタイム。
いや、待て待て。それぞれ何を定義してんのか分からんわ!(いや、なんとなく分かるかw)
ってことで、ブラックベルト。これは分かりやすい。
https://d1.awsstatic.com/webinars/jp/pdf/services/20190814_AWS-Blackbelt_SAM_rev.pdf
できそうなので、レッツ、コネコネ。
(1) 関数コード
CodeUri
が、ローカルの状態なので、S3上のデプロイパッケージのパスに置き換える。
※前の手順でダウンロードしたデプロイパッケージをS3にぶち込んでおく。
(2) 作成するLambdaの関数名
デフォルトだと関数名はCloudFormationのマクロ側で勝手に設定されてしまう。
名前は大事だ。
ユーザに自分の関数名を入力してもらうために、
FunctionName
を追記して、かつパラメータとして扱う記述をする。
それがParameters:
の部分。
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: An AWS Serverless Specification template describing your function.
Parameters:
FunctionName:
Type: String
Description: Enter the purpose of the Lambda-function as a name.
Resources:
slackwebfiltertry:
Type: 'AWS::Serverless::Function'
Properties:
Handler: lambda_function.lambda_handler
Runtime: python3.8
CodeUri: s3://XXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.zip
FunctionName: !Sub "${FunctionName}"
Description: ''
MemorySize: 128
Timeout: 3
(略)
(3) プロキシ統合
今回のAPIは、管理コンソールの図のように「Lambdaプロキシ統合を使用」しない版で作成したい。(チェックない状態)
※上でダウンロードした状態のままだと、プロキシ統合した版(チェックある状態)で作成されてしまう。
こちらと、ブラックベルトを参考に。
https://dev.classmethod.jp/articles/cloudformation_template_for_api_gateway_integration_to_lambda/
※プロキシ統合したい場合⇒ type: "aws_proxy"
、したくない場合⇒type: "aws"
EventsブロックのPathとMethodいらないかな?って思ってけど、
必須らしく、下の方にあるpathsとの違いはよく分かってない。。。
(略)
Events:
Api1:
Type: Api
Properties:
RestApiId: !Ref posttoslackApi
Path: /posttoslack
Method: POST
VpcConfig:
(略)
Tags:
slack: 'true'
posttoslackApi:
Type: 'AWS::Serverless::Api'
Properties:
StageName: prod
DefinitionBody:
swagger: "2.0"
paths:
/posttoslack:
post:
x-amazon-apigateway-integration:
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${slackwebfiltertry.Arn}/invocations
httpMethod: "POST"
type: "aws"
ということで、この3つでテンプレートは完了!
S3にぶち込む。
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: An AWS Serverless Specification template describing your function.
Parameters:
FunctionName:
Type: String
Description: Enter the purpose of the Lambda-function as a name.
Resources:
slackwebfiltertry:
Type: 'AWS::Serverless::Function'
Properties:
Handler: lambda_function.lambda_handler
Runtime: python3.8
CodeUri: s3://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.zip
FunctionName: !Sub "${FunctionName}"
Description: ''
MemorySize: 128
Timeout: 3
Role: >-
arn:aws:iam::xxxxxxxxx:role/service-role/slack-webfilter-try-role-xxxxxxx
Events:
Api1:
Type: Api
Properties:
RestApiId: !Ref posttoslackApi
Path: /posttoslack
Method: POST
VpcConfig:
SecurityGroupIds:
- sg-xxxxxxxxx
SubnetIds:
- subnet-xxxxxxxxx
- subnet-xxxxxxxxx
Environment:
Variables:
POST_SLACKAPI_URL: >-
https://xxxxxxxxxxxxxxxxxx.amazonaws.com/xxxxxxxxxxxxxx/share-postanytoslack-api
WEB_HOOK_URL: >-
https://hooks.slack.com/services/xxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxx
Tags:
slack: 'true'
posttoslackApi:
Type: 'AWS::Serverless::Api'
Properties:
StageName: prod
DefinitionBody:
swagger: "2.0"
paths:
/posttoslack:
post:
x-amazon-apigateway-integration:
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${slackwebfiltertry.Arn}/invocations
httpMethod: "POST"
type: "aws"
4. 使ってみる(ユーザ向けの手順ってところ)
はい、かんたーーーん!
(1) スタックの作成
CloudFormationから、[スタックの作成]→[新しいリソースを使用(標準)]を選択する。
(2) テンプレートを選択する
(3) 名前を記入する
スタックの名前とそこから作成されるLambdaの関数名をそれぞれ記入する。
(4) スタックオプション
このスタックはSlack関連で使ってるってのを分かりやすくするため、タグ付けしておく。
(5) すべてにチェック
(6) 終わったら確認
[スタックの情報]でステータスがCREATE_COMPLETE
になってることを確認する。
※失敗するとROLLBACK_COMPLETE
になる。
作成したLambdaやAPIGWは[リソース]から参照できる。
また、[テンプレート]から、SAMと、処理されたテンプレートも見れるため、詳細を知りたい場合は結構参考になる。
いや、分からにくいって場合は、[デザイナーで表示]を選択すると、
こんな感じにグラフィカルに表現してくれる。うーん、優しい。
(7) 作成されたLambda修正
勿論テンプレベースなので、Lambdaのコードなどを自分用に修正していく。
これで終わり。
5. まとめ
こういった情報はWebに沢山あるし、GUIでほぼ出来ちゃうので仕組み作りも楽しめる。
もっとAWSと仲良くなる旅にでよう、かな。