AWS EC2とAPI gatewayによるAPIサーバをterraformで実装する
はじめに
私の所属している研究室の業務として、機械学習モデルを用いたAPIを作成して外部に公開しなければ行けないタスクが舞い降ってきました。自分の技術スタックとして、インターンシップ先でAWSのEC2の実験環境を整えるために、terraformを使って立ち上げていたことくらいで、API Gatewayを用いてAPIを立てたことがなかったので、いい機会と思い挑戦しました。
ただ、この記事はやってみたの記事なので、あくまで参考程度に見てください。(実験のために素人が作っているので、特にセキュリティ周りはガバガバだと思います。)
使用技術
初期段階
初期段階では、後々研究室でサービスを運用するとなった場合に備えて、スケーラブルなものにしたかったため、ECS+Fargate or ECS+EC2用いて作ることにしていました。しかし、以下のことが原因で諦めました。
- ECS+Fargateは小規模で運用する分には割高
- ECS+EC2 作っている間に、実装するべきことや考えなければいけないことが多く、素人には太刀打ちできなかった。
- スケーラブルは今回のケースにとってはオーバースペックすぎる
- 初めてにしてはハードルが高すぎる
最終段階
そこで、以下の技術を使うことにより少しタスクが減り、1~2日程度で作成することができました。
-
AWS
- API Gateway
- Lambda
- VPC
- EC2
-
APIサーバ
- Python
- FastAPI
- Docker
-
HCL ツール
- terraform
構成
AWS 構成
構成はこちらの記事を参考にさせていただきました。🙏 そのまま使わせていただきます。
流れとしては、API gateway を介してVPC 内のlambdaにリクエストを送り、そこからEC2のAPIを叩くという構成です。
API gatewayをproxyのように使うので、セキュアなAPIを構築しようとしました。
ただ、参考にした記事や他の記事ではAPIをコンソールを用いて構築していたので、自分はterraformで構築することにしました。
EC2内部の構成
EC2内は以下のとおりです。後々、機械学習モデルや、特殊なNLPモジュールを使う予定だったので、EC2インスタンスでそのまま動かすとConflictが起きそうだったのと、ローカルで動かして確認したかったので、Docker Containerを立ち上げて運用することにしました。
ワークスペース構成
❯ tree .
.
├── README.md
├── api
│ ├── docker
│ │ ├── Dockerfile
│ │ ├── push_ecr.sh
│ │ └── requirements.txt
│ ├── docker-compose.yml
│ ├── src
│ │ └── main.py
│ └── test
│ └── api-test.py
└── terraform
├── README.md
├── ami-list.txt
├── api-gateway.tf
├── ec2
│ └── initialize.sh
├── ec2.tf
├── keys
│ ├── example
│ └── example.pub
├── lambda
│ ├── app
│ │ └── lambda.py
│ ├── build_layer.sh
│ ├── lib
│ │ └── python
│ └── requirements.txt
├── lambda.tf
├── layer.zip
├── main.tf
├── output.tf
├── output.txt
├── terraform.tfstate
├── terraform.tfstate.backup
├── terraform.tfvars
├── terraform.tfvars.default
├── variable.tf
└── vpc.tf
APIコンテナの作成
Fast APIを用いたPython API
まずはFastAPIのかんたんなAPIから。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Dialog(BaseModel):
message: str
@app.post("/dialog")
def dialog(dialog: Dialog):
return {"responce": f"Hello! You said {dialog.message}"}
Dockerfile
Dockerfileも例のごとく作ります.
大事な点として、Docker run
したときに8080portを開放するようにしています。
FROM ubuntu:20.04
# aptのサーバを日本にする
RUN sed -i 's@archive.ubuntu.com@ftp.jaist.ac.jp/pub/Linux@g' /etc/apt/sources.list
# 必要そうなものをinstall
RUN apt-get update && apt-get install -y \
software-properties-common && \
rm -rf /var/lib/apt/lists/*
RUN add-apt-repository ppa:apt-fast/stable
RUN apt-get update \
&& apt install -y apt-fast \
&& apt-fast clean && rm -rf /var/lib/apt/lists/*
RUN apt-fast update \
&& apt-fast install -y --no-install-recommends \
wget \
vim \
build-essential \
libreadline-dev \
libncursesw5-dev \
libssl-dev \
libsqlite3-dev \
libgdbm-dev \
libbz2-dev \
liblzma-dev \
zlib1g-dev \
uuid-dev \
libffi-dev \
libdb-dev \
build-essential \
libssl-dev \
libffi-dev \
python3-dev \
python3-pip
RUN apt-fast autoremove -y
COPY docker/requirements.txt .
RUN pip install -r requirements.txt
# copy src
COPY src root/src
COPY test root/test
EXPOSE 8080
ENTRYPOINT uvicorn root.src.main:app --reload --host "0.0.0.0" --port "8080"
Docker compose
これをdocker compose を作成します
version: '3'
services:
chat-server:
image: chat-server-image
platform: linux/amd64
build:
context: .
dockerfile: docker/Dockerfile
container_name: example
restart: always
ports:
- 8080:8080
tty: true
テスト実行
以下のコマンドでdocker imageをビルド&コンテナ化します。
docker compose build
docker compose up
local 環境ではlocalhost:8080
がendpointなので、APIを叩いて確認します。
私のようにtest/api-test.py
にpytestのコードを書いておくと後々便利です。
ECRにpush
EC2にimageを持ってくるためにECRにimageをpushしておきます。
IMAGE_NAME=example
ECR_IMAGE_NAME=<ECR リポジトリURL>/$IMAGE_NAME
aws ecr get-login-password --region ap-northeast-1 | \
docker login \
--username AWS \
--password-stdin \
<account id>.dkr.ecr.<region>.amazonaws.com
docker tag "${IMAGE_NAME}":latest "${ECR_IMAGE_NAME}":latest
docker push "${ECR_IMAGE_NAME}":latest
#docker image rm "{$ECR_IMAGE_NAME}":latest
これで準備OKです。
EC2の立ち上げ
AWSのためのterraform 準備
veriable.tf
などにaccess_key, secret_key, regionなどを定義しておいて、以下のスクリプトでawsを使うことを宣言します。
AWSのaccess/secret keyをPushしてしまうと、めちゃくちゃ危ないので、terraform.tfvarsなど、pushされないファイルに書いて運用しています。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.1.0"
}
}
}
locals {
app_name = "chat-server"
}
provider "aws" {
region = var.region
access_key = var.access_key
secret_key = var.secret_key
default_tags {
tags = {
application = local.app_name
}
}
}
VPC
まずはVPCから作成していきましょう
ここは自分ではなく、他の記事のほうが詳しく書いてくれていると思います。
# ====================
# VPC
# ====================
resource "aws_vpc" "chat-vpc" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true # DNS解決を有効化
enable_dns_hostnames = true # DNSホスト名を有効化
tags = {
Name = "chat-vpc"
}
}
# ====================
# Subnet
# ====================
resource "aws_subnet" "chat-subnet" {
cidr_block = "10.0.1.0/24"
availability_zone = "ap-northeast-1a"
vpc_id = aws_vpc.chat-vpc.id
# trueにするとインスタンスにパブリックIPアドレスを自動的に割り当ててくれる
map_public_ip_on_launch = true
tags = {
Name = "chat-subnet"
}
}
# ====================
# Internet Gateway
# ====================
resource "aws_internet_gateway" "chat-ig" {
vpc_id = aws_vpc.chat-vpc.id
tags = {
Name = "chat-ig"
}
}
# ====================
# Route Table
# ====================
resource "aws_route_table" "chat-rt" {
vpc_id = aws_vpc.chat-vpc.id
tags = {
Name = "chat-rt"
}
}
resource "aws_route" "chat-route" {
gateway_id = aws_internet_gateway.chat-ig.id
route_table_id = aws_route_table.chat-rt.id
destination_cidr_block = "0.0.0.0/0"
}
resource "aws_route_table_association" "chat-rt-ass" {
subnet_id = aws_subnet.chat-subnet.id
route_table_id = aws_route_table.chat-rt.id
}
また、セキュリティグループも記述します。
# ====================
# Security Group
# ====================
resource "aws_security_group" "chat-sg" {
vpc_id = aws_vpc.chat-vpc.id
name = "chat-sg"
tags = {
Name = "chat-sg"
}
}
# インバウンドルール(ssh接続用)
resource "aws_security_group_rule" "in_ssh" {
security_group_id = aws_security_group.chat-sg.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 22
to_port = 22
protocol = "tcp"
}
# インバウンドルール(pingコマンド用)
resource "aws_security_group_rule" "in_icmp" {
security_group_id = aws_security_group.chat-sg.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = -1
to_port = -1
protocol = "icmp"
}
# インバウンドルール HTTP
resource "aws_security_group_rule" "in_http" {
security_group_id = aws_security_group.chat-sg.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
to_port = 80
protocol = "tcp"
}
# インバウンドルール HTTPS(必要ないが)
resource "aws_security_group_rule" "in_https" {
security_group_id = aws_security_group.chat-sg.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
to_port = 443
protocol = "tcp"
}
# インバウンドルール HTTPS(必要ないが)
resource "aws_security_group_rule" "in_app" {
security_group_id = aws_security_group.chat-sg.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 8080
to_port = 8080
protocol = "tcp"
}
# アウトバウンドルール(全開放)
resource "aws_security_group_rule" "out_all" {
security_group_id = aws_security_group.chat-sg.id
type = "egress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 0
to_port = 0
protocol = "-1"
}
最後に、ECRを使えるようにするために、以下を記述します
####
# ECRを使えるようにするため
#####
resource "aws_vpc_endpoint" "ecr-dkr" {
vpc_id = aws_vpc.chat-vpc.id
service_name = "com.amazonaws.ap-northeast-1.ecr.dkr"
vpc_endpoint_type = "Interface"
subnet_ids = [aws_subnet.chat-subnet.id]
security_group_ids = [aws_security_group.chat-sg.id]
private_dns_enabled = true
tags = {
Environment = "ecr-dkr"
}
}
resource "aws_vpc_endpoint" "ecr-api" {
vpc_id = aws_vpc.chat-vpc.id
service_name = "com.amazonaws.ap-northeast-1.ecr.api"
vpc_endpoint_type = "Interface"
subnet_ids = [aws_subnet.chat-subnet.id]
security_group_ids = [aws_security_group.chat-sg.id]
private_dns_enabled = true
tags = {
Environment = "ecr-api"
}
}
secret keyの作成
まずEC2へアクセスする用のaccess keyを作成します。本当はterraform のaws_key_pair
などで、applyするたびに作成するのが一般的なのですが、今回は簡易的に自分で作る方法を取りました。
ssh-keygen -t ed25519
そのSSH鍵で入れるようにします。
# ====================
# Key Pair
# ====================
resource "aws_key_pair" "chat-server" {
key_name = "chat-server-key"
public_key = file("./keys/example.pub")
}
EC2立ち上げ
# ====================
# AMI
# ====================
# 最新版のAmazonLinux2 GPU typeのAMI情報
data "aws_ami" "ami-info" {
most_recent = true
owners = ["amazon"]
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
filter {
name = "name"
values = ["amzn2-ami-hvm-*"] #"Deep Learning AMI GPU PyTorch*"
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "block-device-mapping.volume-type"
values = ["gp2"] # gp2
}
filter {
name = "state"
values = ["available"]
}
}
# ====================
# EC2 Instance
# ====================
resource "aws_instance" "chat-server" {
ami = data.aws_ami.ami-info.image_id
vpc_security_group_ids = [aws_security_group.chat-sg.id]
subnet_id = aws_subnet.chat-subnet.id
key_name = aws_key_pair.chat-server.id
instance_type = "t2.large"
user_data = templatefile(
"${path.module}/ec2/initialize.sh",
{
IMAGE_URL = var.image_url
}
)
iam_instance_profile = "instance_role"
tags = {
Name = "chat-server"
}
}
# ====================
# Elastic IP
# ====================
resource "aws_eip" "chat-eip" {
instance = aws_instance.chat-server.id
vpc = true
}
Elastic IPを指定することで、global IP addressを作成しています。これでできたIPアドレスに、先程作ったガキを使ってssh 接続します。
また、以下のところで、EC2Instanceを初期化するスクリプトを指定しています。
# ====================
# EC2 Instance
# ====================
resource "aws_instance" "chat-server" {
ami = data.aws_ami.ami-info.image_id
vpc_security_group_ids = [aws_security_group.chat-sg.id]
subnet_id = aws_subnet.chat-subnet.id
key_name = aws_key_pair.chat-server.id
instance_type = "t2.large"
user_data = templatefile(
"${path.module}/ec2/initialize.sh", ### ここ!!
{
IMAGE_URL = var.image_url
}
)
・・・
}
これは、ec2/initialize.sh
に最初に実行してほしい内容をshellscriptで書いておくと、自動で実行してくれるようになります。
私の場合は、このように書きました。
#!/bin/sh
# S3FS
yum -y update
amazon-linux-extras install -y epel
yum -y install s3fs-fuse
# S3のマウントポイントを作成
mkdir /mnt/s3fs
echo "<backet name> /mnt/s3fs fuse.s3fs _netdev,allow_other,iam_role=auto,umask=022 0 0" | sudo tee -a /etc/fstab
mount -a
df -h
# docker install
sudo yum install -y docker
sudo systemctl start docker
sudo usermod -a -G docker ec2-user
sudo systemctl enable docker
# imageのpull
aws ecr get-login-password --region ap-northeast-1 | sudo docker login --username AWS --password-stdin <accountID>.dkr.ecr.<region>.amazonaws.com
sudo docker pull ${IMAGE_URL}
# run
sudo docker run --rm -p 8080:8080 -d ${IMAGE_URL}
EC2にassume policyを追加
まだこれでは、EC2からECRにアクセスできません。なぜなら、アクセス件を持ってないからです。個人ユーザのaccess keyとsecret keyでaws configure
を使ってEC2内でloginするのもいいですが、AWSぽくありません。
そこで、assume policyを付与します。
# #####################
# # IAM role
# #####################
resource "aws_iam_instance_profile" "instance_role" {
name = "instance_role"
role = aws_iam_role.instance_role.name
}
resource "aws_iam_role" "instance_role" {
name = "instance_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
# s3とECRのroleを追加
resource "aws_iam_role_policy" "instance_role_policy" {
name = "instance_role_policy"
role = aws_iam_role.instance_role.id
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ecr:*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ecr-public:*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::saya-chat-models"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObjectVersion",
"s3:DeleteObject",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::saya-chat-models/*"
]
}
]
}
EOF
}
これで、立ち上げることができました。
global IP addressがわかっていて、セキュリティグループで8080を開けているので、直接叩くことができます。
直接叩いて、返答が問題なければ成功しています。
Lambda の作成
ここまでで、EC2を使ってAPIサーバを立ち上げることに成功しました。
ここからはlambdaを介してAPIを公開します。
アーキテクチャの図でいうと、以下の赤い部分になります。
lambda layerの作成
lambdaのデフォルトから、追加してモジュールを使いたい場合(例えば、ライブラリやその他aptで入れたいものなど)、Lambda Layerを使うことで解決できます。
Lambda Layerとは、追加のコードまたはデータを含むことができる .zip ファイルアーカイブです。レイヤーには、ライブラリ、カスタムランタイム、データ、または設定ファイルを含めることができます。レイヤーを使用して、デプロイパッケージのサイズを減らし、コードの共有と責任の分離を促進することで、ビジネスロジックの記述をより迅速に繰り返すことができます。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-layers.html
なので、コードを作っていきましょう。
以下のようなディレクトリ構造を取ります。
lambda
├── app
│ └── lambda.py
├── build_layer.sh
└── requirements.txt
app/lambda.py
の中身は以下の通りです。
import os
import requests
import json
def get_responce(statusCode: int, body: str):
if not isinstance(body, str):
raise RuntimeError("body is not string")
response = {
"isBase64Encoded": True,
"statusCode": statusCode,
"headers": { "Access-Control-Allow-Origin": "*" },
"body": body
}
return response
def handler(event, context):
response = {}
endpoint = os.environ["URL"]
port = os.environ["PORT"]
path = os.environ["PATH"]
request_url = f"http://{endpoint}:{port}/{path}"
body = json.loads(event["body"])
if body is None or "data" in body:
response = get_responce(400,"body don't have data")
data = body["data"]
payload = body
print(f"data : {data}")
try:
ecs_res = requests.post(request_url, data=json.dumps(payload), timeout=(60.0,60.0))
except ecs_res.exceptions.RequestException as e:
response = get_responce(400, f"ECS error {e}")
print("failed")
except Exception as e:
response = get_responce(500, f"lambda error {e}")
print("failed in lambda")
else:
response = get_responce(200, ecs_res.text)
print("succeeded!")
finally:
return response
以下のコードを使ってlayerを作成します。
#!/usr/bin/env bash
if [ -d lib/ ]; then
rm -rf lib/
fi
echo "bundle pypi packages"
pip install -r requirements.txt -t lib/python
find lib -type f | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm
ここまでくれば、生成されたlayerをzip化して、プロジェクトルートにおいておけばOKです!
terraform コード
ここまでできたら
terraform のコードは以下の通りです。
resource "aws_iam_role" "iam_for_lambda" {
name = "iam_for_lambda"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
locals {
function_name = "my_lambda_function"
}
data "archive_file" "function_source" {
type = "zip"
source_dir = "lambda/app"
output_path = "lambda/archive/my_lambda_function.zip"
}
data "archive_file" "layer_source" {
type = "zip"
source_dir = "lambda/lib"
output_path = "lambda/archive/my_lambda_layer.zip"
}
resource "aws_lambda_layer_version" "lambda_layer" {
layer_name = "lambda_layer"
filename = data.archive_file.layer_source.output_path
source_code_hash = data.archive_file.layer_source.output_base64sha256
}
resource "aws_lambda_function" "function" {
function_name = local.function_name
handler = "lambda.handler"
role = aws_iam_role.lambda_role.arn
runtime = "python3.9"
layers = [aws_lambda_layer_version.lambda_layer.arn]
kms_key_arn = aws_kms_key.lambda_key.arn
timeout = 60
filename = data.archive_file.function_source.output_path
source_code_hash = data.archive_file.function_source.output_base64sha256
environment {
variables = {
URL = aws_eip.chat-eip.public_ip,
PORT = "8080",
PATH = "dialog",
}
}
depends_on = [aws_iam_role_policy_attachment.lambda_policy, aws_cloudwatch_log_group.lambda_log_group]
}
resource "aws_kms_key" "lambda_key" {
description = "My Lambda Function Customer Master Key"
enable_key_rotation = true
deletion_window_in_days = 7
}
resource "aws_kms_alias" "lambda_key_alias" {
name = "alias/my-lambda-key"
target_key_id = aws_kms_key.lambda_key.id
}
######################
# lambda のためのassume role
#######################
data "aws_iam_policy_document" "assume_role" {
statement {
actions = ["sts:AssumeRole"]
effect = "Allow"
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
}
}
data "aws_iam_policy" "lambda_basic_execution" {
arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
data "aws_iam_policy_document" "lambda_policy" {
source_json = data.aws_iam_policy.lambda_basic_execution.policy
statement {
effect = "Allow"
actions = [
"kms:Decrypt"
]
resources = ["*"]
}
}
resource "aws_iam_policy" "lambda_policy" {
name = "MyLambdaPolicy"
policy = data.aws_iam_policy_document.lambda_policy.json
}
resource "aws_iam_role_policy_attachment" "lambda_policy" {
role = aws_iam_role.lambda_role.name
policy_arn = aws_iam_policy.lambda_policy.arn
}
resource "aws_iam_role" "lambda_role" {
name = "MyLambdaRole"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}
###########################
# cloud watch role
###########################
resource "aws_cloudwatch_log_group" "lambda_log_group" {
name = "/aws/lambda/${local.function_name}"
}
###############
# API Gateway からアクセス許可
###############
resource "aws_lambda_permission" "apigw" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.function.function_name
principal = "apigateway.amazonaws.com"
# The /*/* portion grants access from any method on any resource
# within the API Gateway "REST API".
source_arn = "${aws_api_gateway_rest_api.chat-server-api.execution_arn}/*/*/*"
}
立ち上げられたら、AWSコンソールからlambdaの画面に行って直接叩いてみて、デバッグしてみましょう!
API Gatewayの作成
API Gatewayは以下の通りです!
#####################
# API define
####################
resource "aws_api_gateway_rest_api" "chat-server-api" {
name = "ChatServerAPI"
}
resource "aws_api_gateway_rest_api_policy" "chat-server-api-policy" {
rest_api_id = aws_api_gateway_rest_api.chat-server-api.id
policy = data.aws_iam_policy_document.api-gateway-policy.json
}
data "aws_iam_policy_document" "api-gateway-policy" {
statement {
effect = "Allow"
principals {
type = "*"
identifiers = ["*"]
}
actions = ["execute-api:Invoke"]
resources = [
"${aws_api_gateway_rest_api.chat-server-api.execution_arn}/*/POST/dialog"
]
}
}
#################
# stage and deployment
#################
resource "aws_api_gateway_deployment" "chat-server-deployment" {
depends_on = [
aws_api_gateway_rest_api.chat-server-api,
aws_api_gateway_integration.dialog
]
rest_api_id = aws_api_gateway_rest_api.chat-server-api.id
stage_name = "dev"
triggers = {
redeployment = filebase64("${path.module}/api-gateway.tf")
}
lifecycle {
create_before_destroy = true
}
}
###########################################################
# Path : /dialog
# Method: POST
###########################################################
resource "aws_api_gateway_resource" "dialog" {
path_part = "dialog"
parent_id = aws_api_gateway_rest_api.chat-server-api.root_resource_id
rest_api_id = aws_api_gateway_rest_api.chat-server-api.id
}
resource "aws_api_gateway_method" "dialog" {
rest_api_id = aws_api_gateway_rest_api.chat-server-api.id
resource_id = aws_api_gateway_resource.dialog.id
http_method = "POST"
authorization = "NONE"
api_key_required = false
}
resource "aws_api_gateway_method_response" "dialog" {
rest_api_id = aws_api_gateway_rest_api.chat-server-api.id
resource_id = aws_api_gateway_resource.dialog.id
http_method = aws_api_gateway_method.dialog.http_method
status_code = "200"
response_models = {
"application/json" = "Empty"
}
depends_on = [aws_api_gateway_method.dialog]
}
resource "aws_api_gateway_integration" "dialog" {
rest_api_id = aws_api_gateway_rest_api.chat-server-api.id
resource_id = aws_api_gateway_resource.dialog.id
http_method = aws_api_gateway_method.dialog.http_method
content_handling = "CONVERT_TO_TEXT"
integration_http_method = "POST"
type = "AWS_PROXY"
uri = aws_lambda_function.function.invoke_arn
}
ここまでくればterraform apply
で立ち上げて、実行できるはずです!
まとめ
最後の方は力尽きて解説が疎かになってしまいましたが、今回terraformを使ってAPI構築を行い、デプロイしてみました。
policyとか、必要な情報が欠落していると思うので、適当に埋めて使ってみてください!
今後はCI/CDを使って、適切にデプロイできるようにしてみたいです。
Discussion