LoginSignup
4
7

More than 3 years have passed since last update.

PythonではじめるAWS CDK

Posted at

Pythonで始めるAWS CDK

最近までいろいろと触る機会があったのと、AWS CDK+Pythonの記事が少なかったので書いてみた。
内容はAWS CDKのインストール〜デプロイまで。ついでにLambda関係でよく使いそうなところをいくつか。

実行環境

  • Python 3.7.4
  • OSX Catalina 10.15.5

Python、Pipが実行可能な環境であることが前提で書いています。

はじめに

AWS CDKってなに?

AWS クラウド開発キットより

AWS クラウド開発キット (AWS CDK) は、使い慣れたプログラミング言語を使用してクラウドアプリケーションリソースをモデル化およびプロビジョニングするためのオープンソースのソフトウェア開発フレームワークです。

かなり大雑把にまとめると、使い慣れたプログラミング言語でAWSのリソースを定義、作成できるIaC(Infrastructure as Code)ツールですよっと。

なんでAWS CDKなの?

環境設定をコードで管理したい。けどterraformとかに手を出すほどでもないし、template.ymlは書きたくない…。何よりAWSの公式!

なんでPythonなの?

(TypeScriptやったことないから…)
LambdaをPythonで書いていたからその延長線上でPythonでやってみた

使ってみた感想

  • 後述するが間接的にCloudFormationを使用しているので、実務で使用する場合はAWS CloudFormation の制限は一読しておくことをお勧めする。
  • リリースは頻繁にされているので日々改善されているようだが、使い込んでいくと正直、現状では痒いところに手が届かない感が否めない。少なくともクロススタック参照はなんとかして欲しい。
  • 調べて出てくるのはTypeScriptがほとんどなので、わざわざPythonを使うメリットはそこまでない

AWS CDKのインストール

Node.jsのインストール

前提として、Node.jsが必要なのでインストールされていない場合はまずこちらをインストールする
なぜNode.jsが必要かというと、AWS CDK自体はTypeScriptで書かれており、Pythonなど他の言語はjsiiというライブラリで自動的にTypeScriptに変換してくれているらしい。すごい。

AWS クラウド開発キットのよくある質問

Q: AWS CDK を使用するために JavaScript ランタイムをインストールする必要があるのはなぜですか?
AWS は、AWS Construct ライブラリパッケージのビジネスロジックを TypeScript で構築し、サポートされている各プログラミング言語へのマッピングを提供します。これにより、AWS CDK コンストラクトの動作が異なる言語間で一貫していることを確認でき、すべての言語で利用できる包括的なコンストラクトパッケージのセットを提供できます。AWS CDK プロジェクトで作成したコードはすべてお客様ご希望のプログラミング言語でネイティブになっています。JavaScript ランタイムはお客様のプログラミング経験の実施詳細です。jsii プロジェクトは https://github.com/aws/jsii で参照できます。

Node.jsのインストール自体は簡単で、Node.jsの公式からインストーラをダウンロード。あとはインストーラに従ってポチポチしていけば勝手にインストールしてくれる。

インストールが完了したらバージョンを確認

$ node -v
v12.18.2
$ npm -v
6.14.5

AWS認証情報の設定

AWS CLIがインストールされている場合はaws configure コマンドを実行すればプロンプトで設定可能だが、わざわざAWS CLIインストールしたくない場合は手動で設定する。

以下はmac or linuxの設定手順。Windowsの場合は%USERPROFILE%\.aws\config%USERPROFILE%\.aws\credentialsを作成し、認証情報、リージョンを設定する

$ mkdir ~/.aws
$ touch ~/.aws/config
$ touch ~/.aws/credentials

エディタで~/.aws/configを開き、以下の通りリージョンを設定し、保存する

[default]
region=ap-northeast-1

エディタで~/.aws/credentialsを開き、以下の通り認証情報を設定し、保存する。

[default]
aws_access_key_id={アクセスキーID}
aws_secret_access_key={シークレットアクセスキー}

AWS CDKのインストール

npmを使用してインストールする

$ sudo npm install -g aws-cdk

バージョンを表示し、インストールされていることを確認。

$ cdk --version
1.52.0 (build 5263664)

デプロイ用S3バケットの作成

cdk bootstrapコマンドでCloudFormationで使用するS3バケットを作成する
これはリージョンごとに実施する必要があるので注意。

$ cdk bootstrap
 ⏳  Bootstrapping environment aws://323617333195/ap-northeast-1...
CDKToolkit: creating CloudFormation changeset...

 ✅  Environment aws://323617333195/ap-northeast-1 bootstrapped.

CDK appを作る

プロジェクトディレクトリを作成

mkdir hello-cdk
cd hello-cdk

cdk initコマンドを実行

cdk init app --language python

実行が終わったらvirtualenvを起動する
(pip3を使用している場合はpip3に読み替えて実行すること)

source .env/bin/activate
pip install -r requirements.txt

pipenvを使用したい場合は、virtualenvを起動せずに.envディレクトリを削除して代わりにpipenvを起動する

S3バケットを作成してみる

pip install aws-cdk.aws-s3

hello_cdk_stack.pyにs3バケットを作成するコードを追加する
(bucket_nameは既存のバケット名と重複するとデプロイ時にエラーになるため、重複しないものへ書き換えること)

hello_cdk_stack.py
from aws_cdk import core
from aws_cdk import aws_s3 as _s3


class HelloCdkStack(core.Stack):

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

        # The code that defines your stack goes here
        bucket = _s3.Bucket(self, "MyFirstBucket", bucket_name="kimi-first-cdk-bucket")

デプロイコマンドを実行

$ cdk deploy
hello-cdk: deploying...
hello-cdk: creating CloudFormation changeset...

 ✅  hello-cdk

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:323617333195:stack/hello-cdk/3497b790-ca3f-11ea-9236-0eb7b90bbf8e

デプロイ完了後にAWSマネジメントコンソールでS3バケットが作成されていることを確認できた

2020-07-20-13-31-33.png

AWSマネジメントコンソールでCloudFormationを開くとhello-cdkというスタックができている。

2020-07-20-14-43-44.png

これはAWS CDKがリソースを作成するのにCloudFormationを使用しているため。
cdk synthコマンドを実行すればCloudFormationテンプレートを出力することもできる。

$ cdk synth

また、作成したリソースを全て削除したい場合はcdk destroyコマンドでスタック単位でリソースを削除することが可能。
ただし、S3バケットなど削除されないリソースが一部あるので注意が必要。

$ cdk destroy

Lambdaをデプロイしてみる

  • 参考までに、今回作成したコードはここに置いてあります。

シンプルなLambda関数をデプロイする

新しいプロジェクトを作成。

$ mkdir cdk-lambda
$ cd cdk-lambda/
$ cdk init app --language python

せっかくなのでPipenvを使ってみる。

$ rm -rf .env
$ rm -rf source.bat
$ rm -rf requirements.txt
$ pipenv shell

必要なパッケージをインストール

$ pipenv install aws_cdk.core
$ pipenv install aws_cdk.aws_lambda

Lambda関数を置くディレクトリを作成し、Lambda関数のPythonファイルを作成

$ mkdir function
$ touch function/index.py

今回はあくまでもサンプルなので、Lambdaのコードは適当

index.py
import json

print('Loading function')


def lambda_handler(event, context):
    print("value1 = " + event['key1'])
    print("value2 = " + event['key2'])
    print("value3 = " + event['key3'])
    return event['key1']  # Echo back the first key value

cdk_lambda_stack.pyにLambda関数を作成するコードを追記

cdk_lambda_stack.py
from aws_cdk import core
from aws_cdk import aws_lambda as _lambda


class CdkLambdaStack(core.Stack):

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

        # The code that defines your stack goes here
        lambdaFn = _lambda.Function(self, "SampleLambdaFunction", 
            code=_lambda.Code.from_asset('function/'),
            runtime=_lambda.Runtime.PYTHON_3_7,
            handler="index.lambda_handler",
            function_name="sample_lambda_function"
        )

いざ、デプロイ!

$ cdk deploy

AWSマネジメントコンソールでデプロイされていることを確認。

2020-07-20-17-50-07.png

Lambda関数に環境変数を設定する

Functionを作成する際にenvironmentパラメータを指定するか、add_environmentメソッドで設定する

cdk_lambda_stack.py
        # 環境変数を追加
        lambdaFn.add_environment(key="STAGE", value="DEV")

2020-07-20-18-15-19.png

s3トリガーを設定する

必要なライブラリをインストール

$ pipenv install aws_cdk.aws_s3
$ pipenv install aws_cdk.aws_s3_notifications

ライブラリをインポート

cdk_lambda_stack.py
from aws_cdk import (
    core,
    aws_lambda as _lambda,
    aws_s3 as _s3,
    aws_s3_notifications,
)

s3バケットを作成し、通知イベントを設定。
今のところ、この方法では既存のS3バケットには設定できない。既存のS3バケットにイベントを設定したい場合はカスタムリソースを使用する。

cdk_lambda_stack.py
        bucket = _s3.Bucket(self, "SampleBucket", bucket_name="kimi-first-cdk-bucket")
        notification = aws_s3_notifications.LambdaDestination(lambdaFn)
        bucket.add_event_notification(_s3.EventType.OBJECT_CREATED, notification, _s3.NotificationKeyFilter(prefix="hoge", suffix=".csv"))

2020-07-20-19-07-57.png

Cloudwatch Eventsから定期的に起動する

必要なライブラリをインストール

$ pipenv install aws_cdk.aws_events
$ pipenv install aws_cdk.aws_events_targets

インストールしたライブラリをインポート

cdk_lambda_stack.py
from aws_cdk import (
    core,
    aws_lambda as _lambda,
    aws_s3 as _s3,
    aws_s3_notifications,
    aws_events as _events,
    aws_events_targets as _targets
)

イベントルールを作成するコードを追加。
今回スケジュール文字列を使用して設定しているが、Schedule.cronSchedule.rateなど別の方法でも指定可能。

cdk_lambda_stack.py
        rule = _events.Rule(self, "SampleEventRule",
            rule_name="schedule_trigger_event",
            schedule=_events.Schedule.expression("cron(10 * * * ? *)")
        )
        rule.add_target(_targets.LambdaFunction(lambdaFn))

2020-07-21-11-18-19.png

参考

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7