友人とペアプロでWebアプリを作る過程の記録
概要
以下の目的があり、エンジニアの友人を誘ってペアプロでWebアプリを作ることにしました。
- 業務外でなにかアプリを作りたい
- システム構成やアーキテクチャ構築レベルから考えてアプリを作りたい
- ペアプロによって生産性が上がるかを確かめたい
- サーバレスなアプリを作りたい
- 今ある知識でどの程度のアウトプットを作れるか確かめたい
作業過程を書き連ねていきます。
参加者一覧
HN(敬称略) | 業界歴(開始時点) | 技術スタック | 備考 |
---|---|---|---|
ねおさん | 4年弱 | 業務ではAWS, Java, Vue, TypeScript / 業務外ではAtCoder Algo(茶), Rust | 筆者 |
Teru | 5年弱 | Java, VB.NET / 業務外ではVue |
作るもの
メンタリストDaigo氏の著書「コミュ障でも5分で増やせる超人脈術」で紹介されていた、
「ネットワークマップ」の作成と管理を容易にするアプリ
ユーザ自身の周辺人物情報を入力し、以下を表形式で出力できるもの
- 自分にとっての重要人物(VIP)
- そのVIPを紹介してくれた人物(Broker)
- 自分がそのVIPを紹介した相手(Connect)
1回目
以下をざっくり4時間で行った。
- 作成物の目的の説明
- ペアプロのメリットなどを説明
- レビューの手戻りをなくせる
- 会話しながらの作業により、モチベーションを維持
- お互いの知見・考えをその場で共有できる
- 技量に差がある場合、互いにノウハウを得られる
- ペアプロのルール決め
- discordの画面共有で行う。
- 25分ごとに5分休憩し、ドライバーとナビゲーターを交代
- 4サイクルごとに20分休憩
- 各種ツール決め
- Notionでタスク管理
- 必要なドキュメンテーションはGoogleスプレッドシート
- システム構成作成
- Notionアカウント作成
- TerraformCloudアカウント作成
システム構成について
AWSベースで作成することにした。
想定しているシステム構成は以下の感じ
フロントエンド
- AWS WAF
- Route53
- CloudFront
- S3
- Reactのアーティファクトを載せる
バックエンド
- API Gateway
- Lambda
- Rustで実装
- Cognito
- SES
- 人脈見直しリマインダ機能を想定
DB
※暫定
Aurora Serverless ※v1かv2かは未定- TiDB Serverless
CI/CD
- CodeCommit
- CodeBuild
- CodeDeploy
- CodePipeline
運用保守系
- CloudWatch
- SystemManager
- SecretsManager
ここまでで思ったこと
こうして書いてみると、
アーキテクチャレベルから考えたことがなく感覚でやっているので、
アーキテクチャ設計やモデリングなどは体系的に学習した方がいいかなと思った。
2回目までの下準備
制作用のAWSアカウントを作成
私個人のAWSからOrganizationsを有効化し、
作るアプリの開発と本番環境用のAWSアカウントと、
Identity Centerでそれらアカウントにログインできるユーザを作成
これに伴い、私個人用のIAMユーザを削除し、Identity Centerで作成したユーザを使用することにした。
第二回
以下をざっくり2時間で行った。
ローカル環境の有無について議論
動確のたびに開発環境を使用する場合、デプロイのロードタイムが長いため
結果、必要ということに
CodeCommitリポジトリ作成
以下四つのリポジトリをCodeCommitに作成
- フロント用
- バックエンド用
- インフラ用
- ローカル環境DB
- DockerでローカルにPostgreSQLを構築する想定
aws-cliの設定, CodeCommitリポジトリのクローン
IdentityCenterを使用しているので、下記の手順を参考にクローン
バックエンドのプロジェクトの初期化
serverless install --url https://github.com/softprops/serverless-aws-rust
フロントエンドのプロジェクト初期化
npx create-react-app . --templete typescript
第三回
ざっくり1.5時間で以下を行った
dev環境作成準備
devを作ってからそれに合わせてローカルを作るべきと判断
dev環境作成にあたり、以下の流れをとる
- 試しにdev環境にterraformからs3バケットを作成する
- terraformとcodebuildでdev環境にリソースをつくるパイプラインをつくる
- devのリソース一式をつくる
1 試しにdev環境にterraformからs3バケットをつくる
dev環境のawsアカウントから仮のterraform用IAMユーザを作成
tfbuckendファイルを作成
bucket = ****
key = "****dev.tfstate"
region = "ap-northeast-1"
profile = ****
tfvarsファイル作成
project = ****
environment = "dev"
domain = ""
terraform init
terraform init -reconfigure -backend-config="backend/dev.tfbackend"
# ------------------------
# - Variables
# ------------------------
variable "project" {
type = string
}
variable "environment" {
type = string
}
variable "domain" {
type = string
}
# ------------------------
# - Terraform configuratoions
# ------------------------
terraform {
required_version = ">1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~>3.0"
}
}
}
# ------------------------
# - Provider
# ------------------------
provider "aws" {
profile = ****
region = "ap-northeast-1"
}
# -------------------
# S3 static bucket
# -------------------
resource "aws_s3_bucket" "s3_test_bucket" {
bucket = "test-bucket-${var.project}-${var.environment}"
}
terraform apply
terraform apply --auto-approve -var-file vars/dev.tfvars
↓
tfstateがローカルに作成された
init時にwarnが出ていたのを見落としていた...
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v3.76.1
╷
│ Warning: Missing backend configuration
│
│ -backend-config was used without a "backend" block in the configuration.
│
│ If you intended to override the default local backend configuration,
│ no action is required, but you may add an explicit backend block to your
│ configuration to clear this warning:
│
│ terraform {
│ backend "local" {}
│ }
│
│ However, if you intended to override a defined backend, please verify that
│ the backend configuration is present and valid.
│
╵
main.tfにbackendの設定を記載したら解決
# ------------------------
# - Terraform configuratoions
# ------------------------
terraform {
required_version = ">1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~>3.0"
}
}
+ backend "s3" {
+ bucket = ****
+ key = "****dev.tfstate"
+ region = "ap-northeast-1"
+ profile = ****
+ }
}
↓
必要な設定は.tfbackend
に記載しているので空のブロックでもよかった。
# ------------------------
# - Terraform configuratoions
# ------------------------
terraform {
required_version = ">1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~>3.0"
}
}
+ backend "s3" {
+ }
}
DBに関する議論
Aurora Serverlessの問題点
データ層にAurora Serverlessを使うと考えていたが、以下の問題が発覚。
- Aurora Serverless v2は非使用時にキャパシティ(ACU)を0にすることができない。最低0.5ACU
- 東京リージョンで 1ACU/h あたり0.2 USD
- 0.5ACUを一ヶ月換算で 0.1USD * 24h * 30d * 150 JPY/USD = 10800JPY / M
- 個人開発で使うにはあまりにも高い
- Aurora Serverless v1は2024年中にサービス終了する
- 少なくともコンソールから新規作成はできなかった。
https://aws.amazon.com/jp/rds/aurora/pricing/
- 少なくともコンソールから新規作成はできなかった。
代わりのDBを考える
代替案
- DynamoDB
- CockroachDB Serverless
- TiDB Serverless
DynamoDB
- メリット
- リソースをAWS内部で完結させることができる。
- 従量課金制のため、個人開発の範疇では破茶滅茶な料金にはならないはず
- デメリット
- DynamoDB特有のデータ設計が必要
CockroachDB Serverless
Free for use up to 10 GiB of storage and 50M RUs per organization per month.
- メリット
- NewSQL。Google Spannerのクローン
- PostgreSQL互換のIF
- 無料枠が大きい
- SQLの知識を使用できる
- デメリット
- リソースをAWS内で完結できない
- LambdaからCockroachDBを使用する際のコネクションなどの検証が必要
TiDB Serverless
各組織で作成された5つのクラスタを無料で使用することができます。6つ目のクラスタを作成する場合は、クレジットカードを追加し、使用限度額を設定する必要があります。6つ目のクラスタを作成する前に、既に作成したクラスタをいくつか削除した場合、新しいクラスタは無料枠のクラスタとカウントされ無料となります。
上記の条件を満たしたTiDB Serverlessのクラスタに対して、毎月フリークォータが発行されます。無料枠を利用することで、お客様は1ヶ月間、行ベースのデータ5GiBと列ベースのデータ5GiBを同時に保存し、5,000万RUを消費することができます。これらのクォータを自由に割り当てて、同等の運用を実現することも可能です。
- メリット
- NewSQL
- MySQL互換のIF
- 無料枠が大きい
- SQLの知識を使用できる
- Cockroachと比較してQiitaなどに情報が多そう(雑感)
- デメリット
- リソースをAWS内で完結できない
- LambdaからTiDBを使用する際のコネクションなどの検証が必要
結論
TiDB Serverlessを検証する方向性で一致
第四回
3時間で以下を行った。
dev環境Infraパイプライン作成
Codebuildプロジェクト作成
infraブランチのbuildspec.yml
を以下のように設定
version: 0.2
env:
variables:
TERRAFORM_VERSION: "1.7.5"
phases:
install:
commands:
- curl -sL https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip > terraform.zip
- unzip terraform.zip
- mv terraform /usr/local/bin/
pre_build:
commands:
- terraform init -backend-config="backend/${ENVIRONMENT}.tfbackend"
- terraform validate
- terraform plan -var-file vars/${ENVIRONMENT}.tfvars
build:
commands:
- terraform apply --auto-approve -var-file vars/${ENVIRONMENT}.tfvars
{環境名}.tfvars
と{環境名}.tfbackend
を使用するため、
環境変数で{環境名}を渡すように指定
また、Codebuildのサービスロールを使用するため、各.tfbackend
からprofileの設定を削除した。
bucket = ****
key = "****dev.tfstate"
region = "ap-northeast-1"
- profile = ****
以下は調査と試行錯誤しながら調整した。
- pre_buildフェーズのterraformのインストール
- CodeBuildのサービスロール
- 初期設定の場合にinitが落ちることを確認し、backendのS3バケットへのアクセス許可を追加
- backendのS3バケットへのアクセス許可だけ追加したとき、applyが失敗することを確認し、必要なサービスへのアクセスを許可
CodePipelineを作成
infraリポジトリのdevelopブランチの変更を検知し、
自動的にビルドプロジェクトを実行させるようにした。
次回の予定
AWSアカウントを分割しているPRD環境のInfraパイプラインを作成する。
PRD環境アカウントにCodeBuildプロジェクトとCodePipelineを作成し、
CodeBuildからDEV環境アカウントのCodeCommitリポジトリを参照させる設定を構築する。
↓の記事を参考にする予定。
第五回
1.5時間で以下を行った
Prd環境Infraパイプライン作成試行
下記記事を参考に一部変更して試行
ソースの受け渡しのためだけにS3バケットを使いたくないため、
Prd環境のCodeBuildプロジェクトをDev環境のCodeCommitをソースとするプロジェクトの作成を試行
また、CodeBuildが別アカウントのCodeCommitを見れるようにAssumeRoleの権限を付与
{
"name": "****-infra-prd",
"description": "cross account build project",
"source": {
"type": "CODECOMMIT",
"location": "https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/****infra",
"gitCloneDepth": 1,
"gitSubmodulesConfig": {
"fetchSubmodules": false
},
"buildspec": "",
"insecureSsl": false
},
"sourceVersion": "refs/heads/master",
"serviceRole": "arn:aws:iam::*****:role/******",
"artifacts": {
"type": "NO_ARTIFACTS"
},
"environment": {
"type": "LINUX_CONTAINER",
"image": "aws/codebuild/amazonlinux2-x86_64-standard:5.0",
"computeType": "BUILD_GENERAL1_SMALL",
"environmentVariables": [
{
"name": "ENVIRONMENT",
"value": "prd",
"type": "PLAINTEXT"
}
],
"privilegedMode": false,
"imagePullCredentialsType": "CODEBUILD"
}
}
aws codebuild create-project --cli-input-json file://prd-codebuild.json --profile {prd環境用profile}
リポジトリが存在するアカウントを指定できていないため(そもそもできるか要調査)
当然成功せず
リソース管理再構成案
以下の理由によりソースをGithubに移し、
パイプラインも含めてTerraformCloudで管理したほうがいいと考えた。
- CodeBuild、ロール、ポリシー、CodePipelineを手動で作成してしまっており、管理が煩雑
- Infra用のソースを含むリポジトリがDev環境のCodeCommitにある都合上、Infraのパイプラインがどうしても手動作成になる。
次回予定
ソースをすべてGithubに移し、Dev環境とPrd環境の各リソースをTerraformCloudで管理するように変更
第六回
2h近くで以下を実施
- ソースをすべてGithubに移動
- Dev環境とPrd環境のCodebuildプロジェクトおよびCodePipelineと、関連するIAMポリシー・ロールを削除
Githubの組織無料版の場合、ブランチ保護設定を付加することができないことが判明
次回予定
- TerraformCloud連携
- バックエンドパイプライン作成
第七回
1.5hで以下を実施
- Terraform Cloudプロジェクトおよびワークスペースの作成
- ワークスペースはPRDとDEVのinfra自動適用
- Terraform Cloud用のIAMユーザとアクセスキーを作成
- OIDCの使用も検討したが、学習コストと時間がかかるため断念
- 後々、下記を参考にしてOIDC使用する形に変更する手も検討中
- https://dev.classmethod.jp/articles/terraform-cloud-dynamic-provider-credentials/
作成したTerraform Cloud Workspace
Github上のinfraリポジトリと連携
PRD環境AWSアカウントに対してはmasterブランチ、
DEV環境AWSアカウントに対してはdevelopブランチに対して下記が実施される設定を行う
- PR作成時にplan
- merge時にapply
今回はDEV環境の設定のみ完了
次回予定
PRD環境workspaceの設定
バックエンドのパイプライン作成、DEV環境にお試しデプロイ
第八回
1.5hで以下を実施
- TerraformCloudのPRD環境の設定
- TerraformでバックエンドのCodeBuildプロジェクトを作成
CodeBuildプロジェクト作成時
AWSコンソール上でGithubとOAuthで接続し、
そのままTerraform上でGithubのソースを指定することができる。
次回予定
DEV環境バックエンドパイプラインの作成
バックエンドのお試しデプロイ
第九回
2.5hで以下を実施
バックエンドのリソース管理を変更
バックエンドに関する以下リソース群をすべてServerless Frameworkで管理する想定だった
- Lambda
- API Gateway
- Cognito
しかしバックエンドとして複数のLambdaを構築する構成は、Pythonやnode.jsのように簡単にはできず、ソース管理が煩雑になる。
よって単一のLambdaでバックエンドを構築する。
このためServerlessを使用する必要性が薄くなったと判断
リソース管理はすべてTerraformに寄せる。
バックエンドの構成
lambda_web
でactix_web
を使用し、単一のLambdaでバックエンドサーバとする
以下のサンプルを作成
[package]
name = "****"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "4.8.0"
lambda-web = { version = "0.2.1", features =["actix4"] }
lambda_runtime = "0.12.0"
tokio = "1.38.0"
use lambda_web::actix_web::{self, get, App, HttpServer, Responder};
use lambda_web::{is_running_on_lambda, run_actix_on_lambda, LambdaError};
#[get("/")]
async fn hello() -> impl Responder {
format!("Hello")
}
#[actix_web::main]
async fn main() -> Result<(), LambdaError> {
let factory = move || App::new().service(hello);
if is_running_on_lambda() {
// Run on AWS Lambda
run_actix_on_lambda(factory).await?;
} else {
// Local server
HttpServer::new(factory)
.bind("127.0.0.2:8080")?
.run()
.await?;
}
Ok(())
}
次回予定
Terraformで以下を作成および調整し、バックエンドのパイプラインを完成させる
- Lambda
- API Gateway
- CodeBuild
- CodePipeline
第十回
3h強で以下を実施
バックエンドパイプライン構築継続
先にソースなしのLambda作成を試みるも、
大前提としてそんなLambdaは作れない(それはそう)
resource "aws_iam_role" "backend_lambda_exec_role" {
name = "${var.project}-${var.environment}-lambda-exec-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_lambda_function" "lambda_backend" {
function_name = "lambda-${var.project}-${var.environment}-backend"
role = aws_iam_role.backend_lambda_exec_role.arn
handler = "bootstrap" // Rustの場合、ハンドラーは通常 "bootstrap" となります
runtime = "provided" // カスタムランタイムの場合、"provided" を指定します
environment {
}
}
先にcodebuildの設定を行い、アーティファクトをs3に配置する。
# -------------------
# codebuildアーティファクト配置先S3バケットを作成
# -------------------
resource "aws_s3_bucket" "s3_artifact_backend_bucket" {
bucket = "artifact-backend-bucket-${var.project}-${var.environment}"
}
# codebuildのポリシー
resource "aws_codebuild_project" "backend_codebuild_project" {
name = "${var.project}-${var.environment}-backend-project" // プロジェクトの名前
description = "${var.environment}-backend CodeBuild project" // プロジェクトの説明
build_timeout = "5" // ビルドがタイムアウトするまでの時間(分)
service_role = aws_iam_role.role_for_backend_codebuild.arn // プロジェクトが使用するIAMロールのARN
// ビルドのアーティファクト(出力)に関する設定
artifacts {
- type = "NO_ARTIFACTS" // アーティファクトを生成しない設定
+ type = "S3"
+ location = aws_s3_bucket.s3_artifact_backend_bucket.bucket
+ name = "backend_binary.zip"
+ packaging = "ZIP"
}
// ビルド環境に関する設定
environment {
compute_type = "BUILD_GENERAL1_SMALL"
- image = "aws/codebuild/standard:4.0" // 使用するDockerイメージ
+ image = "rust:latest" // RustのDockerイメージ
type = "LINUX_CONTAINER"
image_pull_credentials_type = "CODEBUILD"
privileged_mode = true
}
// ソースに関する設定
source {
type = "GITHUB" // ソースのタイプ
location = "https://github.com/******/*****.git" // ソースの場所(GitHubリポジトリのURL)
git_clone_depth = 1 // クローンするGitの深さ
}
source_version = var.branch // ビルド仕様ファイルのパス
+ logs_config {
+ cloudwatch_logs {
+ group_name = "****"
+ }
+ }
}
// CodeBuildプロジェクトが使用するIAMロールを作成するリソース
resource "aws_iam_role" "role_for_backend_codebuild" {
name = "role-for-${var.project}-${var.environment}-backend-codebuild" // IAMロールの名前
// IAMロールの信頼ポリシー
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "codebuild.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
+resource "aws_iam_role_policy" "backend_codebuild_policy" {
+ name = "${var.project}-${var.environment}-backend-codebuild-policy"
+ role = aws_iam_role.role_for_backend_codebuild.id
+
+ policy = <<EOF
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "logs:CreateLogGroup",
+ "logs:CreateLogStream",
+ "logs:PutLogEvents"
+ ],
+ "Resource": "arn:aws:logs:*:*:*"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "s3:PutObject",
+ "s3:GetObject",
+ "s3:ListBucket"
+ ],
+ "Resource": [
+ "${aws_s3_bucket.s3_artifact_backend_bucket.arn}",
+ "${aws_s3_bucket.s3_artifact_backend_bucket.arn}/*"
+ ]
+ }
+ ]
+}
+EOF
+}
ビルド時間に関する問題
ビルド成功時の所要時間が5分弱
短縮のため、compute_typeの変更及びキャッシュを検討
雑感
過去の記録から大体のベロシティが推測できそう (そもそも各タスクにストーリーポイント的な見積もりをしているわけではないが)
次回予定の欄はそれを参考に記述し、予実比較してみる
また、AWSサービスのポリシー・ロール回りの調整に大苦戦している傾向がある。
今回の構築を経て糧としたい。
次回予定
- codebuildのキャッシュの設定
- lambdaの作成
第十一回
ざっくり3hで以下を行った
codebuildのキャッシュ用S3バケットを作成
codebuildプロジェクトにキャッシュ用の設定を追加
+ // キャッシュに関する設定
+ cache {
+ type = "S3"
+ location = aws_s3_bucket.s3_cache_bucket.bucket
+ }
前回作成したアーティファクトをもとにlambdaを作成
以下の形で作成を試みるも失敗
resource "aws_iam_role" "backend_lambda_exec_role" {
name = "${var.project}-${var.environment}-lambda-exec-role"
s3_bucket = aws_s3_bucket.s3_artifact_bucket.bucket
s3_key = "backend_binary.zip"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_lambda_function" "lambda_backend" {
function_name = "lambda-${var.project}-${var.environment}-backend"
role = aws_iam_role.backend_lambda_exec_role.arn
handler = "bootstrap" // Rustの場合、ハンドラーは通常 "bootstrap" となります
runtime = "provided" // カスタムランタイムの場合、"provided" を指定します
}
ランタイムprovided
はもう新規で使えない。provided.al2023
を使えと言われる
ので変更を試みるも失敗
- runtime = "provided" // カスタムランタイムの場合、"provided" を指定します
+ runtime = "provided.al2023"
プロバイダが古かった
# ------------------------
# - Terraform configuratoions
# ------------------------
terraform {
required_version = ">1.0"
required_providers {
aws = {
source = "hashicorp/aws"
- version = "~>3.0"
+ version = "~>5.0"
}
}
}
init -upgaradeを実施し、.terraform.lock.hcl
を更新
terraform init -upgrade
Lambda作成成功
Lambda動作確認
Lambdaのコンソールでテストを実施してみる
INIT_REPORT Init Duration: 0.23 ms Phase: init Status: error Error Type: Runtime.InvalidEntrypoint
INIT_REPORT Init Duration: 9.04 ms Phase: invoke Status: error Error Type: Runtime.InvalidEntrypoint
START RequestId: dd427788-f018-435e-97a1-c9fb85107c1b Version: $LATEST
RequestId: dd427788-f018-435e-97a1-c9fb85107c1b Error: Couldn't find valid bootstrap(s): [/var/task/bootstrap /opt/bootstrap]
Runtime.InvalidEntrypoint
END RequestId: dd427788-f018-435e-97a1-c9fb85107c1b
REPORT RequestId: dd427788-f018-435e-97a1-c9fb85107c1b Duration: 10.22 ms Billed Duration: 11 ms Memory Size: 128 MB Max Memory Used: 2 MB
bootstrap置けと言われている。
アーティファクトが誤っている
lambda-webのリポジトリにサンプルのbuildspec.yml
があるので、それをもとに修正
version: 0.2
phases:
install:
runtime-versions:
rust: latest
build:
commands:
+ - rustc -V
- cargo build --release
+ - mv target/release/d-nexus-backend bootstrap
+ - strip --strip-all bootstrap
+ - size bootstrap
+ - ldd bootstrap
artifacts:
files:
- - target/release/*
+ - bootstrap
再ビルドし、動作確認
{
"version": "2.0",
"routeKey": "$default",
"rawPath": "/",
"rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value",
"cookies": ["cookie1", "cookie2"],
"headers": {
"header1": "value1",
"header2": "value1,value2"
},
"queryStringParameters": {
"parameter1": "value1,value2",
"parameter2": "value"
},
"requestContext": {
"accountId": "123456789012",
"apiId": "<urlid>",
"authentication": null,
"authorizer": {
"iam": {
"accessKey": "AKIA...",
"accountId": "111122223333",
"callerId": "AIDA...",
"cognitoIdentity": null,
"principalOrgId": null,
"userArn": "arn:aws:iam::111122223333:user/example-user",
"userId": "AIDA..."
}
},
"domainName": "<url-id>.lambda-url.us-west-2.on.aws",
"domainPrefix": "<url-id>",
"http": {
"method": "POST",
"path": "/",
"protocol": "HTTP/1.1",
"sourceIp": "123.123.123.123",
"userAgent": "agent"
}
},
"body": "{\"query\":\"{ hello }\"}",
"pathParameters": null,
"isBase64Encoded": false,
"stageVariables": null
}
動作確認成功
{
"body": "eyJkYXRhIjp7ImhlbGxvIjoiSGVsbG8sIHdvcmxkISJ9fQ==",
"cookies": [],
"headers": {
"content-type": "application/json"
},
"isBase64Encoded": true,
"statusCode": 200
}
居残り
その後、以下を行った
- ビルドマシンをdockerイメージからcodebuildで用意されているものに変更
- buildspec.ymlのinsatllフェーズでrustをインストールするようにする
- installしたrust自体をキャッシュするようにする
第十二回
おおよそ1.5時間と筆者の居残りで以下を行った。
パイプライン構築(バックエンド)
CodePipelineによる自動デプロイの構築を試行したが、失敗
最終的にはバックエンドのbuildspec.ymlを下記のように変更、
都度、Codebuildを実行することで対応することとした
version: 0.2
env:
variables:
DEPLOY_TARGET: "backend"
phases:
install:
commands:
- if [ -f "$HOME/.cargo/env" ]; then
echo load-env;
. $HOME/.cargo/env;
echo rustup-update;
rustup update;
else
echo rustup-install;
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y;
echo load-env;
. $HOME/.cargo/env;
echo install-cargo-cache;
cargo install cargo-cache;
fi
build:
commands:
- rustc -V
- cargo build --release
- mv target/release/d-nexus-backend bootstrap
- strip --strip-all bootstrap
- size bootstrap
- ldd bootstrap
- zip bootstrap.zip bootstrap
post_build:
commands:
- aws lambda update-function-code --function-name $DEPLOY_TARGET --zip-file fileb://bootstrap.zip
artifacts:
files:
- bootstrap
cache:
paths:
- $HOME/.cargo/env
- $HOME/.cargo/bin/**/*
- $HOME/.cargo/registry
- $HOME/.cargo/git
- target/release/deps
理由としてそもそも基本的に作業自体はペアプロするタイミングでしか行わないため、
工数をかけてまで自動デプロイを構築する旨みが薄いと判断。
第十三回
1.5hで以下を実施
API GatewayおよびCognito関連の構成を検討
Cognitoによるサインアップおよびログイン機能の実装方針を検討した。
下記のうち1が不可能、3のカスタマイズ性の低さから、2の方針に決定。
- API GatewayとCognitoを直接統合し、サインアップ・ログインAPIを提供
- API GatewayとCognitoの間にLambdaを挟み、サインアップ・ログインAPIを提供
- Cognito Hosted UIを使用
また、直近で以下を順に構築する方針にする。
Ⅰ. Cognitoユーザプールを作成
Ⅱ. API Gatewayを作成
Ⅲ. API GatewayとバックエンドのLambdaの統合と作成
Ⅳ. Cognito関連のAPI用のLambdaを別途作成
resource "aws_cognito_user_pool" "user_pool" {
name = "${var.project}-${var.environment}-pool"
}
resource "aws_cognito_user_pool_client" "user_pool_client" {
name = "${var.project}-${var.environment}-client"
user_pool_id = aws_cognito_user_pool.user_pool.id
generate_secret = true
}
resource "aws_api_gateway_rest_api" "rest_api" {
name = "${var.project}-${var.environment}-api"
description = "${var.project}-${var.environment} API Gateway"
}
resource "aws_api_gateway_method" "backend_method" {
rest_api_id = aws_api_gateway_rest_api.rest_api.id
resource_id = aws_api_gateway_rest_api.rest_api.root_resource_id
http_method = "POST"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "backend_integration" {
rest_api_id = aws_api_gateway_rest_api.rest_api.id
resource_id = aws_api_gateway_rest_api.rest_api.root_resource_id
http_method = aws_api_gateway_method.backend_method.http_method
type = "HTTP"
integration_http_method = "ANY"
uri = aws_lambda_function.lambda_backend.invoke_arn
}
resource "aws_api_gateway_deployment" "rest_api_deployment" {
depends_on = [aws_api_gateway_integration.backend_integration]
rest_api_id = aws_api_gateway_rest_api.rest_api.id
stage_name = var.environment
}
resource "aws_lambda_permission" "apigw_lambda" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.lambda_backend.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_api_gateway_rest_api.rest_api.execution_arn}/*/*"
}
Ⅲ以降を次回に構築
第十四回
以下を実施
- lambda_webクレートが使いづらかったためコンテナ化し、web-adapterを使用
- CICDを変更
- API Gateway再作成