在使用Terraform进行配置管理的同时部署AWS Lambda
我是yuua,属于DMM数据基础设施部门。
在使用terraform创建并部署lambda函数时,如果将lambda函数包含在terraform中,可能会导致变更和操作变得复杂。
因此,我想记录下那些导致困扰的情况和相应的操作步骤。
这次的lambda不是lambda容器。
第一步操作
1. 使用Terraform创建Lambda函数的基本前置信息(如部署位置等)。
2. 将Lambda函数压缩为zip格式并放置在S3存储桶中。
持之以恒的部署步骤
我通常使用Github Actions等CI/CD工具。
1. 使用Github Actions将Lambda函数/ Lambda层部署到存储桶中。
2. 使用Github Actions执行函数的更新操作。
做好准备
使用 Terraform 创建用于分配 Lambda 的 S3 key 等。
// bucket作成
resource "aws_s3_bucket" "lambda_bucket" {
bucket = "lambda-bucket"
}
// lambda関数配置するようのkeyを作成
resource "aws_s3_bucket_object" "lambda_function" {
key = "functions/nodejs/"
bucket = aws_s3_bucket.lambda_bucket.id
}
// layerを使う場合はlayer用も
resource "aws_s3_bucket_object" "lambda_layer" {
key = "layers/nodejs/hoge/"
bucket = aws_s3_bucket.lambda_bucket.id
}
现在暂时执行 terraform apply
部署lambda函数
默认的 node.js lambda
exports.handler = async (event) => {
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
将上述内容打包为 zip 文件,并将其放置在之前创建的 s3 key 中。
放置的方式可以使用 cli、控制台或 ci,任何方式都可以。
lambda资源定义
在将函数部署到s3后,使用terraform定义lambda函数。
data "aws_iam_policy_document" "role" {
statement {
actions = ["sts:AssumeRole"]
effect = "Allow"
principals {
identifiers = ["lambda.amazonaws.com"]
type = "Service"
}
}
}
resource "aws_iam_role" "role" {
name = "${var.function_name}-lambda"
assume_role_policy = data.aws_iam_policy_document.role.json
}
// logginなど必要であれば、適宜roleにattachなどしてください
// 関数定義
resource "aws_lambda_function" "function" {
function_name = var.function_name
handler = var.handler
role = aws_iam_role.role.arn
runtime = var.runtime
s3_bucket = bucketを指定
s3_key = 配置したkeyを指定
layers = [layerを使うのであれば指定]
}
实施 terraform apply。
上述的lambda函数已经创建完成,发布等选项可以根据需要进行相应调整。
为了进行持续部署
我认为基本上一旦创建就结束的情况并不多,所以我会创建定义来实现持续的部署。
在这里定义 GitHub Actions,并在从Pull Request到各个分支被关闭/合并的时候进行部署,以便能够进行部署。
在从外部进行部署时,创建一个具有所需权限的用户,并使用该用户的密钥。
大致上可能需要的权限
s3:PutObject
s3:GetObject
s3:DeleteObject
s3:ListBucket
lambda:GetFunction
lambda:UpdateFunctionCode
lambda:UpdateFunctionConfiguration
// layerがいるなら
lambda:GetLayerVersion
lambda:PublishLayerVersion
lambda:ListLayerVersions
lambda:AddLayerVersionPermission
GitHub Actions是一種定義行為的工具。
匿名函数 (ní shù)
以下是关于自助主机设置的定义,但通常情况下使用GitHub托管或自助主机都没有问题。
name: deploy-function
on:
pull_request:
branches:
- ブランチ名
types: [closed]
jobs:
update-functions:
name: lambda deploy
runs-on: [self-hosted, linux]
if: github.event.pull_request.merged == true // mergeされたら処理継続
steps:
- name: Checkout
uses: actions/checkout@v2
- name: code build
uses: actions/setup-node@v2
with:
node-version: "14"
cache: "npm"
- run: npm install // 必要であれば
- run: npx webpack // buildなどあれば
// aws credentialを設定
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: リージョン
// zipファイルを作成
- name: compression
working-directory: ./dist
run: zip function.zip main.js
- name: lambda update function codes
working-directory: ./dist
run: |
aws lambda update-function-code --function-name function名 --zip-file fileb://function.zip
// 必要であればpublish
将代码压缩成zip文件,并执行aws cli中的update-function-code命令。
这样,在PR关闭/合并时将执行部署操作。
Lambda层
如果 `layer` 是一个节点,那么需要将 `nodejs/node_modules` 进行压缩。在这里,我们还在lambda函数之外定义了一个供 `layer` 使用的目录,并在其中放置了 `package.json`。
name: lambda-layer-deploy
on:
pull_request:
branches:
- develop
types: [closed]
paths:
- "layerのpath/**"
jobs:
update-functions:
name: lambda layer deploy
runs-on: [self-hosted, linux]
if: github.event.pull_request.merged == true
steps:
- name: Checkout
uses: actions/checkout@v2
- name: code build
uses: actions/setup-node@v2
with:
node-version: "14"
cache: "npm"
- name: lambda layer
working-directory: ./layer
run: |
mkdir nodejs
cp package*.json nodejs/
npm install --prefix ./nodejs --production
zip -r package.zip nodejs/node_modules
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: リージョン
- name: lambda layer deploy
working-directory: ./layer
run: aws lambda publish-layer-version --layer-name layer名 --zip-file fileb://package.zip --compatible-runtimes nodejs14.x
// 現在のlatestを取得
- name: lambda layer latest version
id: step1
run: |
layer=$(aws lambda list-layer-versions --layer-name layer名 --query 'LayerVersions[0].LayerVersionArn')
echo "::set-output name=layer_ver::$layer"
- name: lambda update configure
run: |
aws lambda update-function-configuration --function-name function名 --layers ${{ steps.step1.outputs.layer_ver }} //複数layerがある場合は ${{ hogehoge }} ${{ foobar }} このような形で続けてかけます
总结
我把创建Lambda资源的Terraform环境以备忘录的形式总结了下来,并使用CI/CD进行持续部署。
由于IaC和Lambda函数的代码被分离了,也不必考虑太多事情,所以如果不使用Lambda容器的话,目前我认为这是最方便的方式。
在数据基础设施部门,我们负责AWS上的大数据基础设施运维,并进行利用各种资源开展产品开发工作。
我们也进行中途招聘等活动,所以如果您有兴趣,请通过我们公司的网站等渠道进行非正式面谈等,请务必提出申请。