AWS CDK + LocalStackでAWSサーバレスのローカル開発環境構築した話
はじめに
こんにちは、エアークローゼットでエンジニアをしているNghiaです。
この記事は、エアークローゼット Advent Calendar 2023 の23日目の記事です!よろしくお願いします!
背景
8日目の記事でマイクロサービス認証認可を実現するために、AWSサーバレス使っていることを紹介しました。ほとんどの開発者は最初にCloud Nativeなアプリケーションを作り始める時には、ローカルでも一通りアプリケーション全体を動かせるような開発体験をしたいと思ったことがありますが、簡単には出来ませんでした。
私たちは、アプリケーションが実行される環境とできるだけ類似(理想的には同じ)の環境で開発する必要があります。AWSの環境向けに開発する人は、AWSアカウントが利用可能でないことがあり、また利用できても企業環境のセキュリティのためにリソースを自由に操作できないことがあります。「実験が必要である」と認識していますが、誰もが不必要なリスクを取りたくありません。
ですので、Localstackを使用することで、AWSアカウントのリソースを消費せずに開発時に機能をテストできます。
LocalStackとは
LocalStackは、クラウドアプリケーションを開発するための使いやすいテスト/モックフレームワークを提供しています。これは、ローカルマシン上でテスト環境を起動し、実際のAWSクラウド環境と同じ機能とAPIを提供します。
ローカルマシン上でLambda関数を実行したり、DynamoDBテーブルにデータを保存したり、SQSキューでメッセージのトラフィックを行ったりすることが可能で、クラウドとの通信なしに行うことができます。
メリット
コスト削減です。デプロイメント時には有料のアカウント機能を使用する必要がないため、費用を削減できます。
ローカル環境で機能テストを行う際には、クラウドリソースを無料かつローカルで利用できるため、時間とお金を節約できます。
LocalStackの導入
開発チームはローカル開発でdocker-composeを利用しているので、docker-composeで導入します。
version: "3.8"
services:
localstack:
container_name: localstack
image: localstack/localstack-pro
network_mode: bridge
ports:
- "127.0.0.1:53:53"
- "127.0.0.1:53:53/udp"
- "127.0.0.1:443:443"
- "127.0.0.1:4566:4566"
- "127.0.0.1:4571:4571"
- "127.0.0.1:4510:4510"
environment:
- EXTRA_CORS_ALLOWED_ORIGINS=http://127.0.0.1:19834
- SERVICES=cognito,apigateway,iam,lambda,cloudformation,s3,sts,ssm,secretsmanager,kms,ecr,sns,sqs,stepfunctions
- DEBUG=1
- DATA_DIR=/tmp/localstack/data
- LAMBDA_EXECUTOR=docker-reuse
- DNS_ADDRESS=0
- DOCKER_HOST=unix:///var/run/docker.sock
- LOCALSTACK_API_KEY=${LOCALSTACK_API_KEY}
- HOST_TMP_FOLDER=./.localstack
volumes:
- './.localstack:/tmp/localstack'
- "/var/run/docker.sock:/var/run/docker.sock"
このdocker-compose.ymlファイルを作成し、docker-compose upコマンドでlocalstackをローカルのDocker上に立ち上げることができます。LOCALSTACK_API_KEYはlocalstackのPro(有償)版申請でもらえます。
AWS CDKとLocalStack
AWS CDKとは
AWSを使ったアプリケーションは、多数のサービスを互いに連携することが多く、そのようなサービスのセットアップだったりクラウドリソースの管理だったりが面倒になってきます。
そこでAWSにはAWS CloudFormationというサービスがあり、これを使えば各リソースをテンプレートとして記述でき、このテンプレートからAWSのサービスをプロビジョニングしてくれます。
しかし、AWS CloudFormationのテンプレートを使って複雑なアプリケーションを記述する際に、サービスごとに必要なパラメータや固有の組み込み関数を覚える必要があったりするので、巨大なテンプレートほど管理が難しくなってきます。
そこで、登場するのがAWS CDKで、
AWS CDKを使うことでコードからCloudFormationのテンプレートをビルドすることができます。CloudFormationで覚えるべきものは特に必要なく、プログラミング言語の知識とプロビジョニングしたいリソースの設定が明確になっていれば、CloudFormation知らなくてもIaCできちゃいます。
CDKプロジェクトの作成
普通にnpm install aws-cdk-local aws-cdkしてcdklocal initします。
API GatewayとECSの構築
8日目のマイクロサービス認証認可でHTTP統合構成のイメージは以下のようになります。
CDKのtypescriptコード
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import {
IVpcLink,
Integration,
IntegrationType,
ConnectionType,
IntegrationOptions
} from 'aws-cdk-lib/aws-apigateway';
const createApiGatewayIntegration = (
params: ApiGatewayIntegrateParams
): Integration => {
const {
method,
protocol,
uri,
localPort,
options
} = params;
let integration: Integration;
integration = new Integration({
type: IntegrationType.HTTP,
integrationHttpMethod: method,
uri: `${protocol}://host.docker.internal:${localPort}/${uri}`,
options
});
return integration;
};
const getMeMethodIntegration = this.createApiGatewayIntegration({
method: 'GET',
protocol: 'http',
uri: 'v1/me',
env: prefix,
vpcLink,
nlb,
localPort: port
});
const api = new apigateway.RestApi(
this,
`phoenix-${prefix}-account-authorizer`,
{
description: `phoenix ${prefix} account-authorizer apigw`,
deployOptions: {
stageName: prefix,
tracingEnabled: true
},
// enable CORS
defaultCorsPreflightOptions: {
allowHeaders: [
'Content-Type',
'X-Amz-Date',
'Authorization',
'X-Amz-Security-Token',
'x-amz-content-sha256',
'Withcredentials',
'Cookie'
],
allowMethods: ['OPTIONS', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
allowCredentials: true,
allowOrigins: DisneyConfig[envConfigKey].client.origin
}
}
);
const methodGetMe = this.api.addMethod('GET', getMeMethodIntegration, {
authorizationType: apigateway.AuthorizationType.IAM // <- apigatewayのIAM認証
});
aws-cdk-localを使ってlocalstackにリソースをデプロイ
aws-cdk-local がLocalStackの公式ツールとして存在します。 デプロイする最初の一回のみ以下コマンドを実行します。このコマンドが正常に終了すれば、デプロイすることができます。
cdklocal bootstrap
以下コマンドでデプロイします。
cdklocal deploy
疎通確認
公式ドキュメントに書かれているように、ローカル環境でアクセスする場合は以下のようになります。
apiId
API Gatewayに割り当てられた識別子です。
stageId
API Gatewayのステージ名です。
_user_request_は固定でそのまま含める必要があります。
まとめ
今回は、AWS CDKとLocalStackを使用し、サーバレス環境を構築しました。
正式リリースされたということもありlocalStackコマンドで起動やcdklocalコマンドなどLocalStackでの開発がしやすくなったと感じました。
エアクロではサーバレス開発に挑戦したいエンジニアも積極的に募集中ですので、もしご興味があれば、ぜひ参加してください。->採用サイト
さいごに
最後までご覧いただきありがとうございました🙇♂️
エアークローゼット Advent Calendar 2023はまだ続きますので、ぜひ他のエンジニア, デザイナー, PMの記事もご覧いただければと思います。
次はエンジニアの@tuananhhedspibkさんです!
よろしくお願いします!