kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Apex の --env オプションを使って Lambda を複数環境にデプロイする

最近仕事で必要になり,CircleCI + Apex を使って,Lambda を複数環境 (prd / stg / dev など) にデプロイできる仕組みを作ったので,実現したかったこと,工夫したことなどを紹介したいと思う.ちなみに,以前も似たような事例で CloudWatch Events + Lambda + CircleCI + Apex を使ったアーキテクチャを紹介したが,これはあくまで開発ツールの位置付けなので,複数環境の考慮が必要なく,単純に apex deploy を実行するだけの非常にシンプルな構成になっていた点が異なる.

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

エイリアスは採用しなかった

「実践 AWS Lambda」にも書いてある通り,Lambda にはエイリアスという機能があり,特定のバージョンに prd / stg / dev など,任意のエイリアスを付けて識別することができる.単純にバージョンと環境を紐付けるだけなら便利だと思うが,今回は以下の要件を満たしたいと考えていて,エイリアスで環境を識別するアプローチは採用しなかった.プロダクションで Lambda を使う場合,基本的には以下の要件はあると思う.

  • 環境ごとに異なる環境変数を設定する
  • 環境ごとに制御した IAM ロールを設定する
  • 環境ごとに異なるコンピューティングリソースを設定する

kakakakakku.hatenablog.com

複数環境デプロイ

公式ドキュメントにも記載がある通り,Apex は複数環境 (Multiple Environments) のデプロイに対応している.特に難しいことはなく,環境ごとの設定ファイルを用意して --env オプションを指定することで,環境別にデプロイを行うことができる.なお,環境ごとの設定ファイルには大きく2種類あり,粒度によって使い分けることができる.

  • project.json … 複数の Lambda 関数で共通して参照する設定ファイル
  • function.json … Lambda 関数ごとに参照する設定ファイル

今回作ったデプロイフローはザッと以下のようになる.

f:id:kakku22:20170620212838j:plain

事前作業

環境ごとに IAM ロールが必要になるため,事前に作成しておく.今回サンプルとして prd / stg / dev を作成した.

  • arn:aws:iam::00000000000:role/prd-myfunc_lambda_function
  • arn:aws:iam::00000000000:role/stg-myfunc_lambda_function
  • arn:aws:iam::00000000000:role/dev-myfunc_lambda_function

IAM ポリシーの設定は割愛するが,公式ドキュメントに Lambda のポリシーテンプレートが公開されていて,様々なユースケースを網羅しているため,非常に便利!

docs.aws.amazon.com

Apex ディレクトリ構造

Apex ディレクトリ構造は以下のようになる.project.*.json はルートディレクトリに配置して,function.*.json は Lambda 関数のメイン処理と同じディレクトリに配置している.なお,今回は2個の Lambda 関数をデプロイできるようにした(ランタイムは Python).

├── circle.yml
├── functions
│   ├── myfunc1
│   │  ├── function.dev.json
│   │  ├── function.prd.json
│   │  ├── function.stg.json
│   │  ├── main.py
│   │  └── requirements.txt
│   └── myfunc2
│       ├── function.dev.json
│       ├── function.prd.json
│       ├── function.stg.json
│       ├── main.py
│       └── requirements.txt
├── project.dev.json
├── project.prd.json
└── project.stg.json

project.*.jsonfunction.*.json

設定項目としては同じで,粒度が異なるだけなので,今回は project.dev.json を例に載せる.

{
  "name": "dev-myfunc",
  "description": "dev-myfunc",
  "memory": 128,
  "timeout": 5,
  "role": "arn:aws:iam::00000000000:role/dev-myfunc_lambda_function",
  "environment": {
    "XXX": "xxx",
    "YYY": "yyy",
    "ZZZ": "zzz"
  }
}

このように設定することで,今回の要件を全て満たすことができた.

  • 環境ごとに異なる環境変数を設定する
  • 環境ごとに制御した IAM ロールを設定する
  • 環境ごとに異なるコンピューティングリソースを設定する

デプロイする

残るはデプロイするだけとなる.

$ apex deploy --env prd
$ apex deploy --env stg
$ apex deploy --env dev

CircleCI で自動デプロイ

今回も CircleCI で自動デプロイをできるようにした.以下にサンプルの circle.yml を載せておく.これで,プルリクを出すと dev / stg 環境にデプロイされて,master にマージをすると dev / stg / prd 環境にデプロイされる.便利!なお,テストを書かないと CircleCI でエラーになるため,今回は echo を設定して回避している.

machine:
  timezone: Asia/Tokyo

dependencies:
  post:
    - curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sudo sh
    - apex version

deployment:
  prd:
    branch: master
    commands:
      - pip install --requirement functions/myfunc1/requirements.txt --target functions/myfunc1
      - pip install --requirement functions/myfunc2/requirements.txt --target functions/myfunc2
      - apex deploy --env dev
      - apex deploy --env stg
      - apex deploy --env prd
  stg_dev:
    branch: /^(?!master$).*$/
    commands:
      - pip install --requirement functions/myfunc1/requirements.txt --target functions/myfunc1
      - pip install --requirement functions/myfunc2/requirements.txt --target functions/myfunc2
      - apex deploy --env dev
      - apex deploy --env stg

test:
  override:
    - echo 'ok'

まとめ

  • Apex 本当に便利!
    • API Gateway / DynamoDB なども必要なら Serverless Framework や AWS SAM なども候補になる
  • Apex の --env オプションを使うと Lambda を複数環境にデプロイすることができる
  • 環境変数,IAM ロール,コンピューティングリソースを環境ごとに設定ファイルで変えることもできる

コントリビュート

公式ドキュメントを見ていたら --env の部分が -env になっていて,検索できずハマったので,修正のプルリクを投げたらすぐにマージしてもらえた!やった!

github.com

Lambda を軸にサーバレスを解説した「実践 AWS Lambda」を読んだ

AWS Summit Tokyo 2017 の先行発売でゲットした「実践 AWS Lambda」をさっそく読んだ.Lambda の解説だけではなく,サーバレスの文脈で導入事例が増えてきたアーキテクチャ(ユースケース)の紹介がされていたり,サーバレスのデプロイツールとして AWS SAM の紹介がされていたりして,非常に良書だった.Amazon を見ると,一般発売は明日 6/9 になっていたので,気になる人はすぐに買うと良いのでは!

実践AWS Lambda ~「サーバレス」を実現する新しいアプリケーションのプラットフォーム~

実践AWS Lambda ~「サーバレス」を実現する新しいアプリケーションのプラットフォーム~

Chapter 3 AWS Lambdaの使い方

3-7 バージョニングとエイリアス

Lambda 関数の ARN にバージョンを付与して識別できるのは知らなかった.また,エイリアスを付けて運用できるのも知らなかった.実際に運用している Lambda 関数を見てみたところ,確かにバージョンなしの ARN もあったし,バージョンありの ARN もあった.ちなみに Lambda 関数は Apex でデプロイをしているため,Apex の実装を確認したら自動的に current エイリアスを付与するようになっていた.おおお!

  • arn:aws:lambda:ap-northeast-1:111111111111:function:sample
  • arn:aws:lambda:ap-northeast-1:111111111111:function:sample:$LATEST
  • arn:aws:lambda:ap-northeast-1:111111111111:function:sample:50
  • arn:aws:lambda:ap-northeast-1:111111111111:function:sample:current

docs.aws.amazon.com

3-10 環境変数の利用

暗号化ヘルパーを使うと,環境変数を KMS で暗号化できるのを知った.今のところ,暗号化が必要な環境変数を使っていないため,普通に Apex の project.json でベタ打ちして運用していた.

docs.aws.amazon.com

Chapter 4 プログラミングモデル

4-5 Lambda関数作成時のポイント

特定の言語に依存せず,対応言語全て (Node.js / Python / Java / C#) の解説があるのは素晴らしかった.また Lambda の特性に合ったアーキテクチャに関しては,AWS Summit Tokyo 2017 で講演があった内容とも似ていた.

speakerdeck.com

Chapter 8 サーバレスアプリケーション開発のデプロイ

個人的に1番良かったのは AWS SAM の紹介がされていた点だった.今まで Lambda のデプロイなら Apex を使って,API Gateway が必要なときは Serverless Framework を使っていたけど,AWS から公式に提供された AWS SAM はずっと気になっていてまだ使ったことが無かった.現状サポートされているリソースは Lambda と API Gateway と DynamoDB とのことだが,CloudWatch Events もサポートされると良いなと思う.Apex もここはサポートしていなくて,自動化できなかった.

github.com

本書には記載がなかったけど,AWS SAM で Tracing を設定すれば X-Ray も合わせてデプロイとのこと.気になる!

www.slideshare.net

誤植

初版だからかもしれないけど,typo 系の誤植があって少し気になった.実際に5箇所を発見したため,マイナビに報告をしておいた.確認してもらえれば,以下のサポートサイトに反映されるのかな?と期待している.

book.mynavi.jp

まとめ

  • Lambda を軸にサーバレス全体の理解を改めて整理できた
  • 実際に Lambda + API Gateway + DynamoDB を使うチュートリアルも紹介されていて未経験者にも参考になる内容だった
  • AWS SAM の紹介があり Lambda の運用まで考慮された解説範囲の広さだった

関連記事

先週参加した AWS Summit Tokyo 2017 の参加レポートも参照してもらえればと!

kakakakakku.hatenablog.com

実際に運用している Lambda + Apex の事例も前にまとめていて参照してもらえればと!

kakakakakku.hatenablog.com

Lambda + Apex 事例紹介 ~ 全ては AWS コスト削減のために ~

今日は社内の別プロダクトと合同勉強会があって,Lambda + Apex 便利だよ!という発表をしてきた.

タイトルは「Lambda + Apex 事例紹介 ~ 全ては AWS コスト削減のために ~」で,発表内容としては,大きく3点にフォーカスした.

  • CloudWatch Events + Lambda + CircleCI + Apex で Lambda をサーバレスに実行 & デプロイする話
  • Apex で Golang with Lambda を動かす仕組みとは
  • AWS 便利ツールの紹介

メインは Lambda + Apex の話で,前に書いた記事をベースにした.

kakakakakku.hatenablog.com

発表資料

speakerdeck.com

Golang with Lambda

Apex の珍しい点を挙げるとすると「Lambda で Golang を動かせる」ことだと思う.今回実際に試してみて,理解できた挙動をまとめた.詳しくは発表資料に書いたけど,Node.js から Golang バイナリを動かす子プロセスを生成して,プロセス間通信をすることで実現しているところまで確認することができた.

github.com

github.com

AWS 便利ツール

最後に AWS 便利ツールの紹介をした.awslogs は非常に便利!

github.com

github.com

github.com

github.com

CloudWatch Events + Lambda + CircleCI + Apex で Lambda をサーバレスに実行 & デプロイする

先週,プロダクトで開発合宿を企画して実施してきた.今回のテーマは「開発効率/運用効率の改善」だったので,僕はインフラチームとして先輩と一緒に開発に取り組んだ.お題は「AWS コスト削減」にした.開発合宿で開発したツールで学んだことを簡単にまとめておこうと思う.

Time-based approach

AWS Well-Architected Framework の「コスト最適化」に「タイムベースアプローチ」と呼ばれるベストプラクティスがある.そんな難しいものではなく,単純に開発系インスタンスを夜間や週末に止めることでコストを最適化できるし,クラウドネイティブな設計にもできるというものだ.意外と開発系インスタンスが週末も起動されているチームも多いのではないだろうか?

Time-based approach Examples of a time-based approach include following the sun, turning off Development and Test instances over the weekend, following quarterly or annual schedules (e.g., Black Friday).

今回は「AWS コスト削減」という課題に対して「タイムベースアプローチをサーバレスアーキテクチャで実現する」という手法で解決することをゴールに決めた(実際にはもう少し他の施策も含めてコスト削減をした).

アーキテクチャ図

今回は以下のようなアーキテクチャで実現した.ポイントは大きく3点ある.

  • スケジューリング実行を CloudWatch Events で行った
    • Jenkins を使いたくなかった
  • インスタンスの起動停止を Lambda で行った
    • 専用のインスタンスを立てたくなかった
  • Lambda Function のデプロイを CircleCI + Apex で行った
    • Jenkins を使いたくなかった

f:id:kakku22:20170217220344p:plain

CloudWatch Events

CloudWatch Events を使うと,cron 形式のスケジューリング設定をして Lambda を起動することができる.注意点は2点で「cron 式が AWS 独自なこと」と「UTC 設定なこと」と言える.

例えば「日本時間で “火水木金土” の 00:00」と設定する場合,CloudWatch Events の cron 式は以下のようになる.

0 15 ? * MON-FRI *

  • UTC 表記なので 15:00 になる
  • 曜日指定だと1日戻るため “月火水木金” を指定する必要がある
  • 日(3番目)と月(4番目)の両方に * を指定することができず,片方は ? にする必要がある
  • 6番目に「製造年」を設定する必要がある(必要ないから * にした)

特に ? の部分が意味不明で,設定にハマった.ドキュメントを読んだらちゃんと書いてあったけど,なんなんだろう.「製造年」もよくわからなかった.

cron 式の Day-of-month フィールドおよび Day-of-week フィールドに同じ 値を指定することはできません。 一方のフィールドに値を指定すると、もう一方のフィールドで ? (疑問符) を使用する必要があります。

docs.aws.amazon.com

ちなみに CloudWatch Events から Lambda を実行するときに

  • { "action": "start" }
  • { "action": "stop" }

というイベントを発火させて,Lambda 側でハンドリングするように実装した.

Lambda

あまり難しいことはしてなく,以下の記事などを参考にして,Node で API を叩いてインスタンスを起動したり,停止したりした.

唯一面倒だったのは Zabbix の考慮で,インスタンスを落とすとアラートが鳴ってしまうため,Zabbix のメンテナンスを API 経由で ON/OFF できるようにする必要があった.ここは先輩に書いてもらった.

dev.classmethod.jp

あとは Lambda Function に割り当てる IAM ロールで,以下のように必要最低限に抑えた.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ec2:Describe*",
                "ec2:StartInstances",
                "ec2:StopInstances",
                "logs:*"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}

Apex

今回 Lambda のデプロイもサーバレスにしたかったため,Apex を使った.Apex は Lambda のデプロイに特化していることもあって非常にシンプルで,Serverless のように複雑ではないところが良かった.また Lambda 以外の AWS リソースを操作したい場合は,Terraform を使うということで,無理に手広くサポートしていないところも逆に好印象だった.

github.com

ドキュメントも非常に充実していて,特に困ることは無かった.主に以下のコマンドを使った.

  • apex deploy
  • apex invoke
  • apex logs
  • apex metrics

apex.run

ドキュメントにも載っているが,コマンド補完もすることができるので,便利だった.また Apex に必要最低限な IAM ポリシーもドキュメントに書いてあるため,すぐに使うことができた.

_apex()  {
  COMPREPLY=()
  local cur="${COMP_WORDS[COMP_CWORD]}"
  local opts="$(apex autocomplete -- ${COMP_WORDS[@]:1})"
  COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
  return 0
}

complete -F _apex apex

Apex で1点だけ残念だったのは,CloudWatch Events の設定は Terraform で行う必要があることだった.方針として正しいとは思うけど,CloudWatch Events だけでも良いから Apex で登録できると良いのになとは思った.今回は CloudWatch Events のためだけに Terraform を使う気にはならなかったため,手動で設定して Lambda と紐付けた.

github.com

CircleCI

雑に書いた.ポイントは master にマージしたときに apex deploy をするところ.これで CircleCI から Lambda のデプロイができるようになった.CircleCI にクレデンシャルを登録することを忘れずに!

machine:
  timezone: Asia/Tokyo

dependencies:
  post:
    - curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sudo sh
    - apex version

deployment:
  master:
    branch: master
    commands:
      - apex deploy

まとめ

  • AWS Well-Architected Framework を見るとクラウドネイティブなベストプラクティスが学べる
  • CloudWatch Events + Lambda + CircleCI + Apex で Lambda をサーバレスに実行 & デプロイできるようにした
  • 開発合宿は最高に燃える!

関連記事

kakakakakku.hatenablog.com

独自ドメインの取得が必須だった「JAWS-UG 朝会 #6」に参加して SES + Lambda を試した

「JAWS-UG 朝会」に参加してきた.今回で4回目!

自己紹介をしたときに,主催の @tcsh さんから「朝会の参加ブログを見ましたよー」と言ってもらえて嬉しかった!

jawsug-asa.connpass.com

テーマ

今回のテーマは Lambda BluePrint の "inbound-ses-spam-filter-python" だった.SES で受信したメールが不正だった場合に Lambda 側で Bounce を登録するというテンプレートになっているけど,今回の朝会では時間の関係上,SES で受信したことを Lambda でトリガーして CloudWatch Logs に書き出すところまでとなった.構成図をザックリと書くとこんな感じ.

f:id:kakku22:20160914144715p:plain

ドメイン登録

aws ses verify-domain-identity コマンドで SES の VerificationToken を取得して,TXT レコードを追加した.そして今回はオレゴンリージョンを使ったため inbound-smtp.us-west-2.amazonaws.com に対して MX レコードも追加した.

登録した後に dig txtdig mx で反映されるのを待ちながら,@launcher_test さんに DNS のことを教えてもらったりしていた(いつもお世話になってます!).

事前準備 : 独自ドメインの取得(笑)

勉強会の数日前に「今回の朝会では独自ドメインが必要です」とアナウンスがあって,実は今まで独自ドメインを持っていなくて「まじか!」となった.急遽 kakakakakku.com を Route 53 で取得して問題なく使えた.独自ドメインを持ってない人も多いのでは?と思ってたけど,朝会に参加してる人は全員持っていて,ちょっと驚いたw

資料

今回は資料も多かった!

qiita.com

qiita.com

qiita.com

qiita.com

qiita.com

qiita.com

qiita.com

qiita.com

まとめ

SES やメール関連の知識が全然無くて,知識不足を痛感した会だった.せっかく独自ドメインも取ったし,SES の設定も CLI でできるようになったし,復習して理解を深めようと思っている.

次回 10/24 もまた参加させて頂きます!(VPN ってまた全然知識ないところだ...w)

jawsug-asa.connpass.com

過去に参加した JAWS-UG 朝会

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com