✍️

AWS CDKを使ってPythonなLambda関数を作成する【Windows】

2023/07/25に公開

AWS CDKはわたしにとってお初の対面でもないのですが、ガッツリ触って
まあまあ壁にぶちあたりながらなんとか攻略できた(気がする)ので
おばあちゃんになった時の自分のために解説していきます🧓

AWS CDK とは

https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/home.html

AWS Cloud Development Kit (AWS CDK) 開発者ガイドへようこそ。このドキュメントではAWS CDK、コードでクラウドインフラストラクチャを定義し、を通じてプロビジョニングするためのフレームワークについて説明しますAWS CloudFormation。

🫠 「AWS CDK を小学生に分かるように説明してください」

ChatGPTさんの回答
AWS CDK(Cloud Development Kit)は、コンピュータのお話と例えると、
「魔法のレゴブロック」みたいなものです。

みんながブロックを使って、自分だけのすごいお城やロボットを作るように、
CDKもAWSのサービスを使って、自分だけの素敵なウェブアプリケーションや
バックエンドを作れるのです。

例えば、普通にAWSを使うときは、たくさんのコードを書かないといけません。
でも、CDKを使うと、プログラムのコードを「レゴブロック」のように
組み合わせるだけで、すごいシステムが作れるんです。

たとえば、ウェブアプリを作りたい場合、CDKを使うと、
ウェブサーバーやデータベース、セキュリティの設定など、
必要なものが全部そろったウェブアプリのシステムを、
ちょっとしたコードで作れるのです。

CDKは、PythonやJavaScriptなどいろんな言語で使えます。
だから、好きな言語で「魔法のレゴブロック」を使って、
AWSの世界に素敵な作品を作れるんですよ。

そして、それが完成したら、AWSにお願いして実際に動かしてもらえます。
だから、CDKはAWSを使いたい友達にとって、とっても楽しい魔法の道具なのです!

🫠 「AWS CDK は 魔 法 の 道 具 !」

なぜ AWS CDK を使うのか

以前うpした記事では、AWSの画面上から直接Lambda関数を作成しました。

https://zenn.dev/collabostyle/articles/9e62974daa7d79

(↑みてね)

画面からでも簡単に作成することができますが、
AWS CDK を利用するとCloudFormation(※)を使って
効率的におこなうことができます。

※AWSに設定する基本的なアレコレをテンプレ化したり実際に設定できる便利なヤツ

Lambda関数を定期的にメンテナンスしたり、
不具合があって修正をしなければならない時に
画面上から(ソースコード含め)さまざまな設定を
閲覧していくのは大変です🤔

AWS CDKを使ってLambda関数をテンプレ化してしまえば、
なにかあったときに(AWSコンソールを開かずとも!)
VS CodeなどのIDE上からデプロイすることが可能になります✨

必要なもの

AWS CLI

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html

Node.js

https://nodejs.org/ja

AWS CDK

npm install -g aws-cdk

https://www.npmjs.com/package/aws-cdk

Python

https://www.python.org/

CDKっていくぅ

ディレクトリの作成

任意の場所にディレクトリをつくります。

PS D:\study\cdkstudy>

仮想環境を作成

ディレクトリを作成したら、Pythonの仮想環境を作成します。

PS D:\study\cdkstudy> python -m venv .venv

memo:なぜ仮想環境を作成するのか

Pythonはライブラリを読み込む(import)と
全てのプロジェクトで読み込んだライブラリを利用することができます。

でも、プロジェクトごとに利用したいライブラリって違ってきますよね🐰

そのプロジェクトに必要なライブラリだけを使うために、
venvを利用して仮想環境を作成して管理をおこないます!

https://docs.python.org/ja/3/library/venv.html

仮想環境に入る

成功すると、文頭に(.venv)が付きます🗿

PS D:\study\cdkstudy> .\.venv\Scripts\Activate.ps1
(.venv) PS D:\study\cdkstudy> 

逆に、出ていきたいときはdeactivateしてください!

(.venv) PS D:\study\cdkstudy> deactivate
PS D:\study\cdkstudy>

新規プロジェクトを作成

さきほど作成したディレクトリの中に、新規プロジェクトを作ります。

(.venv) PS D:\study\cdkstudy> cdk init app --language python

requirementsをインストールする

CloudFormationでテンプレートを作成する際に必要となるので、インストールしておきましょう。

(.venv) PS D:\study\cdkstudy> pip install -r requirements.txt

以上の操作で、Lambdaをデプロイする準備が整いました!

LambdaへデプロイするPythonファイルを作成する

次に、Lambda関数を実行する際に肝心な
ソースコードを作成していきます。

AWS CDKを使ってLambda関数を作成する場合、
具体的に以下のファイルが必要になってきます🥸

  • スタック
  • Lambdaるときのソースコード

スタック とは

この記事の冒頭から順にAWS CDKっている場合、
現在のディレクトリ構成はこのようになっていると思います。↓

cdkstudy
├── .git        # 隠しファイル
├── .venv
├── cdkstudy
├── tests

最初に作成したディレクトリ名と同じものが
配下につくられていることが確認できますね!

(上記の場合、cdkstudyディレクトリに更にcdkstudyディレクトリがいます)

この同名ディレクトリの中に作成されているファイル、
{ファイル名}_stack.pyスタックです!


こんな感じのファイルが勝手に作成されてるはず

cdkstudy
├── .git        # 隠しファイル
├── .venv
├── cdkstudy
│   ├── __init__.py
│   ├── cdkstudy_stack.py
├── tests

そして、この勝手に作られてるスタックが何に使うのかというと、
Lambda関数を作成するとき、必要な設定などをぶち込むのに必要になってきます。

AWS CDKさんはスタックを見て「どんなLambda関数を作るのか」を判断します。
デプロイするときに実行されるやつ と覚えましょう!

Lambda関数にするPythonファイルを作成する

スタックをいじいじする前に、
Lambdaりたいファイルを作成しておきます。

先に作っておかないと「どんなLambda関数を作るのか」わかりませんし👀

今回はkintoneのREST APIを利用して
データを取得するLambda関数を作成します。

https://cybozu.dev/ja/kintone/docs/rest-api/records/get-record/

Pythonファイルを格納するディレクトリを作成する

冒頭で作成したディレクトリの直下に
任意の名前で新たにディレクトリを作成しましょう🌞

例:「lambda」ディレクトリを作成した場合の構成
cdkstudy
├── .git        # 隠しファイル
├── .venv
├── cdkstudy
├── lambda
├── tests

Pythonファイルを作成する

直前で作成したディレクトリに入れてください!

kintone_lambda.py
import json
import requests

def handler(event, context):
    url = "https://{ドメイン名}.cybozu.com/k/v1/record.json?app={アプリID}&id={レコードID}"
    headers = {
        "X-Cybozu-API-Token": "{kintoneアプリのAPIトークンを入れてね}"
    }

    response = requests.get(url, headers=headers)
    print(response.json())

    return {
        'statusCode': 200,
        'body': json.dumps('AWS CDKって便利だね!')
    }


こんな感じになっているはず

これでデプロイするために必要な
Pythonファイルの作成は完了しました🙆

Lambda関数を作成する

いよいよスタックに書き込んでいきます、、!!ドキドキ
今回は以下の条件でLambda関数を作成します。

  • Lambda Function URLを作成する
  • レイヤーをつっこむ
cdkstudy_stack.py
# import aws_lambda が必要
zendesk_attachment_lambda = aws_lambda.Function(
    self,
    'kintone_lambda', # Lambda関数につっこみたいPythonファイル名
    runtime=aws_lambda.Runtime.PYTHON_3_9,
    code=aws_lambda.Code.from_asset('lambda'), # Lambda関数につっこみたいPythonファイルが入っているディレクトリを指す
    handler='kintone_lambda.handler', # Lambda関数につっこみたいPythonファイル名とメイン関数名
    environment={}
)

Lambda Function URLを作成する

cdkstudy_stack.py
function_url = zendesk_attachment_lambda.add_function_url(
    auth_type=aws_lambda.FunctionUrlAuthType.NONE
)

# import CfnOutput が必要
CfnOutput(self, "FunctionUrl",
    value=function_url.url
)

レイヤーを作成する

🤔「レイヤーってなに?」となった方へ
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-layers.html

REST APIを実行するためにrequestsライブラリを読み込んでいるので、
今回は有志の方が作成されたレイヤーを利用します。

「keithrozario/Klayers」

https://github.com/keithrozario/Klayers

ARNをレイヤーとして登録することで、ライブラリを使えるようになります!
※個人でライブラリをZIP圧縮してS3にうp → ARN取得 → Lambdaへドーンすることもできます。

cdkstudy_stack.py
zendesk_attachment_lambda.add_layers(
    aws_lambda.LayerVersion.from_layer_version_arn(
        self, 'requests',
        '{ARNを取得してつっこんでね!}'
    )
)

各々のコードを切り分けて紹介しましたが、全貌はコチラです。

cdkstudy_stack.py
from aws_cdk import (
    Stack,
    aws_lambda,
    CfnOutput
)
from constructs import Construct

class CdkstudyStack(Stack):

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

        zendesk_attachment_lambda = aws_lambda.Function(
            self,
            'kintone_lambda',
            runtime=aws_lambda.Runtime.PYTHON_3_9,
            code=aws_lambda.Code.from_asset('lambda'),
            handler='kintone_lambda.handler',
            environment={}
        )

        zendesk_attachment_lambda.add_layers(
            aws_lambda.LayerVersion.from_layer_version_arn(
                self, 'requests',
                '{ARNを取得してつっこんでね!}'
            )
        )

        function_url = zendesk_attachment_lambda.add_function_url(
            auth_type=aws_lambda.FunctionUrlAuthType.NONE
        )

        CfnOutput(self, "FunctionUrl",
            value=function_url.url
        )

CloudFormation テンプレートを作成する

ここまでの作成、おつかれさまでした🍟
いよいよLambda関数を作成するための作業に入っていきます!

デプロイをする前に、テンプレ化しておきます。
以下のコマンドを実行してください。

PS D:\study\cdkstudy> cdk synth

エラーなく実行できていれば成功です😏

デプロイしてLambda関数を作成する

以下のコマンドを実行してください。

PS D:\study\cdkstudy> cdk deploy

少し待つと、「本当にデプロイしていいんけ?」と聞かれるので
yを入力して「ええよ~」と返信しておきます。

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


キラキラ祝福される感じになったらデプロイ完了です!

画面で確認してみよう

作成されましたね!
レイヤーやFunction URLもきちんと反映されていました😤

補足:だいじな情報をベタ書きせずに環境変数でつっこむ

ソースコードを確認すると、
kintoneのREST APIを実行するときに必要な情報が
すべてベタ書きで入力されている状況です。


ンヒィ

参照するアプリが変更されるたびにソースコードの内容を
修正しなければなりませんし、大事な情報をベタ書きすることにやばみを感じます。

様々な方法で回避できると思いますが、
今回はLambda関数の「環境変数」を使って
ベタ書きせずに大事な情報を利用していきましょう👻

cdk.json に環境変数に入れたい情報を入力する

新規プロジェクトを作成したときに
ディレクトリ直下にcdk.jsonというファイルが作成されています。

cdk.json
{
  "app": "python app.py",
  "watch": {
    "include": [
      "**"
    ],
    "exclude": [
      "README.md",
      "cdk*.json",
      "requirements*.txt",
      "source.bat",
      "**/__init__.py",
      "python/__pycache__",
      "tests"
    ]
  },
  "context": {...

この中の「context」の中にenvironmentという項目を追加してさらに入力していきます。

cdk.json
  "context": {
  ...
  
     "environment": {
      "kintone-api-token": "{kintoneアプリのAPIトークンを入れてね}"
    }
  }

複数の値を環境変数につっこみたい場合は、
カンマ(,)に続けてジャンジャン追記してください。

デプロイするためにスタックで定義する

次に、デプロイ時に環境変数がうpされるよう
スタックファイルに「環境変数をつっこむ」ことを追記していきます。

まずはcdk.jsonに入力した値を取得します。

cdkstudy_stack.py
environment = self.node.try_get_context("environment")
api_token = environment["kintone-api-token"]

さいごに、aws_lambda.Function()で定義されているenvironmentにつっこみます。

cdkstudy_stack.py
environment = self.node.try_get_context("environment")
api_token = environment["kintone-api-token"]

zendesk_attachment_lambda = aws_lambda.Function(
    self,
    'kintone_lambda',
    runtime=aws_lambda.Runtime.PYTHON_3_9,
    code=aws_lambda.Code.from_asset('lambda'),
    handler='kintone_lambda.handler',
    environment={
        "KINTONE_API_TOKEN": api_token
    }
)
cdkstudy_stack.py
environment = self.node.try_get_context("environment")

if environment == None:
    raise Exception("cdk.jsonにenvironmentが定義されていません。")
if "kintone-api-token" not in environment:
    raise Exception("cdk.jsonのenvironmentに「kintone-api-token」が定義されていません。")

api_token = environment["kintone-api-token"]

以上の実装が完了したら、
さきほどと同じようにcdk synthからのcdk deployでLambda関数に反映させましょう!
※新たなLambda関数は作成されません。既存のものが上書きされます。

Lambda関数をなかったことにしたいとき

あるのか分からないですが、なにかの拍子に
🗿「すべてぶちこわして白紙にしたい」と感じたとき。

バルs的な魔法の呪文がAWS CDKにも存在します。

PS D:\study\cdkstudy> cdk destroy

このコマンドを実行すると
そのスタックに定義して作成されたものすべてが削除されます。

さいごに

AWS CDKを使ってゼロからテンプレート作成し、Lambda関数をつくりました。

テンプレートをするためにスタックを定義したり、
レイヤー作ったりなど慣れるまでは独特な操作に頭をうならせていました💦

でも、慣れればコマンドをたたくだけでLambda関数を作成できるので便利です!

のちのちのメンテナンスなどの負担も減りそうですよね🤡
ただ手順が結構あって読むだけでは理解できない部分が多かったです。
ぜひ、やったことがない方は実践して自分のモンにしてください!!

ではまた🌞

コラボスタイル Developers

Discussion