2

我想为我的AWS基础架构和AWS Lambda函数设置CI/CD管道。这个想法是让代码,版本控制和自动化。我只想将git push存储到存储库中,然后让CodePipeline从那里接管,更新我的基础架构,运行测试,并在成功时使用最新的代码更新Lambda函数。通过Cloudformation,CodeBuild和CodePipeline将AWS包部署到AWS Lambda

我基于我的CloudFormation模板this excellent example。它看起来像这样:

AWSTemplateFormatVersion: 2010-09-09 
Description: playground pipeline 1 
Parameters: 
    SourceRepositoryName: 
    Type: String 
    Default: lambda-playground 
    SourceBranchName: 
    Type: String 
    Default: master 

Resources: 
    ArtifactsBucket: 
    Type: AWS::S3::Bucket 
    DependsOn: CloudFormationRole 
    DeletionPolicy: Delete 
    Properties: 
     BucketName: lambda-playground-artifacts 

    CodeBuildRole: 
    Type: AWS::IAM::Role 
    DependsOn: CloudFormationRole 
    Properties: 
     AssumeRolePolicyDocument: 
     Version: 2012-10-17 
     Statement: 
      - Effect: Allow 
      Action: 
       - sts:AssumeRole 
      Principal: 
       Service: 
       - codebuild.amazonaws.com 
     Policies: 
     - PolicyName: ServiceRole 
      PolicyDocument: 
      Version: 2012-10-17 
      Statement: 
       - Sid: CloudWatchWriteLogsPolicy 
       Effect: Allow 
       Action: 
        - logs:CreateLogGroup 
        - logs:CreateLogStream 
        - logs:PutLogEvents 
       Resource: '*' 
       - Sid: CodeCommitPullPolicy 
       Effect: Allow 
       Action: 
        - codecommit:GitPull 
       Resource: '*' 
       - Sid: S3GetObjectPolicy 
       Effect: Allow 
       Action: 
        - s3:GetObject 
        - s3:GetObjectVersion 
       Resource: '*' 
       - Sid: S3PutObjectPolicy 
       Effect: Allow 
       Action: 
        - s3:PutObject 
       Resource: '*' 

    CodePipelineRole: 
    Type: AWS::IAM::Role 
    DependsOn: CloudFormationRole 
    Properties: 
     AssumeRolePolicyDocument: 
     Version: 2012-10-17 
     Statement: 
      - Effect: Allow 
      Action: 
       - sts:AssumeRole 
      Principal: 
       Service: 
       - codepipeline.amazonaws.com 
     ManagedPolicyArns: 
     - arn:aws:iam::aws:policy/AdministratorAccess 

    CloudFormationRole: 
    Type: AWS::IAM::Role 
    Properties: 
     AssumeRolePolicyDocument: 
     Version: 2012-10-17 
     Statement: 
      - Effect: Allow 
      Action: 
       - sts:AssumeRole 
      Principal: 
       Service: 
       - cloudformation.amazonaws.com 
     ManagedPolicyArns: 
     - arn:aws:iam::aws:policy/AdministratorAccess 

    CodeCommitRepository: 
    Type: AWS::CodeCommit::Repository 
    Properties: 
     RepositoryName: !Ref SourceRepositoryName 

    CodeBuildProject: 
    Type: AWS::CodeBuild::Project 
    DependsOn: CloudFormationRole 
    Properties: 
     Description: A playground of Lambda 
     Artifacts: 
     Type: CODEPIPELINE 
     Environment: 
     ComputeType: BUILD_GENERAL1_SMALL 
     Image: aws/codebuild/python:2.7.12 
     Type: LINUX_CONTAINER 
     Name: lambda-playground 
     ServiceRole: !GetAtt CodeBuildRole.Arn 
     Source: 
     Type: CODEPIPELINE 
     TimeoutInMinutes: 5 

    CodePipeline: 
    Type: AWS::CodePipeline::Pipeline 
    Properties: 
     ArtifactStore: 
     Type: S3 
     Location: !Ref ArtifactsBucket 
     Name: !Ref AWS::StackName 
     RestartExecutionOnUpdate: true 
     RoleArn: !GetAtt CodePipelineRole.Arn 
     Stages: 
     - Name: Source 
      Actions: 
      - Name: Source 
       ActionTypeId: 
       Category: Source 
       Owner: AWS 
       Provider: CodeCommit 
       Version: 1 
       Configuration: 
       RepositoryName: !Ref SourceRepositoryName 
       BranchName: !Ref SourceBranchName 
       OutputArtifacts: 
       - Name: SourceOutput 
     - Name: PipelineDeploy 
      Actions: 
      - Name: UpdatePipeline 
       ActionTypeId: 
       Category: Deploy 
       Owner: AWS 
       Provider: CloudFormation 
       Version: 1 
       Configuration: 
       ActionMode: CREATE_UPDATE 
       Capabilities: CAPABILITY_IAM 
       RoleArn: !GetAtt CloudFormationRole.Arn 
       StackName: !Ref AWS::StackName 
       TemplatePath: SourceOutput::infra.yml 
       InputArtifacts: 
       - Name: SourceOutput 
     - Name: Build 
      Actions: 
      - Name: BuildAndTest 
       ActionTypeId: 
       Category: Build 
       Owner: AWS 
       Provider: CodeBuild 
       Version: 1 
       Configuration: 
       ProjectName: !Ref CodeBuildProject 
       InputArtifacts: 
       - Name: SourceOutput 
       OutputArtifacts: 
       - Name: BuildOutput 

    LambdaFunction: 
    Type: AWS::Lambda::Function 
    Properties: 
     Code: 
     S3Bucket: !Ref ArtifactsBucket 
     S3Key: !Ref BuildOutput # DOES NOT WORK 
     FunctionName: playground-fc 
     Handler: src.main.handler 
     # TODO: Role: foo 
     Runtime: python2.7 

Outputs: 
    ArtifactsBucketURL: 
    Description: Artifacts bucket URL 
    Value: !GetAtt ArtifactsBucket.WebsiteURL 
    RepositoryURL: 
    Description: SSH URL of the repository 
    Value: !GetAtt CodeCommitRepository.CloneUrlSsh 

所以我有3个阶段CodePipeline - Source,它从一个CodeCommit回购,PipelineDeploy,这将更新我的CloudFormation堆栈如果有必要和Build,它运行的配置CodeBuild项目抓起代码。

我buildspec.yml是在这里:

version: 0.1 

phases: 
    install: 
    commands: 
     - pip install -r requirements.txt -t lib 
    pre_build: 
    commands: 
     - python lib/pytest.py src 
artifacts: 
    type: zip 
    files: 
    - src/**/* 
    - lib/**/* 

它只是安装必要的库,通过pytest运行测试和创建部署拉链。这个zip文件然后是Build阶段的OutputArtifact并且存储在ArtifactsBucket中。但是,每次都会得到一个唯一的名称(例如dfVV6Uh),这很有道理,但我不知道如何在LambdaFunction - > Properties - > Code - > S3Key字段中引用它。

所以我的问题是,我如何创建一个堆栈/管道,在完成所有步骤之后,将最新版本部署到我的AWS Lambda函数中?有没有办法可能使用CodeDeploy来做到这一点?这里最好的做法是什么?

回答

3

您可以使用Parameter OverrideFn::GetArtifactAttObjectKey属性来动态地提供由AWS CodePipeline生成您的CloudFormation部署行动神器.zip的名称。

使用你的榜样,为您UpdatePipeline CloudFormation部署行动的配置会是这个样子:

Configuration: 
    ActionMode: CREATE_UPDATE 
    Capabilities: CAPABILITY_IAM 
    RoleArn: !GetAtt CloudFormationRole.Arn 
    StackName: !Ref AWS::StackName 
    TemplatePath: SourceOutput::infra.yml 
    ParameterOverrides: 
    { 
     "LambdaKey" : { "Fn::GetArtifactAtt" : ["LambdaFunctionSource", "ObjectKey"]} 
    } 
InputArtifacts: 
- Name: SourceOutput 
- Name: BuildOutput 

然后,声明,然后你的CloudFormation堆栈模板内引用LambdaKey参数:

Parameters: 
    LambdaKey: 
    Type: String 
    # ... 
Resources: 
    LambdaFunction: 
    Type: AWS::Lambda::Function 
    Properties: 
     Code: 
     S3Bucket: !Ref ArtifactsBucket 
     S3Key: !Ref LambdaKey 
     # ... 
+0

所以想法是在单独的CloudFormation模板中声明AWS :: Lambda :: Function?最初,我想在一个模板中包含所有东西,这就是为什么'UpdatePipeline'(一个误导性名称,现在我意识到)的步骤是我的管道中第二个。我的Lambda函数代码是CodeBuild步骤的输出,在管道中是第三个,所以我想我不能在第二步中引用它(我还没有尝试过)。 –

+0

我基于您在您的问题中提供的模板回答了您的问题,该模板引用了'SourceOutput :: infra.yml'。可以将源代码回购库中的模板设置为您用来定义代码管道资源的相同模板,以使其自引用。使用GitHub查看我的回购https://github.com/wjordan/aws-starter-kit以获得完全独立的示例。 – wjordan

+0

我研究了你的aws-starter-kit,并且试图根据你的建议修改我的模板,但没有成功。问题是我想把所有东西都放在一个模板中,这样我就可以引导我的基础架构并不断更新它。为此,在创建Lambda函数资源时,我还没有S3Key,它只是作为我的第三个流水线步骤的输出 - Build操作。我想我会为引导步骤创建一个虚拟部署包。 –

1

有一个如何实现类似的例子(通过CodePipeline/CodeBuild部署lambda函数)。 http://docs.aws.amazon.com/lambda/latest/dg/automating-deployment.html

这个例子是用NodeJS编写的lambda函数,但其​​基本思想是相同的。在通过CodeBuild构建工件后,使用CloudFormation部署/更新您的lambda函数,并让CodePipeline分阶段管理工件传播。

让我知道这是否有帮助。

相关问题