このリポジトリは AWS ハンズオン資料 の サーバーレスアーキテクチャで翻訳 Web API を構築する を参考に Terraform と Serverless Framework で書き直したものになります。
このリポジトリには大きく分けて3つ目的があり作成しています。
- Terraform と Serverless Framework の相互連携
- サーバーレスアーキテクチャーの Infrastructure as Code(IaC)化
- ローカル環境にてサーバーレスアーキテクチャーのエミュレートしながらの開発を可能にする
基本的にはハンズオン資料で作成したものとほぼ同じになるように作成していますが一部 Lambda レイヤーを導入していたりと少し違っています。
AWS のリソースは Terraform で管理されているものと Serverless Framework で管理されているものがあります。
Terraform の tfstate ファイル(現在の状態を表すファイル)は複数人で開発することを想定しているため AWS S3 に保存して開発を行います。
また Serverless Framework もデプロイするために AWS S3 を使用する(CloudFormation, Lambda のコードを zip化されたものなどを指す。 .serverless フォルダ配下に作成されているファイル群)ため作成が必要です。
S3 の作成後、Terraform と Serverless Framework の設定を順番に行っていきます。
Terraform と Serverless Framework の連携のため、 設定する順番がとても重要 になってきます。 必ず Terraform から設定をする必要 があります。
S3 作成用のシェルスクリプトがあるため、基本的にはそのシェルスクリプトを実行するだけで大丈夫です。
AWS CLI を使用してバケットを作成するので、 AWS CLI が実行できる状態にしておいてください。
必ず profile の指定が必要なので profile の作成も行う必要があります。
profile の作成方法に関しては以下のコマンドを実行してください。
$ aws configure --profile terraform
実際に S3 作成用のシェルスクリプトを実行した時の例になります。
dodonki1223🐻: ~/project/translate on 🌱 main [📝🤷✓] took 10s
└─> bin/init_s3.sh
S3バケット作成で使用するprofile名を入力してください: terraform
tfstateもしくはServerless FrameworkのデプロイS3バケット名を入力して下さい: translate-sls
translate-slsの作成を行います
make_bucket: translate-sls
translate-slsにバージョンニングを有効化に成功しました
translate-slsにサーバー側の暗号化を有効化に成功しました
translate-slsのアクセスの変更に成功しました
このリポジトリでは profile 名と バケット名は固定でソースコードに書かれているので適宜変更してください。
設定名 | 設定値 |
---|---|
AWS の profile 名 | terraform |
tfstate の格納バケット | translate-terraform |
Serverless Framework デプロイ用バケット | terraform-sls |
ローカル環境であっても Serverless Framework と連携 するために AWS Systems Manager Parameter Store を使用する必要がある ため、予め開発用のパラメータをセットしておく必要があります。
なので Serverless Framework の開発を始める前にまずは AWS に必要なリソースを Terraform を使って作成していきます。
これからの作業は terraform のディレクトリで行う ので必ず移動してください。
$ cd translate/terraform
asdf などのパッケージマネージャーを使用して Terraform をインストールして使える状態にします。
# terraform の plugin を追加する
$ asdf plugin add terraform
updating plugin repository...remote: Enumerating objects: 41, done.
remote: Counting objects: 100% (41/41), done.
remote: Compressing objects: 100% (36/36), done.
remote: Total 41 (delta 22), reused 14 (delta 5), pack-reused 0
Unpacking objects: 100% (41/41), 40.13 KiB | 334.00 KiB/s, done.
From https://github.com/asdf-vm/asdf-plugins
8ef69e3..fe90d7a master -> origin/master
HEAD is now at fe90d7a feat: add asdf-gcc-arm-none-eabi plugin (#565)
# terraform をインストールする
$ asdf install terraform
terraform 内で使用している plugin などのバイナリファイルをダウンロードします。
$ terraform init
環境の切り分けについてはそれぞれの環境で差異があるわけではないので workspace を使うことを前提としています。
dev, stg, prod の環境をそれぞれ作成しておくと良いでしょう。
注意:workspace は必ず dev
環境を作成しないとローカル実行もできないです!
$ terraform workspace new dev
Created and switched to workspace "dev"!
You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration.
$ terraform workspace select dev
Switched to workspace "dev".
$ terraform apply -parallelism=30
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
・
・
・
Apply complete! Resources: 7 added, 0 changed, 0 destroyed.
Serverless Framework は基本的に Docker で開発を行うため、Docker が使える状態にしておいてください。
これからの作業は serverless のディレクトリ で行うので必ず移動してください。
$ cd translate/serverless
テンプレートファイルをコピーし環境変数を設定します。
$ cp .docker/.env.sample .docker/.env
環境変数名 | 説明 |
---|---|
AWS_ACCESS_KEY_ID | IAM ユーザーまたはロールに関連付けられる AWS アクセスキー |
AWS_SECRET_ACCESS_KEY | AWS アクセスキーに関連付けられているシークレットキー(AWS アクセスキーのパスワードのこと) |
AWS_REGION | profile 設定のリージョン設定 |
DYNAMODB_LOCAL_PORT | ローカルで実行している DynamoDB Local へアクセスするためのポート番号 |
Docker のコマンドを実行し開発環境を立ち上げます。
$ docker-compose up
・
・
・
offline_1 | Server ready: http://0.0.0.0:3000 🚀
http://localhost:3000/dev/translate?input_text=おはよう へアクセスし Good morning
と返ってくれば API Gateway, Lambda, DynamoDB のローカル実行が出来ています。
また http://localhost:8001 にアクセスし dynamodb-admin が表示されていることも確認しておきましょう。
これでローカルの環境構築完了です!
開発に入る前にまずはこのリポジトリでの Terraform と Serverless Framework についての説明をします。
AWS のリソースに関しては Terraform が管理しているもの と Serverless Framework が管理しているもの があります。
Terraform が管理しているリソースは IAM ロール, パラメータストア になります。
権限は Serverless Framework で管理せずに Terraform で管理しています。
Serverless Framework が管理しているリソースは API Gateway, Lambda, DynamoDB, CloudWatch Logs になります。
Terraform と Serverless Framework の連携に関してですが 「Terraform → Serverless Framework」 と 「Serverless Framework → Terraform」 の2種類がありそれぞれちゃんと連携を考えないといけません。
連携するためにデプロイ順もちゃんと考慮する必要があるのでどうやって連携するのかということだけをちゃんと理解出来るようになっていれば応用がきくのでしっかりと概念を頭に入れておくとよいでしょう。
このリポジトリでは「Terraform → Serverless Framework」の連携だけ実装されています。ただしサンプルとして「Serverless Framework → Terraform」も連携出来ることも確認済みなのでいつでも連携可能です。
Serverless Framework の公式サイトに Terraform との連携方法について書かれている記事がありそれを参考にして連携しています。
Terraform で作成したリソースの arn をパラメータストアに設定し設定したパラメータストアから arn を取得して Serverless Framework で使用します。
serverless.yml のソースコード上だと以下のような記述で連携しています。
custom:
iamRoleName: ${ssm:/translate/iam_role/lambda_function_${sls:stage}}
詳しくは以下の記事を参考にしてください。
Serverless Framework は CloudFormation を使用してデプロイするので CloudFormation が出力した output を使用して Terraform で連携させます。
aws_cloudformation_export を使用することで CloudFormation が出力した情報を読み込むことができるようになるので Terraform でも連携が可能になります。
data "aws_cloudformation_export" "lambda_function_arn" {
name = format("lambda-function-arn-%s", terraform.workspace)
}
開発は Terraform と Serverless Framework によって方法が違うため、注意して下さい。
Serverless Framework に関しては複数の開発方法があるため、好みによって使い分けて下さい。
開発環境の構築が終わっていればそのまま開発することができます。
Terraform の開発は translate/terraform
のディレクトリに移動し、Terraform の通常通りの開発と同じく terraform init
, terraform plan
, terraform apply
などのコマンドを使用して開発を行って下さい。
Serverless Framework の開発は2通りあります。
Docker のコンテナ内で開発することは変わらないのですが、VSCode を使った Remote Containers での開発 と 開発用のコンテナにログインして開発 する方法があります。
Serverless Framework の開発は translate/serverless のディレクトリに移動して開発を行います。
DynamoDB Local が M1 Mac だと動作しなかった ため仕方なく Docker 化して開発することにしました。 DynamoDB Local で使用されている SQLLite のライブラリが arm64 に対応していないため M1 Mac での動作が出来ないためです。
ただ現在では Serverless Framework で DynamoDB Local を使用する plugin が Docker に対応した ため Docker 化しなくても動作するようになった(未検証です)かもしれません。
VSCode の拡張機能である Remote Containers を予めインストール しておいてください。
gif を見る通り Remote Containers を使用し offline コンテナを起動して offline コンテナ内で開発を行います。
docker-compose.yml に開発用のサービスを定義してあります。
docker-compose up
のコマンドでは立ち上がらないように profiles の指定をしているので明示的に開発用のサービスを指定することで開発用のコンテナが立ち上がります。
$ docker-compose run --rm runner
デプロイは Terraform と Serverless Framework の2つがあります。
このリポジトリではデプロイ順はすごく大切なことなので 必ずデプロイ順を間違えず に行いましょう。
Serverless Framework は Terraform のリソースに依存 しています。なのでデプロイする時は 必ず Terraform から行う必要 があります。
Serverless Framework からデプロイしようとするとエラーになり失敗します。
デプロイ環境ですが、以下の環境を想定して作成してあります。
環境 | 説明 |
---|---|
dev | 開発環境 |
stg | ステージング環境 |
prod | 本番環境 |
まずは terraform ディレクトリに移動して下さい。
$ cd translate/terraform
デプロイ対象の workspace を選択します。
$ terraform workspace select prod
Switched to workspace "prod".
デプロイコマンドを実行します。
$ terraform apply -parallelism=30
Terraform によるデプロイはこれで終了です。
まずは serverless ディレクトリに移動して下さい。
$ cd translate/serverless
開発用コンテナを実行します。
$ docker-compose run --rm runner
デプロイコマンドを実行します。
--stage xxx
のパラメータを元にどの環境にデプロイするかが決まります。
開発環境はローカル実行する時に DYNAMODB_ENDPOINT
が http://localhost:${env:DYNAMODB_LOCAL_PORT}
になるようにしているため、デプロイ時は明示的に DYNAMODB_ENDPOINT
を指定することでデプロイを行います。
# 開発環境へのデプロイ
$ DYNAMODB_ENDPOINT=https://dynamodb.ap-northeast-1.amazonaws.com yarn deploy --stage dev
# ステージング環境へのデプロイ
$ yarn deploy --stage stg
# 本番環境へのデプロイ
$ yarn deploy --stage prod
Serverless Framework によるデプロイはこれで終了です。
ちなみにですが AWS ハンズオン資料 に AWS SAM を使ってテンプレートからサーバーレスな環境を構築する というハンズオン資料が既にあり SAM を使用して Infrastructure as Code(IaC)化されています。