takafumi blog

日々の勉強メモ

ポストモーテムとは

基本的にSRE本を自分で実施する際に理解しやすい形にまとめたもの。

前提

この文章はインシデント(障害や緊急対応など)発生時の対応関するポストモーテムに関して記述する。

プロジェクト終了時などその他のタイミングで行うポストモーテムとは異なる。

用語

  • ポストモーテム
    • この文章ないではインシデント時に作成するドキュメントをポストモーテムと呼ぶ
    • ドキュメント作成とそれにまつわるレビューやなど一連の流れ、仕組みを指すときはポストモーテムのプロセスと呼称する
  • インシデント
    • 障害・緊急対応などサービスに何かが起きた時の呼称
  • トイル(SRE本 p51)
    • プロダクションサービスを動作させることに関係する作業で以下のような傾向を持つもの
      • 手作業で繰り返し行われる
      • 自動化することが可能である
      • 戦術的で長期的な価値を持たない
      • 作業量がサービスの成長に比例する

まとめ

目的・文化・準備

プロセス

ポストモーテムのプロセスは以下のようになる

  1. インシデントが発生する
  2. インシデントの対応が完了する
  3. ポストモーテムを書く条件に当てはまるかを判定
  4. 必要な情報を収集する
  5. 原因の分析と対策を検討する
  6. ポストモーテムを書く
  7. レビューを行う
  8. 共有する

参考: https://postmortems.pagerduty.com/what_is/


ポストモーテムの目的

過去のインシデントから学習し、再発の可能性や影響を削減するために行われる。

具体的には以下のような事を目的となる。

  • 根本原因、教訓が十分(具体的・広範囲に)に理解されること
  • 効果的な予防策が確実に導入される事

参考: - https://postmortems.pagerduty.com/what_is/ - SRE本 p175

ポストモーテムの準備

ツールの選定

  • ポストモーテムを書くためには以下の機能を備えているツールが望ましい
    • リアルタイムコラボレーション
    • オープンなコメント/アノテーションシステム
    • メール、チャットによる自動通知
  • 管理システム

参考: SRE本 p177

ポストモーテムの作成

まずポストモーテムを書く前にポストモーテムを作成する必要があるかを判断する

書く場合は

  1. インシデント事態の情報、対応に関する情報収集
  2. インパクトの分析
  3. 根本原因の分析
  4. 対策についてアクションプランを検討
  5. 調査・対策が十分かステークホルダーに確認する

を行い上記を十分に吟味し(もしくは行いながら)、ポストモーテムの作成する。

ポストモーテムは事前に用意したテンプレートに従い記述し、どのようにな書き方がよいポストモーテムかを理解しておく必要がある

いつポストモーテムを作成するか

  • 事前に決めた条件に則り、条件を満たす場合に作成する
    • ユーザー影響あるダウンタイムの発生
    • エンジニアが介入が必要だったとき
    • 解決までの時間
    • データの損失が発生した場合
    • 支払い、請求などお金に関わる問題発生時
    • モニタリングシステム自体の障害
    • など
  • 上記の決まった条件以外で問題となったイベントのステークホルダーは条件に以外で求める事ができる

参考: SRE本 p176~p178

ポストモーテムのテンプレート

例としてポストモーテムには以下のような項目を記述する。

- 担当者
    - ポストモーテム担当者
    - 対応担当者
- 概要
- 原因分析
    - 根本原因(e.g. ○○のバグのため)
    - 発生原因(e.g. △△の操作を行ったため)
- 対応内容
- 対応自体の分析
- 教訓
- 今後のアクションリスト
    - 事後対応内容
    - 現在のステータス
    - 担当者
    - 優先度

よいポストモーテムの書き方

TODO

参考: サイトリライアビリティワークブック―SREの実践方法/10章 ポストモーテムの文化:失敗からの学び

レビュー

レビューが行われていないポストモーテムは適切さを証明できないため、無いも同然と考える必要がある。

実際の流れとしては - チームに下書きを内部共有してレビューを行う - この時、上位の役職者は下書きが完全かを評価する

となる。場合によっては広範囲に意見を求める事もある。

レビューの観点

レビューでは事前にある程度観点を定めておく。

以下は一例

  • 不要な非難が含まれていないか
    • 個人に対する指摘
  • インシデントの主要なデータが収集されているか
  • インパクトの分析が十分か
  • 根本原因の分析が十分か
  • アクションプランは適切か
    • 担当者が決まっているか
    • 優先度が与えられているか
  • 結果はステークホルダーと共有されているか

など

レビューを必ず行う仕組み

レビューが行われなければポストモーテムは無意味といっていい。

必ず行うために、何時、どのように行うかをあらかじめ考えておくとよい。

  • どんなタイミングでレビューをするか
    • 下書きの段階でチーム内や直属の上位者がレビューするのが望ましい
  • レビューされていないポストモーテムが存在しない仕組みづくり
    • レビューMTGを行いポストモーテムを完成させる
      • レビューMTGの議論内容はとりまとめ、ポストモーテムに記載する

参考: SRE本 p178

共有

ポストモーテムを広く共有し、知識や教訓を広い範囲で役立てる事を目標とする。

より広範囲なチーム、内部メーリングリスト、チャットチャンネルなどへ共有する。

ポストモーテム文化の導入

参考: SRE本 p179

非難なく行う

ポストモーテムの記述・レビューなど全てのプロセスを通して、非難なく行うことが重要である - 避難的な雰囲気は問題の隠蔽へつながる - ポストモーテムを頻繁に作成している事を非難しない - ポストモーテムはサービス改善のための提案である - ポストモーテムの作成を称賛する文化を作る事が望ましい

参考: SRE本 P176~P177

継続的な育成と強化

継続にはポストモーテム文化の育成と強化が必要となる。 - 上位管理職の積極的な参加 - 積極的な情報の発信 - よいポストモーテムの選出・定期的な発信 - 公開されたポストモーテム議論の場 - チャットチャンネル、メールグループなど - ポストモーテムの読書会 - 過去の興味深いポストモーテムの振り返り - 新旧を問わず - ディザスターロールプレイング - ポストモーテムに書かれている役割をエンジニアたちが演じ、過去のポストモーテムの再現する

ポストモーテムプロセスのフィードバック

ポストモーテムのプロセス自体に無駄がないかを見直し、改善を行う。 - ポストモーテムは業務の支援となっているか? - トイルが発生しすぎていないか? - ツールは適切か?新しい開発が必要か?

参考: SRE本 p180

将来的な価値を考える

参考: SRE本 P181

準備コストと価値に対する理解

ポストモーテム文化を組織に導入する上での最大の課題は、準備コストよりも価値があるのか?と考える人が多いかもしれないこと。

これを解決するには以下のような対策が考えられる - ワークフローに落とし込む - よいポストモーテムを書くことは評価されるように - ピアボーナスを与える - 上位のリーダーたちの承認と参加を奨励する

理解に関しては - ポストモーテムプロセスのフィードバックを行う - 継続的な育成と強化 - 将来的な価値を考える

などと合わせて考えることが理解を得る助けとなる

参考: SRE本 P179

ポストモーテムの例

SRE本 p507

参考

fluent-plugin-s3 設定と IAMロール アクションの関係と注意

環境   fluent-plugin-s3 1.6.0

関係性のまとめ

アクション 関係ある設定 説明
s3:ListBucket check_bucket true trueであればfluent起動時にbucket存在をチェック。存在しなければ起動をリトライする
falseだと起動はするが書き込み時に失敗する
s3:GetObject check_object true trueであれば同じobjectがあると上書きせずエラーになる
falseだと同名objectは上書きされる
s3:PutObject 書き込み全般

つまり check_bucket check_objectfalse ならアクションは最小限の PutObject のみでよい

check_object false の注意

check_object false の時も s3_object_key_format が同名にしない事で不用意な上書きを防ぐ事ができる。

s3_object_key_format を設定していなければ、デフォルト値自体が上書きされにくいフォーマットに自動で変更される。

(s3_object_key_format "%{path}/%{date_slice}_%{hms_slice}.%{file_extension}" になる)

さらに uuid_flush hex_random index hostname などを使えばより重複を防止し安全に扱える。

  • uuid_flush
    • bufferがフラッシュされる際、常にUUIDに置き換えられる
    • 書き込み失敗のリトライ時も新しいUUIDに置き換えられる
  • hostname
    • ホストネームに置き換えられるので、 %s%{hms_slice} などと組み合わせると重複を防止できる
  • hex_random :
    • bufferに使われるhashで置き換えられる
    • 例えば同名エラーでリトライしたときも同じ値が使われる
    • %{index} を組み合わせればリトライ時は %{index} が更新される

fluent-plugin-s3 v0.12 の注意

正確には fluent-plugin-s3 < 1.0.0rc7 のとき。

この時 check_object false だと s3_object_key_format が固定されるので注意

github.com

check_bucket trueAPIリクエストにかかる料金の注意

check_bucket は起動時のチェックなので、 true でもほとんどAPIリクエストはしない。

しかし check_objecttrue だと書き込みの度にAPI GetObject を発行する。

そのため、特に書き込み頻度が高い場合は、APIリクエストが常に GetObject -> PutObject と二重に発生し料金が嵩むので注意。

Scalaでもtry-catchを使う方がよい事もある

環境   Scala 2.13.6

Scalaだと例外を常にTryで処理しがちなので、反省メモ。

もちろん単純に例外出す可能性ある個所をTryで包むのは問題ない。
困るのはTry[Either[L, R]] みたいなネストを避けたい時。

refinedとかでよくある。
例えば以下は単純にStringEither[String, PosInt]に変換している。

import cats.implicits._
import eu.timepit.refined.api.RefType
import eu.timepit.refined.types.numeric.PosInt
import scala.util.Try

def s2pi(s: String): Either[String, PosInt] =
  Try(s.toInt).toEither
    .leftMap(_.getMessage)
    .flatMap(RefType.applyRef[PosInt](_))

val etPiR = s2pi("1") // Right(1)
val etPiL = s2pi("a") // Left(For input string: "a")

読みずらい!
まあ正直言うと、このくらいならまだマシで、実際コード書いているともっと複雑になる事も多々ある。

こういうTryとEitherのネストを避けようとするなら、以下のように書くのが断然読みやすい。

import eu.timepit.refined.api.RefType
import eu.timepit.refined.types.numeric.PosInt
import scala.util.Try

def s2piVer2(s: String): Either[String, PosInt] =
  try RefType.applyRef[PosInt](s.toInt)
  catch { case t: Throwable => Left(t.getMessage) }

val etPiV2R = s2piVer2("1") // Right(1)
val etPiV2L = s2piVer2("a") // Left(For input string: "a")

ドメイン駆動開発(DDD)とCleanArchitectureのエンティティはどう違うか?

双方と共にビジネスモデル定義のためのオブジェクトという点では共通だが、実際には意味は大幅に異なる。

DDDでは

以下のように定義される

「エリック・エヴァンスのドメイン駆動開発 第5章」から

主として同一性によって定義されるオブジェクトはエンティティと呼ばれる。

としている。

つまりDDDではビジネスモデルの中でも、常に同一である事を保証できるオブジェクトととして定義されるものがエンティティである。

CleanArchitectureでは

クリーンアーキテクチャ(The Clean Architecture翻訳)」から

エンティティーは、大規模プロジェクトレベルのビジネスルールをカプセル化する。エンティティは、メソッドを持ったオブジェクトかもしれない、あるいは、データ構造と関数の集合かもしれない。

とある。
これはDDDで言うところの、エンティティ、値オブジェクト、ドメインサービス、リポジトリ(の仕様)、ファクトリ, 集約などのドメインレイヤー全体を指している。

まとめ

回答としては「DDDにおけるエンティティ」と「CleanArchitectureにおけるエンティティ」は全く異なる定義なので、使うアーキテクチャに合わせてコードを書こう。

もっと言えば - 書いているコードのアーキテクチャが、何を採用しているか? - 各用語はどういう定義なのか?

をきちんと理解して書こうという事になる。

プロジェクトによってはCleanArchtectureだけどentityをdomainというpackage名にしたりで、一見DDD風に見える事もあったり、そもそも全く異なる意味で使っている場合もある。
プロジェクトに参加したときはビジネス的な言葉、DDDでいうユビキタス言語だけではなく、こういったコード上の意味合いも慎重に確認する事が大切。

aws sam (Serverless Application Model)に入門する

Infrastructure as Code入門としてaws samでLambdaを作るところからはじめてみる

aws-cliaws-samはinstall済み

sample templateから基本的なアプリケーションをビルト

仕組み的には以下のような順序で作成される

  1. ローカルでsamコマンドでアプリケーションを作成
  2. ローカルからsam deployでcloudformationを呼び出しアプリケーションをデプロイする
  3. S3へテンプレートが保存される
  4. API GatewayとLambdaが作成される

f:id:takafumi-s:20210808235600p:plain

aws samのアプリケーションを作成

$ sam init

# まずはawsのtemplateを選択して使う
# template一覧は以下
Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1


# パッケージはシンプルに
# lambda用のファイルはzipで固め
# cloudformationでS3にアップロードされる
#
# 2のイメージはECR周りの知識が必要なのでそのうち試す
What package type would you like to use?
        1 - Zip (artifact is a zip uploaded to S3)
        2 - Image (artifact is an image uploaded to an ECR image repository)
Package type: 1

# go1.xで作っていく
Which runtime would you like to use?
        1 - nodejs14.x
        2 - python3.8
        3 - ruby2.7
        4 - go1.x
        5 - java11
        6 - dotnetcore3.1
        7 - nodejs12.x
        8 - nodejs10.x
        9 - python3.7
        10 - python3.6
        11 - python2.7
        12 - ruby2.5
        13 - java8.al2
        14 - java8
        15 - dotnetcore2.1
Runtime: 4

# cloudformation, API Gatewayの名前
# S3, Lambdaのprefixとして使われる
Project name [sam-app]:

Cloning from https://github.com/aws/aws-sam-cli-app-templates

# まずは単独のLambdaで作るので1を選択
AWS quick start application templates:
        1 - Hello World Example
        2 - Step Functions Sample App (Stock Trader)
Template selection: 1

    -----------------------
    Generating application:
    -----------------------
    Name: sam-app
    Runtime: go1.x
    Dependency Manager: mod
    Application Template: hello-world
    Output Directory: .

    Next steps can be found in the README file at ./sam-app/README.md

この段階でgolangのLambdaに適した構成が作成される
template.yamlはcloudformationと共通フォーマット
将来的にaws samの範囲より拡張された場合はcloudformationで使う事もできる

$ tree sam-app
sam-app
├── Makefile
├── README.md
├── hello-world
│   ├── go.mod
│   ├── go.sum
│   ├── main.go
│   └── main_test.go
└── template.yaml

1 directory, 7 files

main.goは以下のようにLambdaでGetリクエストを受ける基本的な構成になっている

package main

import (
        "errors"
        "fmt"
        "io/ioutil"
        "net/http"

        "github.com/aws/aws-lambda-go/events"
        "github.com/aws/aws-lambda-go/lambda"
)

var (
        // DefaultHTTPGetAddress Default Address
        DefaultHTTPGetAddress = "https://checkip.amazonaws.com"

        // ErrNoIP No IP found in response
        ErrNoIP = errors.New("No IP in HTTP response")

        // ErrNon200Response non 200 status code in response
        ErrNon200Response = errors.New("Non 200 Response found")
)

func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
        resp, err := http.Get(DefaultHTTPGetAddress)
        if err != nil {
                return events.APIGatewayProxyResponse{}, err
        }

        if resp.StatusCode != 200 {
                return events.APIGatewayProxyResponse{}, ErrNon200Response
        }

        ip, err := ioutil.ReadAll(resp.Body)
        if err != nil {
                return events.APIGatewayProxyResponse{}, err
        }

        if len(ip) == 0 {
                return events.APIGatewayProxyResponse{}, ErrNoIP
        }

        return events.APIGatewayProxyResponse{
                Body:       fmt.Sprintf("Hello, %v", string(ip)),
                StatusCode: 200,
        }, nil
}

func main() {
        lambda.Start(handler)
}

アプリケーションをbuild

$ sam build
Building codeuri: ./sam-app/hello-world runtime: go1.x metadata: {} functions: ['HelloWorldFunction']
Running GoModulesBuilder:Build

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

ローカルでアプリケーションを実行

sam local start-apiと実行する事で、ローカルでsamでbuildしたAPIを実行できる

$ sam local start-api
Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2021-08-08 23:37:49  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)

この状態でリクエストを投げると、dockerイメージが作成&実行され、レスポンスを返す

$ curl http://127.0.0.1:3000/hello
Hello, 11.111.111.111

sam local start-apiのログ

Invoking hello-world (go1.x)
Image was not found.
Building image......................................................................................................
Skip pulling image and use local one: amazon/aws-sam-cli-emulation-image-go1.x:rapid-1.27.2.

Mounting ./sam-app/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container
START RequestId: fa806430-6835-4b88-acd6-4e1b857bcd4a Version: $LATEST
END RequestId: fa806430-6835-4b88-acd6-4e1b857bcd4a
REPORT RequestId: fa806430-6835-4b88-acd6-4e1b857bcd4a  Init Duration: 0.07 ms  Duration: 1010.38 ms    Billed Duration: 1100 ms        Memory Size: 128 MB     Max Memory Used: 128 MB
No Content-Type given. Defaulting to 'application/json'.
2021-08-08 23:43:07 127.0.0.1 - - [08/Aug/2021 23:43:07] "GET /hello HTTP/1.1" 200 -
$ docker ps
CONTAINER ID   IMAGE                                                   COMMAND                  CREATED         STATUS        PORTS                      NAMES
fa8dda6a0f15   amazon/aws-sam-cli-emulation-image-go1.x:rapid-1.27.2   "/var/rapid/aws-lamb…"   2 seconds ago   Up 1 second   127.0.0.1:6436->8080/tcp   vigorous_allen

アプリケーションをawsへデプロイする

--guided をつけると会話形式で設定できる

$ sam deploy --guided

Configuring SAM deploy
======================

        Looking for config file [samconfig.toml] :  Not found

        Setting default arguments for 'sam deploy'
        =========================================
        Stack Name [sam-app]:
        AWS Region [ap-northeast-1]:
        #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
        Confirm changes before deploy [y/N]:
        #SAM needs permission to be able to create roles to connect to the resources in your template
        Allow SAM CLI IAM role creation [Y/n]:
        HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y
        Save arguments to configuration file [Y/n]:
        SAM configuration file [samconfig.toml]:
        SAM configuration environment [default]:

        Looking for resources needed for deployment: Not found.
        Creating the required resources...
        Successfully created!

                Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-xarl3ki5fc62
                A different default S3 bucket can be set in samconfig.toml

        Saved arguments to config file
        Running 'sam deploy' for future deployments will use the parameters saved above.
        The above parameters can be changed by modifying samconfig.toml
        Learn more about samconfig.toml syntax at
        https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html

Uploading to sam-app/7ad10cf1c8bd04b9d2c1ad18dd4297c0  4328737 / 4328737  (100.00%)

        Deploying with following values
        ===============================
        Stack name                   : sam-app
        Region                       : ap-northeast-1
        Confirm changeset            : False
        Deployment s3 bucket         : aws-sam-cli-managed-default-samclisourcebucket-xarl3ki5fc62
        Capabilities                 : ["CAPABILITY_IAM"]
        Parameter overrides          : {}
        Signing Profiles             : {}

Initiating deployment
=====================
Uploading to sam-app/17fb0b7caff4b6a85cdca466c28c1236.template  1154 / 1154  (100.00%)

Waiting for changeset to be created..

CloudFormation stack changeset
----------------------------------------------------------------------------------------------------
Operation    LogicalResourceId                           ResourceType                   Replacement
----------------------------------------------------------------------------------------------------
+ Add        HelloWorldFunctionCatchAllPermissionProd    AWS::Lambda::Permission        N/A
+ Add        HelloWorldFunctionRole                      AWS::IAM::Role                 N/A
+ Add        HelloWorldFunction                          AWS::Lambda::Function          N/A
+ Add        ServerlessRestApiDeployment47fc2d5f9d       AWS::ApiGateway::Deployment    N/A
+ Add        ServerlessRestApiProdStage                  AWS::ApiGateway::Stage         N/A
+ Add        ServerlessRestApi                           AWS::ApiGateway::RestApi       N/A
----------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:111111111111:changeSet/samcli-deploy1628426562/db1f0927-131d-4bf1-9b12-aacf949eacda


2021-08-08 21:42:54 - Waiting for stack create/update to complete

CloudFormation events from changeset
------------------------------------------------------------------------------------------------------------------------------
ResourceStatus         ResourceType                   LogicalResourceId                           ResourceStatusReason
------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS     AWS::IAM::Role                 HelloWorldFunctionRole                      -
CREATE_IN_PROGRESS     AWS::IAM::Role                 HelloWorldFunctionRole                      Resource creation Initiated
CREATE_COMPLETE        AWS::IAM::Role                 HelloWorldFunctionRole                      -
CREATE_IN_PROGRESS     AWS::Lambda::Function          HelloWorldFunction                          -
CREATE_IN_PROGRESS     AWS::Lambda::Function          HelloWorldFunction                          Resource creation Initiated
CREATE_COMPLETE        AWS::Lambda::Function          HelloWorldFunction                          -
CREATE_IN_PROGRESS     AWS::ApiGateway::RestApi       ServerlessRestApi                           -
CREATE_IN_PROGRESS     AWS::ApiGateway::RestApi       ServerlessRestApi                           Resource creation Initiated
CREATE_COMPLETE        AWS::ApiGateway::RestApi       ServerlessRestApi                           -
CREATE_IN_PROGRESS     AWS::Lambda::Permission        HelloWorldFunctionCatchAllPermissionProd    -
CREATE_IN_PROGRESS     AWS::Lambda::Permission        HelloWorldFunctionCatchAllPermissionProd    Resource creation Initiated
CREATE_IN_PROGRESS     AWS::ApiGateway::Deployment    ServerlessRestApiDeployment47fc2d5f9d       -
CREATE_COMPLETE        AWS::ApiGateway::Deployment    ServerlessRestApiDeployment47fc2d5f9d       -
CREATE_IN_PROGRESS     AWS::ApiGateway::Deployment    ServerlessRestApiDeployment47fc2d5f9d       Resource creation Initiated
CREATE_IN_PROGRESS     AWS::ApiGateway::Stage         ServerlessRestApiProdStage                  -
CREATE_IN_PROGRESS     AWS::ApiGateway::Stage         ServerlessRestApiProdStage                  Resource creation Initiated
CREATE_COMPLETE        AWS::ApiGateway::Stage         ServerlessRestApiProdStage                  -
CREATE_COMPLETE        AWS::Lambda::Permission        HelloWorldFunctionCatchAllPermissionProd    -
CREATE_COMPLETE        AWS::CloudFormation::Stack     sam-app                                     -
------------------------------------------------------------------------------------------------------------------------------

CloudFormation outputs from deployed stack
-----------------------------------------------------------------------------------------------------------
Outputs
-----------------------------------------------------------------------------------------------------------
Key            HelloWorldFunctionIamRole
Description    Implicit IAM Role created for Hello World function
Value          arn:aws:iam::111111111111:role/sam-app-HelloWorldFunctionRole-MGSTGE9WCIMR

Key            HelloWorldAPI
Description    API Gateway endpoint URL for Prod environment for First Function
Value          https://aaaaaaaaaa.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/

Key            HelloWorldFunction
Description    First Lambda Function ARN
Value          arn:aws:lambda:ap-northeast-1:111111111111:function:sam-app-HelloWorldFunction-pMOSVaxRjbuN
-----------------------------------------------------------------------------------------------------------

Successfully created/updated stack - sam-app in ap-northeast-1

これにより API Gateway経由でLambdaを呼び出せるようところまで作成される

デプロイ結果の確認

OutputsにあるHelloWorldAPIへアクセスしてみると、レスポンスが返ってくる

$ curl - 'https://aaaaaaaaaa.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/'
HTTP/2 200
content-type: application/json
content-length: 22
date: Sun, 08 Aug 2021 13:41:16 GMT

Hello, 11.111.111.111

参考

docs.aws.amazon.com

docs.aws.amazon.com

awsデータストレージまとめ(インスタンスストア・EBS・EFS・S3)

各ストレージ

インスタンス ストア

Elastic Block Store (EBS)

  • ブロックレベルストレージ
  • インスタンスから独立してデータを永続化する
  • 起動しているインスタンスにアタッチ(追加)できる
  • 稼働中にサイズ変更、ボリュームタイプの変更など可能
  • インスタンスとEBSは同じAZにある必要がある

Elastic File System (EFS)

  • マネージドなサーバーレスなファイルレベルストレージ
  • 最大サイズ16TiB(=tebibyte=1024GB)
  • EC2でNFSとしてマウント可能
  • オートスケール
  • リージョン内のAZを跨いでマウント可能
    • ただし複数のVPCに接続はできない

Simple Storage Service (S3)

  • オブジェクトレベルストレージ
  • インターネットストレージとしてURLでアクセス可能
  • 無制限のストレージ容量
  • 各オブジェクトは最大5TB
  • バケットはリージョン単位で保存される
  • 各オブジェクトのバージョニングによる変更追跡
  • 少なくとも3つのAZにデータが保存(バックアップ)される
  • 複数のストレージクラスによる料金プラン
  • 各オブジェクトにURLがあり静的webページとしても使える

ストレージ形式について

ファイルレベルストレージ

  • ファイルストレージ
  • ファイルベース・ストレージ

ファイルによるデータ管理。
階層構造化が容易で、一意のデータパスによりファイルにアクセスする。
データにはファイル名、作成日時などの最低限のメタデータが付与される。

ブロックレべルストレージ

ディスクを論理ボリュームへ分割し、論理ボリュームをさらにブロックへ分割。
データをブロック単位で保存する(ブロックより大きなデータは複数ブロックへ保存される。連続性はない)

ボリューム、ブロック両方にIDが振られボリュームID+ブロックIDでデータを特定する事で高速なデータアクセスが可能。

ブロック単位での差分更新が可能なため、巨大なデータの更新が高速で行える。

メタデータは基本的にはない、もしくは非常に限定的。

オブジェクトレベルストレージ

  • オブジェクトストレージ
  • オブジェクトベース・ストレージ

一つのデータを一つのオブジェクトとして保存する。
オブジェクトは一意のIDを持ち、インデックス化され高速にアクセスできる。

多彩なメタ情報が付与され、セキュリティポリシーやアクセス権限に至るまで様々な情報を持つ事ができる。

通常はフラットな構造になるが、S3のようにバケット入れ子構造にできるサービスもある。

一度書き込まれたオブジェクトは変更できず、オブジェクトは全体を一度で書き込む必要がある。
そのため巨大なデータを更新する場合などは、巨大なデータを再度全て書き込み、過去データを削除(もしくは履歴として残す)ような運用になる。

参考

docs.aws.amazon.com

docs.aws.amazon.com

docs.aws.amazon.com

docs.aws.amazon.com