Lambda Sharp Demo
Demo for Lambda Containerized .NET
LICENSE
MIT
Posted on April 30, 2022
You will need several tools, like
dotnet new --install Amazon.Lambda.Templates::6.1.0
dotnet tool install -g Amazon.Lambda.Tools
.There are many options that you may use and explore. In this article, I will use Web API with Container Image.
You may use this command to generate the project:
dotnet new serverless.image.AspNetCoreWebAPI --name Demo
After that, please copy the folder/directory inside Demo to the root directory of the project. Previously you will have files like this:
Demo/src/Demo
Demo/test/Demo.Test
Please move it, so become like this:
src/Demo
test/Demo.Test
Well done! Let's move on to the next step.
I use Terraform to manage my Lambda setup. Unfortunately, I still create/manage Amazon ECR manually, so I will not include the set up of ECR here. My configuration will be like this:
main.tf
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
}
resource "aws_lambda_function" "lambda_container_demo" {
function_name = "lambda_container_demo"
role = aws_iam_role.iam_for_lambda.arn
image_uri = "<your image location in here>" # please update your image inside the quotes
publish = true
package_type = "Image"
tags = {
"env" = "dev"
}
}
resource "aws_lambda_function_url" "lambda_container_demo_dev" {
function_name = aws_lambda_function.lambda_container_demo.function_name
authorization_type = "NONE"
cors {
allow_credentials = true
allow_origins = ["*"]
allow_methods = ["GET", "POST", "PUT", "DELETE"]
allow_headers = ["date", "keep-alive"]
expose_headers = ["keep-alive", "date"]
max_age = 300
}
}
resource "aws_lambda_function_url" "lambda_container_demo_prod" {
function_name = aws_lambda_function.lambda_container_demo.function_name
authorization_type = "AWS_IAM"
cors {
allow_credentials = true
allow_origins = ["*"]
allow_methods = ["*"]
allow_headers = ["date", "keep-alive"]
expose_headers = ["keep-alive", "date"]
max_age = 86400
}
}
You may use that configuration or customize it. Please change the image_uri
before you use it.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
cloud {
organization = "<org>" # change with your organization
workspaces {
name = "<workspace-name>" # please update the workspace name inside the quotes
}
}
}
# Configure the AWS Provider
provider "aws" {
region = "ap-southeast-1" # you may use another region
}
I store the Terraform scripts inside terraform directory. So it will look like this:
src/Demo
test/Demo.Test
terraform/
I will cover the Github Action only. If you are curious to prepare the Amazon ECR, please visit this post.
"github/workflows/deploy.yml"
name: Deploy
on:
push:
branches: [ main ]
tags:
- v*
pull_request:
env:
IMAGE_NAME: 'lambda-sharp'
PROJECT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
jobs:
build-push-docker:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.DEMO_ECR_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.DEMO_ECR_SECRET_KEY }}
aws-region: ap-southeast-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
with:
registries: ${{ secrets.AWS_ACCOUNT_ID }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v3
with:
images: ${{ env.ECR_REGISTRY }}/${{ env.IMAGE_NAME }}
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
- name: Build and push Docker images
uses: docker/build-push-action@v2
with:
context: src/SimpleAPI
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
terraform:
name: 'Terraform'
needs: build-push-docker
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
- name: Terraform Format
id: fmt
run: terraform fmt -check
working-directory: ./terraform
- name: Terraform Init
id: init
run: terraform init
working-directory: ./terraform
- name: Terraform Validate
id: validate
run: terraform validate -no-color
working-directory: ./terraform
- name: Terraform Plan
id: plan
if: github.event_name == 'pull_request'
run: terraform plan -no-color
continue-on-error: true
working-directory: ./terraform
- name: Update Pull Request
uses: actions/github-script@v6.0.0
if: github.event_name == 'pull_request'
env:
PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const output = `#### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\`
#### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\`
#### Terraform Plan 📖\`${{ steps.plan.outcome }}\`
#### Terraform Validation 🤖\`${{ steps.validate.outcome }}\`
<details><summary>Show Plan</summary>
\`\`\`\n
${process.env.PLAN}
\`\`\`
</details>
*Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
- name: Terraform Plan Status
if: steps.plan.outcome == 'failure'
run: exit 1
- name: Terraform Apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
working-directory: ./terraform
run: terraform apply -auto-approve
So, I use two different jobs to deploy my Lambda. 1) I will deploy my Docker Image to ECR. 2) Provision and sync my AWS Lambda with terraform. Please check my architecture here:
Yeah, if you have set up all of them. You may push it to Github. Note: Please set up the Terraform Cloud with AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
. In the Github, you will need those credentials and Terraform API Key/Token (to store/check state in the Terraform Cloud.
You may check my repository.
Demo for Lambda Containerized .NET
MIT
You may check the Lambda Function URL in Lambda Menu.
Next, please visit the URL, and you may find it like this.
After that, we may check another URL.
You might want to know more about AWS Lambda Functions and Terraform. I suggest visiting an article How to Manage AWS Lambda Functions with Terraform.
If you have some questions, please don't hesitate to ask me on Twitter or directly comment here.
Thank you.
I will try to cover Lambda to connect with Amazon RDS (Relational Database Service). After that, I will cover Lambda to be called by any Frontend(s), and maybe I will use React. Stay tune!
Posted on April 30, 2022
Sign up to receive the latest update from our blog.