📑

AWS CDK学習の始め方

2023/02/17に公開

2022年末頃からAWS CDKを使い始め、その実用性に感動している。
IaCのコンセプトを体現しているなーと言う印象を受けた。

自習メモの他にもオンライン勉強会もぼちぼち拝見しているため、今後はそれらの覚え書きもしていきたい。

AWS CDK仕様まわり

CDK CLI

CLIツールcdkと実装で使う各言語のライブラリは別々なので、バージョン不一致であればcdk実行時にエラーで教えてくれる。

私はv0.2あたりのプレビューをインストールしっぱなしの環境でCDKを再開したので下記エラーが発生した。CLIを最新バージョンするだけでOK。

This CDK CLI is not compatible with the CDK library used by your application. Please upgrade the CLI to the latest version.
(Cloud assembly schema version mismatch: Maximum schema version supported is 22.0.0, but found 29.0.0)

ベストプラクティス色々

StackConstructの扱いに関しては既に各所で共有されているが、一通りはAWSブログにまとまっているので一読がおすすめ。
https://aws.amazon.com/jp/blogs/news/best-practices-for-developing-cloud-applications-with-aws-cdk/

「Constructのベストプラクティス」は正しい使い方に重要。
AWS CDKは言語ライブラリなので、CloudFormationとは段違いの自由度がある分、簡潔に維持する努力が必要でアプリ開発と同じ姿勢が必要になってくる。(CFnテンプレートの知識は使わないし忘れた方が良い)

個人的にはスタック間参照(CFnで言うOutputs)から解放されるところが嬉しい。テンプレートが大きく育っても可読性を維持できそう。
SSMパラメータ使わずとも、大抵のケースでは(Pythonにおける@propertyのように)Constructのクラス変数をイミュータブルに参照すればOutputsの代用に十分なはず。

学習ネタ

JAWS-UG CDK支部

https://jawsug-cdk.connpass.com

一度参加したら面白かったのでまた参加しよう。

AWS CDK for LocalStack

AWS CDKをlocalstackで動作させれば学習環境に最適だな、と思って使い始めたら最初のbootstrapでエラーに遭遇した。
--endpoint-urlの切り替えだけで動く想定だったが過去issueを見回っても解決できなかったため自分でissueに追加したところ、nodeバージョンに起因するIPv6の問題だったことが判明。

またipv6か...と言う気持ちはあるけれど解決策を調査&リリースしてくれたJoelさんにはすごく感謝している。issueあげて良い経験ができました。
https://github.com/localstack/aws-cdk-local/issues/76

実際に使っての感想

IaCとソースコードを分離しつつ一括管理できる

自分にIaCという概念が足りてなかったなーと実感できた。
例えばLambda関数をデプロイしたい場合、CFnテンプレートではCodeステートメントを使ってテンプレート内にソースコードを埋め込む必要があった。(それが無理で個人的には一度も使ったことがない...)

AWS CDKではテンプレートもオブジェクトなのでソースコードを読み込んで引数に使えばOK、と言うシンプルさが通用する。

  • Construct記述例: 構築リソースの定義
from aws_cdk import (
    aws_lambda as lambda_,
    aws_iam as iam,
)
from constructs import Construct


class Summarizer(Construct):
    def __init__(self, scope: Construct, construct_id: str, **kwargs):
        super().__init__(scope, construct_id, **kwargs)

    lambda_role = iam.Role(self, "lambdaRole",
        role_name="LambdaRole-dev",
        assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"),
    )
    lambda_role.add_managed_policy(iam.ManagedPolicy.from_aws_managed_policy_name('service-role/AWSLambdaBasicExecutionRole'))

    with open('./src/index.py', 'r') as src:
        src_code = src.read()

    function = lambda_.CfnFunction(self, 'functionQuery',
        code=lambda_.CfnFunction.CodeProperty(
            # image_uri="imageUri",
            # s3_bucket="s3Bucket",
            # s3_key="s3Key",
            # s3_object_version="s3ObjectVersion",
            zip_file=src_code,
        ),
        role=lambda_role.role_arn,
        description='###',
        environment=lambda_.CfnFunction.EnvironmentProperty(
            variables={
                'TZ': 'Asia/Tokyo',
            }
        ),
        # 後略
  • Stack記述例: 構築リソースの順序やパラメータの定義
from aws_cdk import (
    Stack,
    Aws,
)
from constructs import Construct

from .database import DataBase
from .function import Summarizer


class CdkStack(Stack):

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

        accountId = Aws.ACCOUNT_ID
        database = 'cdk_default'
        tableName = 'table'
        data_location = 's3://**'
        glue_config  = {
            "db_name": database,
            "table_name": tableName,
            "location": data_location,
        }

        database = DataBaseCUR(self, "database", glue_config)

        summarizer = Summarizer(self, "Query")
        # 後略

開発者がインフラレイヤも管理しやすくする

現状ではSREチームがインフラレイヤをIaC構築しても、IaCごと開発チームに保守してもらうことは難しかった。巨大なプレーンテキストのテンプレート設定を理解してね、とも言いづらいし実際にデメリットも大きい。

AWS CDKのように一つの言語ライブラリになれば、ソースコードと同じ言語を採用してIaCを記述できて開発チーム自身がインフラレイヤを理解しやすくなる。

その段階に来たらSREチームはIaCを委任すれば良いが、SREの仕事としてはバリデーションなどの共通コンポーネントを実装することが重要になると感じている。

企業によっては自社サービスの共通機能(ex. 認証や決済)を内製化してプロダクト開発の品質と速度を上げる取り組みを見かけるので、AWS CDKによるIaC管理でも同様のアプローチは大切になりそう。

Discussion