どうも、こんにちは。お元気ですか?
今年は夏が来るのが遅いな、と思っていたら、
すごく暑い夏をいくつか残していって
あっという間に過ぎていきそうですね。
復習を兼ねて、serverless.ymlを一行一行、見ていこうと思います
まずはこんな記述がありました、と。
service: xxxxx-xxxxx
frameworkVersion: ">=1.53.0 <2.0.0"
plugins:
- serverless-pseudo-parameters
custom: ${file(../../serverless.common.yml):custom}
provider:
name: aws
runtime: python3.8
stage: ${opt:stage, self:custom.defaultStage}
region: ap-northeast-1
profile: ${opt:profile, ''}
logRetentionInDays: 30
environment:
TZ: Asia/Tokyo
STAGE: ${self:provider.stage}
API_ENDPOINT: ${self:custom.api_endpoint}
iamRoleStatements:
- Effect: Allow
Action:
- ssm:GetParameter
- ssm:PutParameter
Resource:
- arn:aws:ssm:${self:provider.region}:#{AWS::AccountId}:parameter/*
functions:
Refresh:
handler: handler.xxx_handler
layers:
- ${self:custom.requirements_layer}
- ${self:custom.shared_layers}
events:
- schedule: cron(0 16 ? * WED *) # 1週間おき(UTC -> JST毎週木曜の1:00AM)に実行
見ていくぞ! 英語ばっかり!
service: xxxxx-xxxxx
- ここでつけた名前がLamda関数やCloudFormationの一覧に登場します
- xxxxx-xxxxx-<ステージ名>-<Lambda画面ではここにfunctionsの名前が追記されます>
frameworkVersion: ">=1.53.0 <2.0.0"
- バージョン範囲です、1.53.0以上、2.0.0未満、数値の左にある
frameworkVersion
に対して不等号が向けられてるんですね - 公式ドキュメントによると
チームの全員がまったく同じ設定を使用し、予期しない問題が発生しないように、正確なバージョンに固定することをお勧めします
だそうです - 正確なバージョンとは
frameworkVersion: "=1.0.3"
こう書くようです
plugins:
- 色々とプラグインが出回っているようです(出回っているというと、海賊版みたいな雰囲気ありますね)
- Serverless Frameworkのメリットはこのプラグインが使えることにあるようです
- serverless-pseudo-parameters
- 「serverless.ymlに文字列をいれておくと、デプロイ時にデプロイ先のAWSリージョンやAWSアカウント名に置換してくれます。 開発環境と本番環境で作成するS3バケット名などを変更したい時に使います」だそうです
-
BucketName: mybucket-#{AWS::Region}-#{AWS::AccountId}
こんな感じだそうです - ちなみに
pseudo
とは疑似
という意味でした(最初のpは発音しないらしいです) - ハイフンが先頭についてる記述がいくつかあるのは、各内容に応じてデータソースが異なるときは、記述の先頭にハイフンをつけて[- xxx]とすることで複数記述することが可能ですとのことです、ありがとうございます
- この先頭にハイフンを書くのはYAML形式の特徴なんですね
custom: ${file(../../serverless.common.yml):custom}
- ここから
../../serverless.common.yml
の位置にある、serverless.common.yml
の中身のcustom
に書いてあることを、ここでもcustom
という変数名で使うよ、と
provider:
- プロバイダー(回線をインターネットと繋げる役割を担う接続事業者)ですね
- ここではクラウドサービスとかコンテナサービス(
azure
とかGoogle Cloud Platform
とか)のようです(ご指摘いただきました、ありがとうございます)
name: aws
- プロバイダーはAWSです
runtime: python3.8
- ここで使用するpython言語のバージョンは3.8にします、と
stage: ${opt:stage, self:custom.defaultStage}
- ステージ変数というらしいです
- 関数のステージはデフォルトで「dev」に設定されています
- 開発ステージ名はすべて
dev
と設定しておいて - 本番では
prd
としておくと見分けがつく - デプロイしたあとの設定名に必ずついてくる名前です
- opt:stageでステージ名は改めて
self:custom.defaultStage
にしますと言っています - self(自分の)custom
../../serverless.common.yml
に書いてあるdefaultStage
という欄を参照してください(ここではdevです)
region: ap-northeast-1
- リージョン(地域)です
- ap-northeast-1はAWSの指定で
アジアパシフィック (東京)
になります
profile: ${opt:profile, ''}
- プロファイル指定ですが、ここでは特使指定せず、デプロイ時に追記してください、もしくは、あとで指定があればここに、と
- プロファイルの詳しくは、先日私が書いた「slsコマンドを使って、デプロイを行った」を参照
logRetentionInDays: 30
- ログは30日間保存しててください、と設定
environment:
- 直訳で環境ですが、ここでは環境変数となります(ご指摘いただきました、ありがとうございます)
TZ: Asia/Tokyo
- タイムゾーン(地域ごとに標準時間は異なり、それらの標準時間帯)を
Asia/Tokyo
に
STAGE: ${self:provider.stage}
- ここでも念のためstage
dev
を追記
API_ENDPOINT: ${self:custom.api_endpoint}
- API(にアクセスするためのURL)は
cunstom
のapi_endpoint
の項目に書いてあります
iamRoleStatements:
- IAMロールの設定ですね
- ステートメントは申告とかの意味もありますから、許可申請とかですね
- Effect: Allow
- この下に書かれる項目の効果を許可(Allow)してます
- 不許可はDenyを使うと思いますが、不許可ならそもそも書かなくていいと思うので、基本Allowと思います
Action:
- じゃあ何の動作を許可するの、と
- ssm:GetParameter
- 今回はこれと
- ssm:PutParameter
- この2つです
- ssmというのは、
AWS Systems Manager
のことで、その中にある、アプリケーション管理 > パラメータストアの挙動の許可申告をしています - パラメータストアというのはパスワードとかデータベースの文字列を暗号化などして、格納するのに使用します
Resource:
- リソース:資源、仕様
- arn:aws:ssm:${self:provider.region}:#{AWS::AccountId}:parameter/*
- 上の2つの挙動を誰に対して許可するの? というのがここで指定されています
- arn(Amazon リソースネーム):(の)aws(AWSリージョン):(の)ssm:(は)${ここのプロバイダーのリージョンに準拠}:(し、)#{AWS::AccountId}
- AWS::(擬似パラメータ)についてはここが詳しかったです。ありがとうございます
-
擬似パラメータは、CloudFormation側で事前定義されているパラメータです
擬似パラメータ ->AWS::AccountId-AWSアカウントID
-
parameter/
はパラメータストア API アクションで、階層の 1 レベルのすべてのパラメータに対するアクセスを許可または制限するには、次のように階層名と AWS Identity and Access Management (IAM) ポリシーを使用するそうです - 例えばこんな感じで
parameter/Dev/ERP/Oracle/*
- 今回は
parameter/*
パラメータ階層すべてのアクセスを許可してくださいと申請しています - つまり自分がssmのパラーメタストアを使うので許可してね、と
functions:
- 働きかけとか関数の意味らしいです
- ここからLambda関数の記述が入ります
Refresh:
- これは私が任意でつけた名前です
- ここにつけた名前はLambda関数一覧で、1行目の
service
で付けた名前のあとに追記されます
handler: handler.xxx_handler
- 取り扱う関数はありますか? ->
handler.
pyの中のxxx_handler
の関数をここで使います - ちなみに
xxx_handler
の関数にはapp.
pyの中のevent
の関数を使うと書いてあります
layers:
- AWSをプロバイダーとして使用している場合(
provider: name: aws
)、サービス内のすべてのレイヤーはAWS Lambdaレイヤー - Lambda Layersは、複数の関数で共有されるコードとデータを集中管理する方法
- 下記の2つをレイヤーに分けて使用しますよ、と
- ${self:custom.requirements_layer}
-
../../serverless.common.yml
に記述してあるrequirements_layer
を参照します - ここでは
該当するCloudFormationの出力に設定されているキー
までの記述が書かれていました
勘違いして覚えたこと(消してもいいですが残しておきます)
layers:
- ここでは
layers
というディレクトリの中に別のserverless.ymlファイルを作っており、その中でserverless-python-requirements
というプラグインを呼び出しています - AWS Lambdaに分割してファイルをアップロードすることで、わかりやすさとデプロイの時間短縮ができている、と
- ${self:custom.requirements_layer}
- layerディレクトリの中の
serverless-python-requirements
というプラグインでできる、custom
を使用しますよ、と - 上記の
custom
の中にはlayer: true
という記述があり、それは、Lambdaレイヤーに、依存関係を処理する方法を、配置することだそうです - また要件が圧縮され、レイヤーが自動的に作成されますとも書いてありました
さ、気を取り直して続きです!
- ${self:custom.shared_layers}
-
../../serverless.common.yml
に記述してあるshared_layers
を参照します - ここでは
該当するCloudFormationの出力に設定されているキー
までの記述が書かれていました
events:
- Lambdaをどうやって実行しますか?
- ちなみにここはActionではないのはなぜ?
- アクションはあなたがすることです、あなたは何かをするつもりであることを意味する「アクションを起こす」ことができます。イベントはパーティーのような大きなもののようなものです。「メインイベント」でさえ、一連のものの中で最大のものです。だそうです、ありがとうございます。
- つまり、自分でなにかするのではなく、Lambdaに包括的にしてもらうので、Eventと読んでいるのかも知れませんね
- schedule: cron(0 16 ? * WED *) # 1週間おき(UTC -> JST毎週木曜の1:00AM)に実行
- 今回は
cron式
を使って、毎週木曜深夜1時に実施する旨を書きました - 当初JSTという日本時間で設定していました(
TZ: Asia/Tokyo
だったためです)が、どうやら、ここの標準時間はCloudWatchに依存するようで、実施したい9時間前(UTFとかGMTとか海外の標準時間)を指定する
ようです - cronの中に書かれている
?
は、日または週日(=曜日)用の値で、疑問符である必要があるそうです - [日] フィールドに 7 と入力し、7 日が何曜日であってもかまわない場合、[曜日] フィールドに ? を入力できるそうです
- 今回は水曜日(日本時間で木曜日)は指定して、何日を指定しないので[日] フィールドに
?
と入力しました -
公式ドキュメントによると
, - * ? / L W
の中のどれでも良さそうですが、日と曜日だけを表しているものとして?
もしくはL
で良さそうです
終わりに 長かった!
間違いがあればご指摘いただければと思います
次はもっと長くなるであろう、Python部分の記述を1行1行見ていこうと思います
ある晴れた日の午後、道を歩いていたら、
赤い洗面器を頭に乗せた男が歩いてきました。
洗面器の中にはたっぷりの水、
男はその水を一滴もこぼさないように、
ゆっくりゆっくり歩いてきます。
私は勇気をふるって
『ちょっとすいませんが、あなたどうして、
そんな赤い洗面器なんか頭に乗せて歩いてるんですか?』
と聞いてみました。
すると男は答えました。
『それは…』
えー、お察ししますー
それではこの辺で失礼いたしますー