CDKでインフラとコードを 一緒にデプロイしてみよう(CDKでLambdaをデプロイしてみた)

まえおき

 今週の水曜日に開催されたJAWS-UG 初心者支部の勉強会(#44)に参加した。今回はAWS Builders Online Series recap2 ということで AWS Builders Online SeriesのTrack2 開発者向けAWS入門に関する内容の勉強会だった。私は「CDKでLambdaをデプロイしてみた」をタイトルでLT発表をした。せっかくなので(ブログのアクセスを増やすためにも(笑))ここにもブログ版としても書いてみる。

当時発表した発表版はこちら。


サービス紹介

 デプロイをする前に、今回使うサービスの紹介を簡単にする。

AWS CDKとは

 AWS Cloud Development Kit(AWS クラウド開発キット)と呼ばれ、慣れたプログラミング言語でAWSリソースを定義できるフレームワークである。プログラミング言語が利用できるので、プログラミング言語の知識と表現力を使用できるのが特徴で、例えばCloudFormationでは利用が難しいif文(条件関数があるけど、複雑に作るのは難しい)やfor文を利用できる。また、言語もCDKライブラリについてもエディターの補完が聞いたり、AWSのベストプラクティスがデフォルト値として入っているため、コード記述量が少なくなるというメリットもある。ただし、CDKコードがそのままAWS環境にデプロイされるわけではなく、CloudFormationのテンプレートに変換されて、AWS環境にデプロイされる仕組みとなっている。

AWS CDK紹介ページより(https://aws.amazon.com/jp/cdk/)


AWS Lambdaとは

 AWS Lambdaはサーバーレスでプログラムを実行できるAWSのサービスで、サーバーレスの名前通りにサーバーがないので、インフラ周りのプロビジョニングや管理が不要である。また、リクエスト数に応じて自動スケールしたり、様々なAWSサービスと連携が便利という特徴を持っている。課金もリクエスト数&実行時間という利用した分だけ払えばいい構造となっている。

  AWS Lambda紹介ページより(https://aws.amazon.com/jp/lambda/)
写真をS3バケットに入れるとLambdaがトリガーされて、写真サイズ加工が実行される

 

CDKでLambdaをデプロイしよう!

デプロイの手順

 今回は図のようにシンプルにLambdaだけをデプロイしてみる。

 

以下の4ステップで実施する。また、CDKバージョンはv2.10.0で利用言語はPythonを使った。

  1. CDKプロジェクトを生成する
  2. LambdaをStackに定義する
  3. Lambdaのコードを書く
  4. Let's デプロイ!

 

1. CDKプロジェクトを生成する

プロジェクトフォルダを作成し、CDKプロジェクト(プロジェクト名はCDKLambda)を生成してvenvの仮想環境に入る。

$ mkdir CDKLambda && cd CDKLambda

// CDKプロジェクトを生成
$ cdk init --language python

//仮想環境に入る
$ . .venv/Scripts/activate 

//仮想環境に必要なモジュールをインストール
$ pip install -r requirements.txt 

 cdk init --language pythonでCDKプロジェクトの必要な初期ファイルが生成される。

 また、PythonでCDKを使う場合、venvという仮想環境を生成してプロジェクトで利用するモジュールをインストールする。CDK v1の時はプロジェクト内で利用するサービスごとにモジュールをインストールする必要があったため、requirements.txt などに必要なモジュールを書いてインストールしていた。プロジェクトでCDK関連操作をする場合は、仮想環境に入って実施する。

deactivateで仮想環境から出ることができる。

$ deactivate

 

2. LambdaをStackに定義する

from aws_cdk import (
    Stack,
    aws_lambda as cdk_lambda
)
from constructs import Construct

class CdkLambdaStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        cdk_lambda.Function(self, "simple_lambda",
                            runtime=cdk_lambda.Runtime.PYTHON_3_9, //Lambdaのランタイム
                   //コードがある場所。S3バケットの指定やインラインで書くことも可能
                            code=cdk_lambda.Code.from_asset("resources"),
                            handler="simple_lambda.lambda_handler" //ハンドラーを指定
                            )

 CDK initで生成されたスタックファイルcdk_lambda_stack.pyにLambdaの定義を書いていく。lambdaの定義に必要なaws_lambdaをインポートし、Functionという関数でLambdaを定義する。ランタイム,コードの場所、ハンドラーを指定する。コードの場所について、今回はローカルにあるファイルを指定するためCode.from_asset('ファイルの場所')と書いてあるが、ここはS3バケットやインラインで直接書くこともできる。詳細はドキュメントを参照。

 

3. Lambdaのコードを書く

import json

def lambda_handler(event, context):
    print("Welcome beginner!!")

    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

 上で定義したように、resourcesというフォルダとsimple_lambda.pyを生成して、Lambdaの内部コードを作成する。

今回のコードはLambdaで基本生成されるコードをほぼそのままコピペーしている。

 

4. Let's デプロイ

残りはデプロイだけ!仮想環境(venv)に入り、以下のコマンドを実行する

// 作成されるスタックを確認
$ cdk ls

// AWS CDKのコードからCloudformationのテンプレートを生成(cdk.outフォルダーの中に生成)
$ cdk synth 

// AWS環境でAWS CDKを利用するための初期構築を実施(AWS CDKを環境で初めて利用する時に必要)
// ここで生成されたS3バケットにCloudformationテンプレートやLambdaのコードがアップロードされる
$ cdk bootstrap

$ cdk deploy

 まずはcdk lsで生成されるスタックを確認する。その後cdk synthでCDKコードをCloudFormationのテンプレートに変換する。変換されたファイルはcdk.outというフォルダーの中に保存される。

 また、デプロイする環境が初めてCDKを利用する環境である場合、cdk bootstrapというコマンドでCDKを利用するための初期構築をする必要がある。例えば、cdk-XXXXXXXXX-assets-[account_id]-[region]という名前のS3バケットが生成されるが、このバケットはCDKから変換されたCloudFormationのテンプレートや上で作成したLambdaのファイルなどが保存される用途として使われる。その他にもIAMロールやECRのレポジトリが作成されるようだ。初期構築はCloudFormationよりCDKToolkitというスタック名でデプロイされるので、詳細はそちらを参考するとよいと思う。

 すべての準備ができたら、cdk deployよりデプロイが無事終わったら完了だ。もし、デプロイをするリソースの中で、セキュリティ的に確認が必要なもの(IAMロールの生成など)がある場合、以下のようなメッセージが出る。今回はLambdaの生成時に必要なIAMロールも生成されるため、メッセージが出ている。確認して問題なければ、Yでデプロイを継続しよう。

This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening).
Please confirm you intend to make the following modifications:

IAM Statement Changes
┌───┬──────────────────────────────────┬────────┬────────────────┬──────────────────────────────┬───────────┐
│   │ Resource                         │ Effect │ Action         │ Principal                    │ Condition │
├───┼──────────────────────────────────┼────────┼────────────────┼──────────────────────────────┼───────────┤
│ + │ ${simple_lambda/ServiceRole.Arn} │ Allow  │ sts:AssumeRole │ Service:lambda.amazonaws.com │           │
└───┴──────────────────────────────────┴────────┴────────────────┴──────────────────────────────┴───────────┘
IAM Policy Changes
┌───┬──────────────────────────────┬──────────────────────────────────────────────────────────────────────────────┐
│   │ Resource                     │ Managed Policy ARN                                     │
├───┼──────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ + │ ${simple_lambda/ServiceRole} │ arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole 
└───┴──────────────────────────────┴──────────────────────────────────────────────────────────────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Do you wish to deploy these changes (y/n)? y
 ✅ CdkLambdaStack

 

マネジメントコンソールで確認

 デプロイが完了したので、マネジメントコンソールでCloudFormationとLambdaを確認してみよう。スタックがCREATE_COMPLETE状態で無事デプロイできたことがわかる。

 リソース側を見るとCDK Metadata、Lambda、IAMロールがデプロイされたことがわかる。

 ここで注目したいのはIAMロールで、先ほどLambdaをスタックに定義した際はIAMの定義は書いてなかにも関わらず、CDKではIAMロールを生成している。確かに、マネジメントコンソールでLambdaを作成するときを思い出すと、作成時に、既存または新しいIAMロールを生成する必要がある。このように、AWS CDKではベストプラクティスがデフォルト値として保存されているため、デフォルト値でよければ特に書かなくてもリソースが自動生成される場合がある。もちろん、既存のロールやカスタマイズしたIAMロールをしているすることもできる。

 また、CDK MeatadataはCDK利用の調査と改善のために収集されるデータ(Version reporing)で、オプションでオフにすることもできる(https://docs.aws.amazon.com/cdk/v2/guide/cli.html#version_reporting)。

 

 Lambda側もみると、書いたコードがちゃんとデプロイされていることが確認できる


これで、AWS環境にAWS CDKを利用して、Lambdaとコードをデプロイすることができた。

 

AWS CDKでLambdaのコードをデプロイする時のいいところ

AWS CDK による AWS Lambda コードの管理から、AWS CDKでLambdaをデプロイする利点を書いてみると

  • 本番環境により近い状態を表すことができる

    • AWS環境のすべてをCDKのプロジェクト1つに入れることがでkりう
  • インフラとアプリケーションチームのそれぞれの変更がより可視化できる

  • インフラと同一のデプロイ方法で管理できる

  • インフラとアプリケーションコードを同じ言語で書ける

    • 小さなプロジェクトを開発する際、同じ言語を利用できることで開発のスピードが上がる

という利点がある。

 

おまけ

 今回のLambdaデプロイ時はaws-lambdaというLambdaの基本モジュールを利用していたが、CDKにはその他にもより便利に利用できるLambda関連モジュールがある。

  • aws-lambda-nodejs
  • aws-lambda-go(Experimental)
  • aws-lambda-python(Experimental)
  • aws-lambda-event-source
  • aws-lambda-destinations

例えば、aws-lambda-nodejsを利用すれば、TypeScriptの変換が便利になったりするらしい。詳細はAWS CDKのレファレンスを参照

 また、AWS CDKに関してAWS Builders Online Seriesでは Track 2 「コードを使ったAWS運用のはじめかた」で紹介されている。このセッションではAWS CDKだけではなく、AWS CLI, CloudFormaionといったコードでAWSを運用することができるサービスを紹介して、どの場面でどのサービスが適合しているかも案内しているので、1回視聴してみるといいと思う。

 

感想

JAWSの勉強会で発表するのは初めてで、当日の朝から緊張していたが、終わったあとは達成感がすごかった。また、自分が好きなことについて、周りに話すことは楽しかった。また、実際の業務ではCDKでLambdaを生成したことがないので、自分ためにもいい勉強となった。最後にスナップショットテストについておすすめされたので今後試してみたいと思う。

 

Popular Posts

CloudWatch EventsはAmazon EventBridgeになるらしい

PythonのDict型をDynamoDB形式のJsonに変換する

CloudFormationテンプレート内のStep functionsのState machine定義をS3に置けるようになった