苦労しながらAWS CDKをインストールしてGetting Start(Python)した話

AWS CDKのGetting Startを行った際に環境依存でいろいろハマってしまったので対処した内容をまとめました。同じようにハマる人の参考になれば嬉しいです。CDKでIaCガンガンやっていきまっしょい!
2020.02.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、臼田です。

みなさん、IaC(Infrastructure as Code)してますか?(挨拶

今回は私がただ地味に苦労した話を、備忘録としてまとめます。同じようにハマった人の役に立てばいいなーと思います。

AWS CDKとは

AWSが提供するCloud Development Kitで、従来のIaCで利用するCloudFormationとは違いTypeScript、JavaScript、Python、Java、C#/.NETなどの言語でIaCを実現でき、プログラマブルに書ける嬉しいツールです。公式で出してくれているのも嬉しいですね。

本ブログでもCDKについてはたくさんのメンバーが取り上げており、詳細は下記などを見ていただくとわかりやすいです。

AWS CDK が GA! さっそく TypeScript でサーバーレスアプリケーションを構築するぜ【 Cloud Development Kit 】

【コードでインフラ定義】CDKという異次元体験をさくっとやるのに便利なAWS公式Workshopの紹介

でもうまく動かないんや…

CDKを初めるにはWorkshopGetting Startがあります。学習するならまずはこのあたりから手を付けるのがいいです。Python のWorkshopは下記が参考になります。

[AWS CDK入門] CloudFormationをプログラミングで生成!?ワークショップをやってプロジェクト作成からデプロイまでを理解する

今回はGetting Startをやってみました。

しかしながら、私の環境ではすんなりGetting Start出来なかったため、時系列に発生した問題とどのように解決したかを書いていきます。

環境

pyenv + pyenv-virtualenvを利用しています。詳細は下記の通り。

AWS LambdaがPython3.6に対応したのでpyenvとpyenv-virtualenvで環境構築してみた

今回は下記の状態ではじめました。

  • Python 3.6.1
  • macOS 10.13.6
  • npm 6.13.7
  • CDK 1.24.0 (build 6619e36) (インストール後)

インストール

まずはCDKのインストールから始めました。

$ npm install -g aws-cdk
~中略~
+ aws-cdk@1.24.0
$ pip install --upgrade aws-cdk.core
~中略~
Successfully installed attrs-19.3.0 aws-cdk.core-1.24.0 aws-cdk.cx-api-1.24.0 cattrs-1.0.0 importlib-resources-1.0.2 jsii-0.22.0 publication-0.0.3 typing-extensions-3.7.4.1

ここはまだ問題がなかったです。

cdk synthできない…

次にGetting Startのhello worldをやっていきます。

cdk initから新しいアプリを作成します。

$ mkdir hello-cdk
$ cd hello-cdk
$ cdk init --language python
~中略~
## Useful commands

 * `cdk ls`          list all stacks in the app
 * `cdk synth`       emits the synthesized CloudFormation template
 * `cdk deploy`      deploy this stack to your default AWS account/region
 * `cdk diff`        compare deployed stack with current state
 * `cdk docs`        open CDK documentation

Enjoy!

セットアップについて色々出力されるため、順にやっていきます。具体的にはvirtualenvの環境に切り替えてcdkを試しています。

$ python -m venv .env
(.env) $ source .env/bin/activate
(.env) $ pip install -r requirements.txt
~中略~
Successfully installed attrs-19.3.0 aws-cdk.core-1.24.0 aws-cdk.cx-api-1.24.0 cattrs-1.0.0 hello-cdk importlib-resources-1.0.2 jsii-0.22.0 publication-0.0.3 python-dateutil-2.8.1 six-1.14.0 typing-extensions-3.7.4.1
(.env) $ cdk synth
Traceback (most recent call last):
  File "app.py", line 3, in <module>
    from aws_cdk import core
  File "/Users/username/hello-cdk/.env/lib/python3.6/site-packages/aws_cdk/core/__init__.py", line 2047, in <module>
    class DependableTrait(metaclass=jsii.JSIIAbstractClass, jsii_type="@aws-cdk/core.DependableTrait"):
TypeError: __new__() got an unexpected keyword argument 'jsii_type'
Subprocess exited with error 1

ここでエラーになってしまいました。cdk synthがうまく通りません。他のcdk lsなども同様でした。

from aws_cdk import coreをしようとする段階で失敗するようです。

これについては同じようなissueがこちらでも上がっていたり、いくつかの記事でも取り上げられていました。

しかしながら、どれも根本解決はしていなくて、Python 3.7を利用すると同様のエラーが出なくなるというワークアラウンドで対処されていました。今回はpyenvで3.7.4をインストールして切り替えることにより対処しました。

(別ターミナルにて)
$ pyenv install 3.7.4
$ mkdir hello-cdk-with-37
$ cd hello-cdk-with-37
$ pyenv local 3.7.4
$ python --version
Python 3.7.4
$ cdk init --language python
~中略~
Enjoy!
$ python -m venv .env
(.env) $ source .env/bin/activate
(.env) $ pip install -r requirements.txt
~中略~
Successfully installed attrs-19.3.0 aws-cdk.core-1.24.0 aws-cdk.cx-api-1.24.0 cattrs-1.0.0 hello-cdk-with-37 jsii-0.22.0 publication-0.0.3 python-dateutil-2.8.1 six-1.14.0 typing-extensions-3.7.4.1
$ cdk synth
Resources:
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Modules: aws-cdk=1.24.0,@aws-cdk/core=1.24.0,@aws-cdk/cx-api=1.24.0,jsii-runtime=Python/3.7.4
    Condition: CDKMetadataAvailable
~中略~

hellow worldの環境も新しく作り変えて無事すすめることが出来ました。cdk synthを実行するとテンプレートが作成されることが確認できました!

しかしながら次の問題に引っかかるのでした。

cdk deployが通らない…

次にcdk deployを実行します。

$ cdk deploy
Need to perform AWS calls for account 999999999999, but no credentials found. Tried: default credentials.

クレデンシャルが無くて失敗しています。デプロイ先をapp.pyの中で指定していたのですが、そのアカウントのクレデンシャルがない状態でした。

普段はawscliでstsからクレデンシャルを取得するラッパーのコマンドを利用して環境変数にクレデンシャルを設定しているのですが、pyenvで新しく環境を作ったためawscliも入って無くてうまく動かない状態でした。

$ aws sts get-caller-identity
pyenv: aws: command not found

The `aws' command exists in these Python versions:
  3.6.1

というわけでawscliをインストールします。

$ pip3 install awscli --upgrade --user
~中略~
Successfully installed PyYAML-5.2 awscli-1.18.2 botocore-1.15.2 colorama-0.4.3 docutils-0.15.2 jmespath-0.9.4 pyasn1-0.4.8 rsa-3.4.2 s3transfer-0.3.3 urllib3-1.25.8
$ aws sts get-caller-identity
pyenv: aws: command not found

The `aws' command exists in these Python versions:
  3.6.1

変わりません。PATHの問題の可能性もあったので再読み込み。

$ source ~/.bash_profile

それでも変わりませんでした。

ここからめちゃくちゃ試行錯誤したのですが、最終的にvirtualenvから抜けて入り直したら行けました。

$ deactivate
$ source .env/bin/activate
(.env) $ cdk deploy
hello-cdk-with-37: deploying...
hello-cdk-with-37: creating CloudFormation changeset...
 0/3 | 18:38:39 | CREATE_IN_PROGRESS   | AWS::S3::Bucket    | MyFirstBucket (MyFirstBucketB8884501)
 0/3 | 18:38:39 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata
 0/3 | 18:38:41 | CREATE_IN_PROGRESS   | AWS::S3::Bucket    | MyFirstBucket (MyFirstBucketB8884501) Resource creation Initiated
 0/3 | 18:38:41 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata Resource creation Initiated
 1/3 | 18:38:41 | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata
 2/3 | 18:39:03 | CREATE_COMPLETE      | AWS::S3::Bucket    | MyFirstBucket (MyFirstBucketB8884501)
 3/3 | 18:39:04 | CREATE_COMPLETE      | AWS::CloudFormation::Stack | hello-cdk-with-37

 ✅  hello-cdk-with-37

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:999999999999:stack/hello-cdk-with-37/xxxxxxxx-52fb-11ea-b6ef-xxxxxxxxxxxxxx

おそらくpyenvの優先度とvirtualenvの優先度がぶつかってうまく動いていなかった感じなので、環境をリセットするのが大事なんだなーと実感。

しかしこれでCDKが利用できるようになりました!

まとめ

私がCDKを始めた際にハマったことをまとめました。どちらかというと私の環境や進め方に問題があった感じですが、調べてもいい感じの情報が出てこなくて試行錯誤したのでまとめてみました。

CDKを使えばCloudFormationよりも表現の幅が広がり、プログラマブルにIaCできるので夢が広がりますのでこれからもガンガン使っていきたいです!

CDKでアカルイミライヲー!