GitLab CI运行Lambda旧版本清理Python脚本报错如何解决
报错根因
CI配置中使用了shell的source语法(. 命令)执行Python脚本,该语法会将文件内容作为shell命令解析,而不是调用Python解释器运行代码,因此shell读到首行的import关键字时会抛出command not found错误。
另外原配置和脚本还存在几个隐性问题:
- 未确认运行环境是否安装
boto3依赖 - 未处理Lambda API的分页逻辑,函数/版本数量超过API单次返回上限时会漏清理
- 未提前过滤被别名绑定的版本,触发删除时会直接抛异常中断任务
- 原脚本中删除逻辑的代码是注释状态,实际执行不会真的删除版本
正确配置方法
按照以下步骤调整即可正常运行:
- 修正脚本执行命令,不要使用
.前缀调用Python脚本,优先直接指定Python解释器执行,兼容性最好:
修正后的.gitlab-ci.yml片段参考:delete-lambda-versions-nonprod: stage: import image: "someimage/confidential" <<: *nonprod variables: ENV_TAG: "alpha1" AWS_DEFAULT_REGION: "ap-southeast-1" # 替换为实际Lambda所在区域 script: # 先安装依赖,如果你的自定义镜像已经预装boto3可以跳过这行 - pip3 install boto3 # 调用Python解释器执行脚本,不要加.前缀 - python3 clean_old_lambda_versions.py when: manual - 修复原Python脚本的逻辑缺陷,补充分页、别名过滤逻辑,参考修正后的代码:
#!/usr/bin/env python3 from __future__ import absolute_import, print_function, unicode_literals import boto3 def clean_old_lambda_versions(): client = boto3.client('lambda') # 处理函数列表分页 function_paginator = client.get_paginator('list_functions') for function_page in function_paginator.paginate(): for function in function_page['Functions']: func_name = function['FunctionName'] print(f"Processing function: {func_name}") # 先查询所有别名绑定的版本,加入保留列表 alias_paginator = client.get_paginator('list_aliases') reserved_versions = set() for alias_page in alias_paginator.paginate(FunctionName=func_name): for alias in alias_page['Aliases']: reserved_versions.add(alias['FunctionVersion']) # 拉取全量版本列表 version_paginator = client.get_paginator('list_versions_by_function') all_versions = [] for ver_page in version_paginator.paginate(FunctionName=func_name): all_versions.extend(ver_page['Versions']) # 过滤掉$LATEST,按版本号排序取最大的那个作为最新发布版本加入保留列表 published_versions = [v for v in all_versions if v['Version'] != '$LATEST'] published_versions.sort(key=lambda x: int(x['Version']), reverse=True) if published_versions: reserved_versions.add(published_versions[0]['Version']) reserved_versions.add('$LATEST') # 遍历删除不在保留列表里的版本 for version in all_versions: ver_num = version['Version'] if ver_num not in reserved_versions: arn = version['FunctionArn'] print(f"Deleting old version: {arn}") # 测试没问题后再取消下面这行的注释执行实际删除 # client.delete_function(FunctionName=arn) print(f"{func_name}: cleanup completed") if __name__ == '__main__': clean_old_lambda_versions() - 确认GitLab Runner配置的AWS凭证有权限执行Lambda的
lambda:ListFunctions、lambda:ListVersionsByFunction、lambda:ListAliases、lambda:DeleteFunction权限,否则会报权限不足错误。
可选替代方案
- 方案一:基于AWS CLI实现清理逻辑,无需Python依赖,只要运行镜像预装AWS CLI即可,通过shell循环完成版本遍历、过滤、删除操作,逻辑更轻量。
- 方案二:将保留版本数做成CI可配置变量,比如通过
KEEP_VERSIONS_COUNT变量控制保留最近N个发布版本,而不是硬编码只保留1个最新版本,适配不同环境的版本保留需求。 - 方案三:如果是多账号环境,在CI脚本中加入STS跨账号角色扮演逻辑,通过GitLab存储的对应环境凭证获取临时访问密钥后再执行清理,避免给Runner服务账号开放过宽的权限。
内容的提问来源于stack exchange,提问作者deepan
相关产品推荐
相关产品推荐

