Pengantar
Dalam artikel ini, saya akan memperkenalkan kode untuk mendeploy AWS Lambda menggunakan AWS CLI. Kode yang kita perkenalkan akan memungkinkan Anda untuk mencapai hal-hal berikut:
- Membangun Lambda menggunakan gambar Docker
- Integrasi dengan Amazon API Gateway
- Menetapkan Provisioned Concurrency pada Lambda
- Memperbarui Lambda secara berkelanjutan
Struktur Direktori
Kita akan menulis kode sesuai dengan struktur direktori berikut.
├── Dockerfile
├── Makefile
├── deploy
│ ├── config
│ │ ├── policy.json
│ │ └── role.json
│ ├── push-ecr.sh
│ ├── provision-api-gateway.sh
│ ├── provision-ecr.sh
│ ├── provision-lambda.sh
│ └── update-lambda.sh
└── src/ # source code
Menetapkan Variabel Lingkungan
Atur variabel lingkungan berikut.
AWS_ACCOUNT_ID
AWS_REGION
IMAGE_NAME
LAMBDA_ALIAS
PROVISIONED_CONCURRENCY
# AWS account ID
$ export AWS_ACCOUNT_ID=123456789123
# AWS region
$ export AWS_REGION=ap-northeast-1
# ECR image and lambda name
$ export IMAGE_NAME=my-program
# Lambda alias
$ export LAMBDA_ALIAS=prod
# Number of Lambda Provisioned Concurrency
$ export PROVISIONED_CONCURRENCY=1
Kode Terkait ECR
Buat sebuah skrip shell deploy/provision-ecr.sh
untuk membuat sebuah repository ECR.
#!/bin/sh
# Create ECR repository
aws ecr create-repository --repository-name ${IMAGE_NAME} --region ${AWS_REGION}
Kemudian, buat skrip shell deploy/push-ecr.sh
untuk menjalankan hal-hal berikut:
- Masuk ke ECR
- Membangun gambar Docker dari
Dockerfile
- Mendorong gambar Docker yang telah dibangun ke ECR.
#!/bin/bash
# ECR repository URI
ECR_URI=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$IMAGE_NAME:latest
# ECR login
aws ecr get-login-password | docker login --username AWS --password-stdin https://$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com
# Build docker image
docker build -t $ECR_URI .
# Push docker image to ECR
docker push $ECR_URI
Kode Terkait Lambda
Buat file JSON untuk IAM Role dan Policy untuk memberikan izin kepada Lambda.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Kemudian, buat skrip shell provision-lambda.sh
untuk menjalankan hal-hal berikut:
- Membuat IAM Policy untuk Lambda dari
deploy/config/policy.json
- Membuat IAM Role untuk Lambda dari
deploy/config/role.json
- Melampirkan Policy ke Role
- Membuat Lambda (menggunakan gambar dari ECR sebagai sumber)
- Membuat versi Lambda dan alias (untuk digunakan dengan Provisioned Concurrency)
- Menetapkan Provisioned Concurrency pada Lambda.
#!/bin/bash
# Create IAM policy for lambda
aws iam create-policy --policy-name AWSLambdaBasicExecutionRole-${IMAGE_NAME} --policy-document file://deploy/config/policy.json
# Create IAM role for lambda
aws iam create-role --role-name ${IMAGE_NAME}-lambda-role --assume-role-policy-document file://deploy/config/role.json
# Sleep for waiting provision of policy and role creation
sleep 10
# Attach policy to role
aws iam attach-role-policy \
--role-name ${IMAGE_NAME}-lambda-role \
--policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/AWSLambdaBasicExecutionRole-${IMAGE_NAME}
# Sleep for waiting attachment
sleep 10
# Create lambda
aws lambda create-function \
--function-name ${IMAGE_NAME} \
--package-type Image \
--code ImageUri=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_NAME}:latest \
--timeout 600 \
--memory-size 10240 \
--ephemeral-storage Size=2048 \
--role arn:aws:iam::${AWS_ACCOUNT_ID}:role/${IMAGE_NAME}-lambda-role
# Wait for Lambda function to be created
while true; do
LAMBDA_STATUS=$(aws lambda get-function --function-name ${IMAGE_NAME} --query "Configuration.State" --output text)
if [[ ${LAMBDA_STATUS} == "Active" ]]; then
break
elif [[ ${LAMBDA_STATUS} == "Failed" ]]; then
echo "Lambda creation failed" >&2
exit 1
else
echo "Waiting for Lambda function to be created..."
sleep 10
fi
done
echo "Lambda function created."
# Create lambda version and alias
LAMBDA_VERSION=$(aws lambda publish-version --function-name ${IMAGE_NAME} --region ${AWS_REGION} --query 'Version' --output text)
aws lambda create-alias \
--function-name ${IMAGE_NAME} \
--name ${LAMBDA_ALIAS} \
--function-version ${LAMBDA_VERSION} \
--region ${AWS_REGION}
# Add provisioned concurrency to lambda
aws lambda put-provisioned-concurrency-config \
--function-name ${IMAGE_NAME} \
--qualifier ${LAMBDA_ALIAS} \
--provisioned-concurrent-executions "$PROVISIONED_CONCURRENCY" \
--region ${AWS_REGION}
# Wait for provisioned concurrency to be configured
while true; do
CONCURRENCY_STATUS=$(aws lambda get-provisioned-concurrency-config \
--function-name ${IMAGE_NAME} \
--qualifier ${LAMBDA_ALIAS} \
--query "Status" --output text)
if [[ ${CONCURRENCY_STATUS} == "READY" ]]; then
break
elif [[ ${CONCURRENCY_STATUS} == "FAILED" ]]; then
echo "Provisioned concurrency addition failed" >&2
exit 1
else
echo "Waiting for provisioned concurrency to be configured..."
sleep 10
fi
done
echo "Provisioned concurrency added to the Lambda function."
Buat skrip shell update-lambda.sh
untuk terus memperbarui Lambda. Hal-hal berikut akan dijalankan dalam update-lambda.sh
:
- Memperbarui Lambda dari gambar ECR yang ditentukan
- Memperbarui alias Lambda (memperbarui alias juga memperbarui Provisioned Concurrency)
# !/bin/bash
# Update lambda
aws lambda update-function-code --function-name ${IMAGE_NAME} --image ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_NAME}:latest
while true; do
LAST_UPDATE_STATUS=$(aws lambda get-function --function-name ${IMAGE_NAME} --region ${AWS_REGION} --query 'Configuration.LastUpdateStatus' --output text)
if [ ${LAST_UPDATE_STATUS} != "InProgress" ]; then
break
fi
echo "Waiting for Lambda function update to complete..."
sleep 10
done
NEW_LAMBDA_VERSION=$(aws lambda publish-version --function-name $IMAGE_NAME --region $AWS_REGION --query 'Version' --output text)
# Update lambda alias
aws lambda update-alias \
--function-name $IMAGE_NAME \
--name $LAMBDA_ALIAS \
--function-version $NEW_LAMBDA_VERSION \
--region $AWS_REGION
# Wait for provisioned concurrency to be configured
while true; do
CONCURRENCY_STATUS=$(aws lambda get-provisioned-concurrency-config \
--function-name ${IMAGE_NAME} \
--qualifier ${LAMBDA_ALIAS} \
--query "Status" --output text)
if [[ ${CONCURRENCY_STATUS} == "READY" ]]; then
break
elif [[ ${CONCURRENCY_STATUS} == "FAILED" ]]; then
echo "Provisioned concurrency addition failed" >&2
exit 1
else
echo "Waiting for provisioned concurrency to be configured..."
sleep 10
fi
done
echo "Provisioned concurrency added to the Lambda function."
Kode Terkait API Gateway
Buat skrip shell provision-api-gateway.sh
untuk menyiapkan API Gateway. provision-api-gateway.sh
akan menjalankan hal-hal berikut:
- Membuat REST API
- Membuat metode POST
- Mengintegrasikan dengan Lambda
- Menetapkan izin untuk Lambda
- Mendeploy API Gateway
#!/bin/bash
LAMBDA_FUNCTION_ARN=arn:aws:lambda:${AWS_REGION}:${AWS_ACCOUNT_ID}:function:${IMAGE_NAME}
# Create REST API
REST_API=$(aws apigateway create-rest-api --name $IMAGE_NAME)
REST_API_ID=$(echo $REST_API | python -c "import sys, json; print(json.load(sys.stdin)['id'])")
# Get root resource ID
RESOURCE=$(aws apigateway get-resources --rest-api-id $REST_API_ID)
RESOURCE_ID=$(echo $RESOURCE | python -c "import sys, json; print(json.load(sys.stdin)['items'][0]['id'])")
# Create POST method for the root resource
aws apigateway put-method \
--rest-api-id $REST_API_ID \
--resource-id $RESOURCE_ID \
--http-method POST \
--no-api-key-required \
--authorization-type NONE
# Create integration for Lambda function
aws apigateway put-integration \
--rest-api-id $REST_API_ID \
--resource-id $RESOURCE_ID \
--http-method POST \
--type AWS \
--integration-http-method POST \
--uri "arn:aws:apigateway:${AWS_REGION}:lambda:path/2015-03-31/functions/${LAMBDA_FUNCTION_ARN}:${LAMBDA_ALIAS}/invocations"
aws apigateway put-method-response \
--rest-api-id $REST_API_ID \
--resource-id $RESOURCE_ID \
--http-method POST \
--status-code 200 \
--response-models '{"application/json": "Empty"}'
aws apigateway put-integration-response \
--rest-api-id $REST_API_ID \
--resource-id $RESOURCE_ID \
--http-method POST \
--status-code 200 \
--response-templates '{"application/json": ""}'
# Add Lambda permission
aws lambda add-permission \
--function-name $IMAGE_NAME:${LAMBDA_ALIAS} \
--statement-id apigateway-access \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:${AWS_REGION}:${AWS_ACCOUNT_ID}:${REST_API_ID}/*/POST/"
# Deploy API Gateway
aws apigateway create-deployment \
--rest-api-id $REST_API_ID \
--stage-name prod
# Output API Gateway endpoint
echo "https://$REST_API_ID.execute-api.$AWS_REGION.amazonaws.com/prod"
Makefile
Buat sebuah Makefile seperti berikut:
.PHONY: deploy-init deploy
deploy-init:
sh deploy/provision-ecr.sh
sh deploy/push-ecr.sh
sh deploy/provision-lambda.sh
sh deploy/provision-api-gateway.sh
deploy:
sh deploy/push-ecr.sh
sh deploy/update-lambda.sh
Deploy
Ketika Anda menjalankan perintah berikut, Lambda dan API Gateway akan di-deploy secara awal:
$ make deploy-init
Proses berikut akan dijalankan dalam make deploy-init
:
- Membuat repository ECR
- Membangun Docker dan mendorong ke ECR
- Membuat Lambda
- Membuat API Gateway
Ketika Anda perlu memperbarui Lambda dengan gambar Docker yang diperbarui, jalankan perintah berikut:
$ make deploy
Proses berikut akan dijalankan dalam make deploy
:
- Membangun Docker dan mendorong ke ECR
- Memperbarui Lambda