引言
在现代云计算环境中,Lambda 函数是一种常见的无服务器计算服务,用于构建和执行应用程序的功能。为了实现 Lambda 函数的更新控制,我们可以使用 Jenkins,一个流行的持续集成和持续交付(CI/CD)工具。本文将介绍如何在 Jenkins 中通过参数化构建过程和 Extended Choice Parameter 插件,实现对特定 Lambda 函数的自动化构建与部署。
Jenkins 构建 Lambda 函数的意义与目的
Lambda 函数的构建和部署通常涉及多个步骤,包括代码上传、依赖解析、更新函数代码、发布新版本等。手动执行这些步骤既繁琐又容易出错。通过使用 Jenkins,我们可以实现以下目标:
- 自动化构建: 将 Lambda 函数的构建过程自动化,减少手动操作,提高效率。
- 参数化控制: 使用 Jenkins 的 Extended Choice Parameter 插件,通过参数化控制构建过程,使用户能够选择要构建和部署的 Lambda 函数。
- 集成 AWS 服务: 通过 AWS 的 Boto3 SDK,实现 Jenkins 与 AWS 服务的集成,包括 Secrets Manager 和 Lambda。
- 实时通知: 使用 DingDing 机器人,实现 Lambda 函数部署成功后的实时通知,提高可视化和沟通效果。
Jenkins 构建 Lambda 函数的实现代码详解
Python 部署脚本
#!/usr/bin/python3
import boto3
import requests
import json,os
def get_secret(secret_name, region_name):
"""
从AWS Secrets Manager获取指定的secret。
"""
client = boto3.client(service_name='secretsmanager', region_name=region_name)
return json.loads(client.get_secret_value(SecretId=secret_name)['SecretString'])
def send_dingding_message(lambda_name, token, version):
"""
向DingDing发送一条消息,通知Lambda函数部署成功。
"""
headers = {'Content-Type': 'application/json'}
data = {
"msgtype": "markdown",
"markdown": {
"title": f"Restart {lambda_name} Success",
"text": f"<font face='黑体' color='#00EC00'>Restart {lambda_name} VERSION:{version} Success</font>\n"
}
}
response = requests.post(f"https://oapi.dingtalk.com/robot/send?access_token={token}", headers=headers, data=json.dumps(data))
print(response.text)
def update_lambda_function_and_get_version(lambda_name, s3_bucket, s3_key, region):
"""
使用boto3更新Lambda函数的代码并发布新版本,然后返回新版本号。
"""
client = boto3.client('lambda', region_name=region)
response = client.update_function_code(
FunctionName=lambda_name,
S3Bucket=s3_bucket,
S3Key=s3_key,
Publish=True
)
return response['Version']
# 从Secrets Manager获取DingDing token
token = get_secret('base', 'us-east-1')['BUILD1_TOKEN']
# 定义Lambda函数的配置
lambda_config = {
"S-iot-cvm-account": [("us-east-1", "pro-codebuild", "lambda-zip/pro/S-iot-cvm-account.zip")],
"Govee-Skill-Handle-Prod": [
("eu-west-1", "pro-ew1-codebuild", "lambda-zip/pro/S-iot-alexa-skills.zip"),
("us-east-1", "pro-ue1-codebuild", "lambda-zip/pro/S-iot-alexa-skills.zip"),
("us-west-2", "pro-uw2-codebuild", "lambda-zip/pro/S-iot-alexa-skills.zip")
],
"cloud9-iot-rule-intercept-intercept-R8PQYULWSH7M": [("us-east-1", "pro-codebuild", "lambda-zip/pro/S-iot-rule.zip")],
"google-assistant-iot-hanlder-prod": [("us-east-1", "pro-codebuild", "lambda-zip/pro/S-iot-google-actions.zip")]
}
# 从Jenkins环境变量获取Lambda函数的名称
lambda_names = os.environ['LAMBDA_NAMES'].split(',')
# 更新Lambda函数并发送DingDing消息
for lambda_name in lambda_names:
if lambda_name in lambda_config:
for region, s3_bucket, s3_key in lambda_config[lambda_name]:
version = update_lambda_function_and_get_version(lambda_name, s3_bucket, s3_key, region)
send_dingding_message(lambda_name, token, version)
else:
print(f"Warning: No configuration found for {lambda_name}")
Shell部署脚本
#!/bin/bash
get_secret() {
secret_name=$1
region_name=$2
aws secretsmanager get-secret-value --secret-id $secret_name --region $region_name --query 'SecretString' --output text
}
send_dingding_message() {
lambda_name=$1
token=$2
version=$3
headers='Content-Type: application/json'
data="{\"msgtype\": \"markdown\", \"markdown\": {\"title\": \"Restart $lambda_name Success\", \"text\": \"<font face='黑体' color='#00EC00'>Restart $lambda_name VERSION:$version Success</font>\"}}"
curl -s -X POST "https://oapi.dingtalk.com/robot/send?access_token=$token" -H "$headers" -d "$data"
}
update_lambda_function_and_get_version() {
lambda_name=$1
region=$2
s3_bucket=$3
s3_key=$4
aws lambda update-function-code --function-name $lambda_name --region $region --s3-bucket $s3_bucket --s3-key $s3_key --publish | jq -r .Version
}
# 从Secrets Manager获取DingDing token
token=$(get_secret 'base' 'us-east-1' | jq -r .BUILD1_TOKEN)
# 定义Lambda函数的配置
lambda_config=(
"S-iot-cvm-account:us-east-1:pro-codebuild:lambda-zip/pro/S-iot-cvm-account.zip"
"Govee-Skill-Handle-Prod:eu-west-1:pro-ew1-codebuild:lambda-zip/pro/S-iot-alexa-skills.zip"
"Govee-Skill-Handle-Prod:us-east-1:pro-ue1-codebuild:lambda-zip/pro/S-iot-alexa-skills.zip"
"Govee-Skill-Handle-Prod:us-west-2:pro-uw2-codebuild:lambda-zip/pro/S-iot-alexa-skills.zip"
"cloud9-iot-rule-intercept-intercept-R8PQYULWSH7M:us-east-1:pro-codebuild:lambda-zip/pro/S-iot-rule.zip"
"google-assistant-iot-hanlder-prod:us-east-1:pro-codebuild:lambda-zip/pro/S-iot-google-actions.zip"
)
# 从Jenkins环境变量获取Lambda函数的名称
IFS=',' read -ra lambda_names <<< "$LAMBDA_NAMES"
# 更新Lambda函数并发送DingDing消息
for lambda_config_entry in "${lambda_config[@]}"; do
IFS=':' read -ra config <<< "$lambda_config_entry"
lambda_name=${config[0]}
region=${config[1]}
s3_bucket=${config[2]}
s3_key=${config[3]}
if [[ " ${lambda_names[@]} " =~ " $lambda_name " ]]; then
version=$(update_lambda_function_and_get_version $lambda_name $region $s3_bucket $s3_key)
send_dingding_message $lambda_name $token $version
else
echo "Warning: No configuration found for $lambda_name"
fi
done
注意:
- 在 Shell 中,数组的声明和使用方式与 Python 不同。上面的
lambda_config
数组包含了 Lambda 函数的配置信息。 - 使用
jq
工具来解析 JSON 数据,确保其在系统上可用。如果没有安装,请根据系统环境选择合适的安装方式。 LAMBDA_NAMES
环境变量应该包含您要部署的 Lambda 函数的名称,以逗号分隔。
使用 Extended Choice Parameter 进行参数化构建
在 Jenkins Job 的配置中,使用 Extended Choice Parameter 插件,定义了一个名为 LAMBDA_NAMES
的参数,其值为需要构建和部署的 Lambda 函数的名称列表。
Name: LAMBDA_NAMES
Parameter Type: Check Boxes
Number of Visible Items: 10
Delimiter:,
Quote Value: S-iot-cvm-account,Govee-Skill-Handle-Prod,cloud9-iot-rule-intercept-intercept-R8PQYULWSH7M,google-assistant-iot-hanlder-prod
总结
通过 Jenkins 构建 Lambda 函数的自动化流程,我们实现了对 Lambda 函数更新控制的一体化解决方案。使用参数化构建,我们可以轻松选择并部署特定的 Lambda 函数,同时通过 DingDing 机器人实时通知,提高了构建过程的可视化和沟通效果。这种自动化流程不仅减轻了开发人员的负担,还提高了整个团队的工作效率。
在实际应用中,可以根据团队的需求进行更多定制和扩展,例如添加更多的构建步骤、日志记录、错误处理等。通过 Jenkins 构建 Lambda 函数的自动化流程,将使开发团队更加专注于业务逻辑的实现,提高开发效率,降低出错风险。