如何构建CI/CD流水线更新控制台创建的现有AWS Lambda代码?
解决控制台创建的AWS Lambda代码更新的CI/CD方案
我来帮你梳理几个针对「仅更新控制台创建的Lambda函数代码、禁止新建函数」需求的可行方案,完美避开你遇到的CloudFormation和CodeDeploy的坑:
方案1:CodePipeline + CodeBuild + AWS CLI(最直接省心)
这个方案完全绕开CloudFormation的资源归属限制,直接用AWS CLI命令更新代码,简单粗暴但有效。
具体配置步骤:
- CodePipeline源码阶段:连接你的代码仓库(GitHub/CodeCommit/GitLab都行),拉取最新的Lambda源码。
- 添加CodeBuild阶段:
- 写一个
buildspec.yml放在代码根目录,负责打包代码并调用CLI更新Lambda:version: 0.2 phases: install: runtime-versions: python: 3.9 # 替换成你的Lambda运行时,比如nodejs18.x build: commands: # 把源码打包成zip(排除.git和buildspec.yml这些无关文件) - zip -r lambda-update-package.zip . -x "*.git*" "buildspec.yml" # 核心命令:更新指定的Lambda函数代码 - aws lambda update-function-code --function-name 你的现有Lambda名称 --zip-file fileb://lambda-update-package.zip artifacts: files: - lambda-update-package.zip - 给CodeBuild的服务角色加上
lambda:UpdateFunctionCode权限,确保它能操作目标Lambda。
- 写一个
- 无需额外部署阶段:CodeBuild跑完就已经完成代码更新了,直接结束流水线就行。
优势:
- 完全适配控制台创建的Lambda,绝对不会触发新建函数的操作。
- 配置成本极低,不需要写复杂的CloudFormation模板。
方案2:CodePipeline + 自定义Lambda动作(更灵活)
如果不想用CodeBuild,可以搞个辅助Lambda来做代码更新的事儿,把它作为CodePipeline的一个自定义动作。
具体操作:
- 写一个辅助Lambda函数:这个函数的任务是从CodePipeline的输出 artifact(存在S3里的代码包)拉取内容,然后调用Lambda的更新API。示例代码(Python):
import boto3 import os from io import BytesIO s3 = boto3.client('s3') lambda_client = boto3.client('lambda') codepipeline = boto3.client('codepipeline') def lambda_handler(event, context): # 从CodePipeline事件里拿到S3的代码包位置 job_details = event['CodePipeline.job'] input_artifact = job_details['data']['inputArtifacts'][0]['location']['s3Location'] bucket = input_artifact['bucketName'] key = input_artifact['objectKey'] # 下载S3里的代码包 s3_response = s3.get_object(Bucket=bucket, Key=key) zip_content = BytesIO(s3_response['Body'].read()) # 更新目标Lambda函数 try: lambda_client.update_function_code( FunctionName=os.environ['TARGET_LAMBDA'], ZipFile=zip_content.getvalue() ) # 告诉CodePipeline任务成功 codepipeline.put_job_success_result(jobId=job_details['id']) except Exception as e: # 失败的话也要通知CodePipeline codepipeline.put_job_failure_result( jobId=job_details['id'], failureDetails={'message': str(e), 'type': 'JobFailed'} ) return {'statusCode': 200} - 配置CodePipeline的自定义动作:
- 在流水线里加一个“Lambda”类型的动作,选择刚才创建的辅助Lambda。
- 给辅助Lambda设置环境变量
TARGET_LAMBDA,值就是你要更新的现有Lambda名称。 - 给辅助Lambda的角色加上
s3:GetObject、lambda:UpdateFunctionCode和codepipeline:PutJobSuccessResult这几个权限。
方案3:修复CodeDeploy的BundleType错误(如果想继续用CodeDeploy)
你遇到的BundleType must be either YAML or JSON错误,本质是CodeDeploy找不到正确的appspec.yml配置文件,或者代码包结构不对。针对控制台创建的Lambda,调整代码包结构就能解决:
正确的代码包结构:
lambda-deploy-package/ ├── appspec.yml └── src/ └── 你的Lambda代码文件(比如index.js、requirements.txt等)
appspec.yml的正确写法:
version: 0.0 Resources: - TargetLambda: Type: AWS::Lambda::Function Properties: Name: 你的现有Lambda名称 CodeUri: src/ Runtime: python3.9 # 匹配你的Lambda运行时
把整个lambda-deploy-package目录打包成zip,上传给CodeDeploy,就能正常识别BundleType了。
不管用哪个方案,记得给流水线/辅助服务的IAM角色配置足够的权限,避免出现权限不足的报错。
内容的提问来源于stack exchange,提问作者taiphalili
相关产品推荐
相关产品推荐

