Python Lambda functions with container images Deployment Automation
1. Introduction
This is the follow-up tutorial of my previous one. As you may see, our deployment pipeline in the last article involves many manual steps. Let see how we can automate the entire process.
If you have not read the previous article, it would be helpful to check it out here.
Code is available at this repo.
2. Deployment steps
2.1. Prerequisite
2.2 Terraform script
There are a few components in terraform script which are there to declare used variables, etc. If you want to know more about it, please check out the code in my repo. I will only talk about the most important file which is ./infra/aws_lambda/main.tf
# IAM role which dictates what other AWS services the Lambda function may access.
resource "aws_iam_role" "lambda_exec" {
name = "${var.app}-${var.env}-iam_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
# Get ECR repository info in terraform
data "aws_ecr_repository" "function_ecr_repo" {
name = "${var.app}-${var.env}"
}
# Apply the image to lambda function
resource "aws_lambda_function" "lambda_function" {
function_name = "${var.app}-${var.env}"
timeout = var.timeout
memory_size = var.memory_size
image_uri = "${data.aws_ecr_repository.function_ecr_repo.repository_url}:${var.app_version}"
package_type = "Image"
role = aws_iam_role.lambda_exec.arn
environment {
variables = {
ENV = var.env
APP = var.app
}
}
}
aws_iam_role
is to create an execution role for AWS Lambda functionaws_ecr_repository
is to get information from the ECR repoaws_lambda_function
is to apply all configurations to the Lambda Function e.g. applying the image uri and execution role we declared above
2.3 Uploading Image script
I have mentioned about this script in the previous article. However, in this tutorial, there will be a small change in URI name. We are now choosing to tag the image with version name instead of the env. Hence, we accept one more input as version and change env
to version
in image_uri
.
# Step 1: Configure AWS credentials and application-related values such as application name, environment (e.g., dev, sqa, uat, and prod), and AWS account number
aws_profile="$1"
aws_region="$2"
env="$3"
app="$4"
aws_account="$5"
version="$6" # New Change
# Step 2: Formulate ECR values
ecr_repo="$app-$env"
base_uri="$aws_account.dkr.ecr.$aws_region.amazonaws.com"
image_uri="$base_uri/$ecr_repo:$version" # New Change
# Step 3: Upload docker image to ECR
# Step 3.1: Docker Image Built
echo "Docker Image Built"
docker build --platform linux/amd64 -t $ecr_repo:$env ../
# Step 3.2: Login into AWS ECR
export ecr_password=$(aws ecr get-login-password --region $aws_region --profile $aws_profile)
eval $ecr_password
echo "Successful ECR Login"
docker login --username AWS --password $ecr_password $base_uri
# Step 3.3: Tag the Docker image
docker tag $ecr_repo:$env $image_uri
echo "Successfully tagged the ECR image"
# Step 3.4: Push the Docker image to ECR repository
docker push $image_uri
echo "Successfully pushed the Docker image to ECR"
2.4 Deployment script
I have also mentioned about this script in the last article. However, the previous script stops at uploading the image to ECR repo. In this new script, we will add the part running terraform script.
# Step 1: Get the environment
if [ -z "$1" ]; then
env="dev"
else
env=$(awk '{print tolower($0)}' <<< "$1")
fi
# Step 2: Specify your aws credentials and app name
aws_profile="AdministratorAccess-007985056474"
app="lambda-docker"
aws_account="007985056474"
aws_region="ap-southeast-1"
version="0.0.1"
# Step 3: Run uploading image script
source ./upload_image.sh $aws_profile $aws_region $env $app $aws_account $version
# Step 4: Configure variable for terraform script
export TF_VAR_aws_profile=$aws_profile
export TF_VAR_env=$env
export TF_VAR_app=$app
export TF_VAR_app_version=$version
# Step 5: Run terraform script
cd ../infra/$env
terraform init
# Generate and show an execution plan
terraform plan -var-file=tfvariables.tfvars
# Apply the changes
terraform apply -auto-approve -var-file=tfvariables.tfvars
If you notice, we also added version
variable in this deployment script to match with the uploading script.
2.5. Create repository in ECR
Please refer to point 3.5 in my previous article.
2.6 Deploy
After creating ECR repo, you should be able to deploy your code to Lambda function with created deployment script.
- Navigate the ternimal to
deployment
folder - Run `deploy.sh` file with the command
bash deploy.sh
Here is the result:
3. Redeployment
After you changed the handler code and updated all dependencies, simply run the script like what we have done in step 2.6. Please make sure that you change the code version
inside the script.
4. Deploy to different environment
If you are following my code folder structure, you may notice that this facilitate to deployment to different enviroment e.g. sqa
. I will demonstrate how we can deploy the current code to sqa
environment.
- Create duplicate version of
./infra/dev
and rename itsqa
. Because there is no configuration change between our environments, we do not need to change anything insqa
folder. Make sure that you delete all cache files/folder in the folder such as .terraform, .terraform.lock.hcl, terraform.tfstate, terraform.tfstate.backup. - Create a new ECR repo for the new environment e.g.
lambda-docker-sqa
. Please refer to step 2.5. - Repeat step 2.6 with a new command
bash deploy.sh sqa
Here is what you get out of it:
5. What’s next
In the next article, we will develop a complete solution for text masking service utilizing Presidio. Stay tuned for my next articles.