少し前に話題になっていた東京大学の講義資料をやってみたので、内容、感想などメモ。
講義で使用するソースコードはすべて Python で書かれていますが、自分が実際に使うとしたら TypeScript で書くだろうなと思ったので TypeScript で写経しました。
が、CDK のコードはすべて TypeScript で書けましたが、Lambda 関数や動作確認用のスクリプトなどを全て置き換えるところまでは至らず、Python のままです。
写経したリポジトリは https://github.com/zaki-yama-labs/intro-aws に。
学べること
本講義資料には全部で5つのハンズオンがあります。
各ハンズオンで利用する AWS のサービスについては以下の通り。
- 全般
- 3.6.1. CloudFormation による Infrastructure as Code (IaC)
- CloudFormation (紹介のみ)
- 4. Hand-on #1: 初めてのEC2インスタンスを起動する
- EC2
- 付随して、VPC, Security Group(SG)
- 6. Hands-on #2: AWSでディープラーニングの計算を走らせる
- Hands-on #1 と同じ
- 8. Hands-on #3: AWSで自動質問回答ボットを走らせる
- 11. Hands-on #4: サーバーレス入門
- Lambda
- DynamoDB
- マネージド NoSQL データベース
- 12. Hands-on #5: Bashoutter
- 番外編
- SSM: AWS System Manager
- 詳細不明。パラメータの保存先として使ってた
- SSM: AWS System Manager
その他、 7. Docker を用いた大規模機械学習システムの構築 で Docker についての説明があります。
(次の 8. Hands-on #3 で ECS に使用するコンテナイメージとして Docker イメージを使用する)
学べないこと
講義資料の進め方として、基本的にソースコードは GitLab に公開されているものをそのまま使い、手元では CDK のデプロイやスクリプトを実行するぐらいなので、自分でコードを書く場面はないです(CLI を実行してみよう、などを除き)。
そのため、資料をそのままなぞるだけでは上に挙げた AWS の各種サービスの基本的な使い方を学ぶことができる(たとえば、Lambda 関数の書き方がわかる)、というわけではなさそうです。
感想
私の AWS に対する知識が、
3年ぐらい前にこの本を読んだ程度のもので、あとは「Lambda や DynamoDB がどんなものかは知っているが触ったことない、CDK に至ってはどんなものかも知らない...」という感じでした。
特に、↑の本を読んだときも「サーバー構成とかをコードで管理する方法を知りたいなあ」と思った記憶があり、今回 CDK の部分を TypeScript で書き直すことで「AWS のリソースをコードで管理する比較的新しめの方法」を手を動かして学べたのは良かったです。
トラブルシューティング
ここから下は、実際にハンズオンをやっていてハマったところと解決策を残しておきます。
AWS CLI を実行すると "Unknown output type: JSON" エラーで怒られる
たとえば、以下のようなコマンド
$ aws ec2 describe-images --owners amazon Unknown output type: JSON
💡解決策💡
「14.2. AWS CLI のインストール」で、aws configure
実行時に聞かれるDefault output format
は JSON
でなく json
(小文字)を指定するのが正しい。
4. Hands-on #1 で cdk deploy -c key_name="XXX"
するとエラー
💡解決策💡
-c
は context と呼ばれる。
https://docs.aws.amazon.com/cdk/latest/guide/context.html
context はコード中では
const keyName = this.node.tryGetContext('key_name');
という書き方で取り出せるので、これを渡してあげれば OK。
資料の class MyFirstEc2
という Python のコードにはコンストラクタ引数で key_name
を受け取っているが、これは外から渡している。
https://gitlab.com/tomomano/intro-aws/-/blob/master/handson/01-ec2/app.py
6. Hands-on #2 で cdk deploy
するとエラー
2つ問題があった。
1つは
$ cdk deploy -c key_name="XXX" Unable to determine AMI from AMI map since stack is region-agnostic Subprocess exited with error 1
というエラーで、これは region
を渡す必要があった。
Python のコードでは
https://gitlab.com/tomomano/intro-aws/-/blob/master/handson/02-ec2-dnn/app.py
でスタッククラスを定義しているファイル内で渡しているが、TypeScript のコードだと lib/xxx-stack.ts
ではなく bin/xxx.ts
に書く必要があった。
const app = new cdk.App(); new XXXStack(app, 'XXXStack', { env: { region: process.env.CDK_DEFAULT_REGION, account: process.env.CDK_DEFAULT_ACCOUNT, } });
ref. https://github.com/zaki-yama-labs/intro-aws/blob/master/ch06/bin/ch06.ts
2つめのエラーは
You have requested more vCPU capacity than your current vCPU limit of 0 allows for the instance bucket that the specified instance type belongs to. Please visit http://aws.ama zon.com/contact-us/ec2-request to request an adjustment to this limit. (Service: AmazonEC2; Status Code: 400; Error Code: VcpuLimitExceeded; Request ID: *****; Proxy: null)
というもので、どうやら現在は vCPU と呼ばれるものの上限を引き上げてもらうよう AWS への申請が必要らしい。(たぶん。回避策あるのかもしれない)
ref. vCPUベースのオンデマンドインスタンス起動数の制限を試してみた。 | Developers.IO
8. Hands-on #3 で Argument of type 'this' is ...
というエラー
このへんで怒られる。
const table = new dynamodb.Table(this, 'EcsClusterQaBot-Table', ... ^^^^
Argument of type 'this' is not assignable to parameter of type 'Construct'. Type 'Ch08Stack' is not assignable to type 'Construct'. Types of property 'node' are incompatible. Type 'import("/Users/yamazaki/repos/github.com/zaki-yama-labs/intro-aws/ch08/node_modules/@aws-cdk/core/lib/construct-compat").ConstructNode' is not assignable to type 'import("/Users/yamazaki/repos/github.com/zaki-yama-labs/intro-aws/ch08/node_modules/@aws-cdk/aws-iam/node_modules/@aws-cdk/core/lib/construct-compat").ConstructNode'. Types have separate declarations of a private property 'host'.
💡解決策💡
@aws-cdk/core
とそれ以外のパッケージのマイナーバージョンがずれてた (coreが 1.63.0
、それ以外が ^1.64.1
)。
バージョンを揃えたら解決。
8. Hands-on #3 で run_task.py
を実行したらエラー
$ python run_task.py ask "A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro." "What is the name of the baby?" Traceback (most recent call last): File "run_task.py", line 173, in <module> ask(args.context, args.question) File "run_task.py", line 22, in ask P = Params() File "run_task.py", line 12, in __init__ self.ECS_CLUSTER_NAME = ssm_client.get_parameter(Name="ECS_CLUSTER_NAME")["Parameter"]["Value"] File "/Users/yamazaki/repos/github.com/zaki-yama-labs/intro-aws/ch08/.venv/lib/python3.8/site-packages/botocore/client.py", line 337, in _api_call return self._make_api_call(operation_name, kwargs) File "/Users/yamazaki/repos/github.com/zaki-yama-labs/intro-aws/ch08/.venv/lib/python3.8/site-packages/botocore/client.py", line 656, in _make_api_call raise error_class(parsed_response, operation_name) botocore.errorfactory.ParameterNotFound: An error occurred (ParameterNotFound) when calling the GetParameter operation:
💡解決策💡
ECS_CLUSTER_NAME
などは SSM に保存していた。
https://gitlab.com/tomomano/intro-aws/-/blob/master/handson/03-qa-bot/app.py#L76-101
同様にSSMに保存するようにして解決。