如何通过Jenkins及CloudFormation模板自动化AWS AMI创建?
嗨,我来帮你梳理下在CloudFormation模板里实现自动创建AMI的具体方案,结合你已经配置好的Jenkins和CloudFormation插件,咱们分两种场景来聊:
这是最可靠的生产级方案,能精确控制AMI创建的时机、状态,还能自动处理资源清理,而且能给CloudFormation和Jenkins返回明确的执行结果。
第一步:编写Lambda函数
这个函数要负责调用EC2的CreateImageAPI,还要处理CloudFormation的回调(告知创建成功/失败)。给你个Python示例:import boto3 import cfnresponse ec2 = boto3.client('ec2') def lambda_handler(event, context): try: if event['RequestType'] == 'Create': # 从CloudFormation传入的参数里拿EC2实例ID instance_id = event['ResourceProperties']['InstanceId'] # 调用API创建AMI create_response = ec2.create_image( InstanceId=instance_id, Name=f"Auto-Generated-AMI-{instance_id}-{context.request_id}", Description="Automatically created via CloudFormation + Lambda", NoReboot=True # 按需选择是否重启实例,建议生产环境选True减少 downtime ) ami_id = create_response['ImageId'] # 等待AMI状态变为可用(可选但强烈建议,确保后续流程能正常使用) waiter = ec2.get_waiter('image_available') waiter.wait(ImageIds=[ami_id]) # 向CloudFormation返回成功信号和AMI ID cfnresponse.send(event, context, cfnresponse.SUCCESS, {'ImageId': ami_id}) elif event['RequestType'] == 'Delete': # 可选:当CloudFormation栈被删除时,自动清理对应的AMI ami_id = event['PhysicalResourceId'] ec2.deregister_image(ImageId=ami_id) # 如果有对应的快照,也可以在这里删除 # ec2.delete_snapshot(SnapshotId='快照ID') cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) except Exception as e: # 出错时及时通知CloudFormation,避免栈一直处于创建中状态 cfnresponse.send(event, context, cfnresponse.FAILED, {'ErrorDetail': str(e)})记得给Lambda配置IAM权限:至少需要
ec2:CreateImage、ec2:DeregisterImage、ec2:DescribeImages权限,还要允许它向CloudFormation发送回调请求。第二步:在CloudFormation模板中集成Lambda
先定义你的EC2实例,然后添加自定义资源调用上面的Lambda:Resources: # 你的EC2实例配置 TargetEC2Instance: Type: AWS::EC2::Instance Properties: ImageId: "你的基础AMI ID" InstanceType: t3.micro SecurityGroups: ["你的安全组ID"] # 其他实例配置... # 自动创建AMI的自定义资源 AMICreatorCustomResource: Type: Custom::AutoAMICreator Properties: ServiceToken: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:你的Lambda函数名称 InstanceId: !Ref TargetEC2Instance这样CloudFormation会在EC2实例创建完成后,自动触发Lambda创建AMI,并且等待AMI可用后才标记整个资源创建成功。
如果只是做快速验证,不想写Lambda,可以在EC2的用户数据里加脚本,实例启动后自动创建AMI。但这种方式无法给CloudFormation返回状态,Jenkins没法直接确认AMI是否创建成功,适合测试用。
- 用户数据脚本示例:
注意要给EC2实例的IAM角色添加#!/bin/bash # 等待实例初始化完成(比如安装依赖、配置环境,时间按需调整) sleep 300 # 获取当前实例ID INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) # 调用AWS CLI创建AMI aws ec2 create-image \ --instance-id $INSTANCE_ID \ --name "Test-Auto-AMI-$(date +%Y%m%d-%H%M%S)" \ --description "Created via EC2 user data" \ --no-rebootec2:CreateImage权限,并且实例里要安装AWS CLI(Amazon Linux 2/2023默认自带)。
获取AMI ID:用方法一的话,可以在CloudFormation模板里加输出项,Jenkins就能拿到AMI ID:
Outputs: CreatedAMIId: Value: !GetAtt AMICreatorCustomResource.ImageId Description: The automatically generated AMI IDJenkins里可以用CloudFormation插件的功能,或者直接调用
aws cloudformation describe-stacks --stack-name 你的栈名 --query "Stacks[0].Outputs[?OutputKey=='CreatedAMIId'].OutputValue" --output text来获取这个ID,用于后续部署。资源清理:Jenkins构建结束后,可以触发CloudFormation删除栈,Lambda会自动清理AMI(如果写了Delete逻辑);或者单独调用
aws ec2 deregister-image删除不需要的AMI。错误处理:在Jenkins流程里加个步骤,检查CloudFormation栈的创建状态,如果失败就终止构建并发送通知,避免后续流程走偏。
内容的提问来源于stack exchange,提问作者Walter

