2

Я использую конвейер кода для развертывания моей инфраструктуры, и я хотел бы иметь возможность развертывать его в разных средах (dev, staging, prod, ...).Как работать с несколькими средами в CodePipeline?

В настоящее время у меня есть файл buildspec.yml, содержащий некоторые инструкции по установке «pip install» и команду «aws cloudformation package». Я также создал 2 трубопровода, один для производства, а другой для разработки, указывающий на 2 разных филиала на github. Проблема в том, что, поскольку в обеих ветвях файлы содержат похожие ресурсы, я, например, столкнулся с именами на кодах S3.

При использовании AWS CLI и облачной информации для создания или обновления стека вы можете передавать параметры с помощью параметра --parameters. Я хотел бы сделать что-то подобное в 2 конвейерах, которые я создал.

Что было бы лучшим решением для решения этой проблемы?

Конечная цель - автоматизировать развертывание нашей инфраструктуры. Наша инфраструктура состоит из пользователей, ключей KMS, Lamdbas (на python), групп и ковшей.

Я создал два трубопровода следующие руководства: http://docs.aws.amazon.com/lambda/latest/dg/automating-deployment.html

Первый трубопровод соединен с главной ветвью репо, содержащий код, а второй к промежуточной ветви. Моя цель - автоматизировать развертывание главной ветви в производственной среде с использованием первого конвейера и промежуточной ветви в промежуточной среде, используя вторую.

Мой buildspec.yml файл выглядит следующим образом:

version: 0.1 
phases: 
    install: 
     commands: 
      - pip install requests -t . 
      - pip install simplejson -t . 
      - pip install Image -t . 
      - aws cloudformation package --template-file image_processing_sam.yml --s3-bucket package-bucket --output-template-file new_image_processing_sam.yml 
artifacts: 
    type: zip 
    files: 
     - new_image_processing_sam.yml 

image_processing_sam.yml файл выглядит следующим образом:

AWSTemplateFormatVersion: "2010-09-09" 
Transform: "AWS::Serverless-2016-10-31" 
Description: Create a thumbnail for an image uploaded to S3 
Resources: 

    ThumbnailFunction: 
    Type: "AWS::Serverless::Function" 
    Properties: 
     Role: !GetAtt LambdaExecutionRole.Arn 
     Handler: create_thumbnail.handler 
     Runtime: python2.7 
     Timeout: 30 
     Description: "A function computing the thumbnail for an image." 

    LambdaSecretEncryptionKey: 
    Type: "AWS::KMS::Key" 
    Properties: 
     Description: "A key used to encrypt secrets used in the Lambda functions" 
     Enabled: True 
     EnableKeyRotation: False 
     KeyPolicy: 
     Version: "2012-10-17" 
     Id: "lambda-secret-encryption-key" 
     Statement: 
      - 
      Sid: "Allow administration of the key" 
      Effect: "Allow" 
      Principal: 
       AWS: "arn:aws:iam::xxxxxxxxxxxxx:role/cloudformation-lambda-execution-role" 
      Action: 
       - "kms:Create*" 
       - "kms:Describe*" 
       - "kms:Enable*" 
       - "kms:List*" 
       - "kms:Put*" 
       - "kms:Update*" 
       - "kms:Revoke*" 
       - "kms:Disable*" 
       - "kms:Get*" 
       - "kms:Delete*" 
       - "kms:ScheduleKeyDeletion" 
       - "kms:CancelKeyDeletion" 
      Resource: "*" 
      - 
      Sid: "Allow use of the key" 
      Effect: "Allow" 
      Principal: 
       AWS: 
       - !GetAtt LambdaExecutionRole.Arn 
      Action: 
       - "kms:Encrypt" 
       - "kms:Decrypt" 
       - "kms:ReEncrypt*" 
       - "kms:GenerateDataKey*" 
       - "kms:DescribeKey" 
      Resource: "*" 

    LambdaExecutionRole: 
    Type: "AWS::IAM::Role" 
    Properties: 
     RoleName: "LambdaExecutionRole" 
     AssumeRolePolicyDocument: 
     Version: "2012-10-17" 
     Statement: 
     - Effect: Allow 
      Principal: 
      Service: 
      - "lambda.amazonaws.com" 
      Action: 
      - "sts:AssumeRole" 
     Policies: 
     - 
      PolicyName: LambdaKMS 
      PolicyDocument: 
      Version: "2012-10-17" 
      Statement: 
       - 
       Effect: "Allow" 
       Action: 
        - "kms:Decrypt" 
       Resource: "*" 
       - 
       Effect: "Allow" 
       Action: 
        - "lambda:InvokeFunction" 
       Resource: "*" 
     ManagedPolicyArns: 
     - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 

    UserGroup: 
     Type: "AWS::IAM::Group" 

    LambdaTriggerUser: 
    Type: "AWS::IAM::User" 
    Properties: 
     UserName: "LambdaTriggerUser" 

    LambdaTriggerUserKeys: 
    Type: "AWS::IAM::AccessKey" 
    Properties: 
     UserName: 
     Ref: LambdaTriggerUser 

    Users: 
    Type: "AWS::IAM::UserToGroupAddition" 
    Properties: 
     GroupName: 
     Ref: UserGroup 
     Users: 
     - Ref: LambdaTriggerUser 

    Policies: 
    Type: "AWS::IAM::Policy" 
    Properties: 
     PolicyName: UserPolicy 
     PolicyDocument: 
     Statement: 
      - 
      Effect: "Allow" 
      Action: 
       - "lambda:InvokeFunction" 
      Resource: 
       - !GetAtt DispatcherFunction.Arn 
     Groups: 
     - Ref: UserGroup 

    PackageBucket: 
    Type: "AWS::S3::Bucket" 
    Properties: 
     BucketName: "package-bucket" 
     VersioningConfiguration: 
     Status: "Enabled" 

Outputs: 
    LambdaTriggerUserAccessKey: 
    Value: 
     Ref: "LambdaTriggerUserKeys" 
    Description: "AWSAccessKeyId of LambdaTriggerUser" 

    LambdaTriggerUserSecretKey: 
    Value: !GetAtt LambdaTriggerUserKeys.SecretAccessKey 
    Description: "AWSSecretKey of LambdaTriggerUser" 

Я добавил действие Deploy в обоих трубопроводах, чтобы выполнить множество изменений, вычисленный во время бета-действия.

Первый трубопровод работает как шарм и делает все, что я ожидаю от него. Каждый раз, когда я нажимаю код в главной ветке, он развертывается.

Проблема, с которой я сталкиваюсь, заключается в том, что когда я нажимаю код в промежуточной ветке, все работает в конвейере до тех пор, пока не будет достигнуто действие развертывания. Действие развертывания попытается создать новый стек, но поскольку это точно тот же файл buildspec.yml и обработчик image_processing_sam.yml, я получаю столкновение имен, как показано ниже.

package-bucket already exists in stack arn:aws:cloudformation:eu-west-1:xxxxxxxxxxxx:stack/master/xxxxxx-xxxx-xxx-xxxx 
LambdaTriggerUser already exists in stack arn:aws:cloudformation:eu-west-1:xxxxxxxxxxxx:stack/master/xxxxxx-xxxx-xxx-xxxx 
LambdaExecutionRole already exists in stack arn:aws:cloudformation:eu-west-1:xxxxxxxxxxxx:stack/master/xxxxxx-xxxx-xxx-xxxx 
... 

Есть ли способ параметризировать buildspec.yml, чтобы иметь возможность добавить суффикс к имени ресурсов в image_processing_sam.yml? Любая другая идея достичь этого приветствуется.

С уважением.

ответ

2

http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline-basic-walkthrough.html

файлы конфигурации шаблона применяются к CloudFormation в CodePipeline с помощью файла параметров, как это:

{ 
    "Parameters" : { 
    "DBName" : "TestWordPressDB", 
    "DBPassword" : "TestDBRootPassword", 
    "DBRootPassword" : "TestDBRootPassword", 
    "DBUser" : "TestDBuser",  
    "KeyName" : "TestEC2KeyName" 
    } 
} 

поместить эти файлы в корневом каталоге вашего репо, и они могут ссылаться на на менее 2 путей.

В вашем CodePipeline CloudFormation:

Configuration: 
    ActionMode: REPLACE_ON_FAILURE 
    RoleArn: !GetAtt [CFNRole, Arn] 
    StackName: !Ref TestStackName 
    TemplateConfiguration: !Sub "TemplateSource::${TestStackConfig}" 
    TemplatePath: !Sub "TemplateSource::${TemplateFileName}" 

Или в консоли в поле конфигурации шаблона: enter image description here

Стоит отметить, формат конфигурационного файла отличается от CloudFormation через кли, используя

-- parameters 

--параметры используют этот формат:

[ 
    { 
    "ParameterKey": "team", 
    "ParameterValue": "AD-Student Life Applications" 
    }, 
    { 
    "ParameterKey": "env", 
    "ParameterValue": "dev" 
    }, 
    { 
    "ParameterKey": "dataSensitivity", 
    "ParameterValue": "public" 
    }, 
    { 
    "ParameterKey": "app", 
    "ParameterValue": "events-list-test" 
    } 
] 

CodePipeline CloudFormation файлы конфигурации шаблона используйте следующий формат:

{ 
    "Parameters" : { 
    "DBName" : "TestWordPressDB", 
    "DBPassword" : "TestDBRootPassword", 
    "DBRootPassword" : "TestDBRootPassword", 
    "DBUser" : "TestDBuser",  
    "KeyName" : "TestEC2KeyName" 
    } 
} 
+1

Привет, у меня нет времени, чтобы проверить это на этой неделе, но я прослежу, чтобы попробовать и принять ваш ответ как можно скорее. Спасибо за ваше время и подробный ответ. – JonathanGailliez

+0

Проведенный вчера пример полного кода доступен здесь. Строка 271: https://github.com/byu-oit-appdev/iac/blob/master/cloudformation/codepipeline/lambda-pipeline-cf.yaml –

+1

Привет, Эрик, я, наконец, уделите время, чтобы попытаться проверить ваше решение. Это действительно способ продолжения. Еще раз спасибо за подробный ответ и за ваше время. С наилучшими пожеланиями. – JonathanGailliez

1

Проверьте ответ Эрика Норда. Это тот, который вы ищете.


Я задал вопрос на форуме AWS, а here.

Вот решение, предоставляемое AWS:

Привет,

Если ваша цель состоит в том, чтобы иметь различные имена ковшей для постановки и мастеров, то другой вариант заключается в использовании параметров CloudFormation.

При редактировании существующего конвейера, если вы редактируете действие, вы можете развернуть панель «Дополнительно» и ввести переопределения параметров, чтобы указать другой префикс ведра для каждого этапа. Вы также можете вводить параметры в виде отдельного файла .json в своем артефакте.

Там же более подробно на том, что здесь: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline-parameter-override-functions.html

Вот через полный ходьбы с различной конфигурацией стеки для тестирования и производства: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline-basic-walkthrough.html

  • Тим.

Вы должны обязательно следовать приведенной документации. Вот решение, которое я придумал ниже.


Вот мое собственное решение, которое меня не устраивало.

Я добавил скрипт, запущенный во время сборки, и изменив свой шаблон, учитывая ARN агента CodeBuild, создающего проект.

Я добавил «BRANCH_NAME», где может возникнуть столкновение имен. Image_processing_sam.yml Сейчас:

AWSTemplateFormatVersion: "2010-09-09" 
Transform: "AWS::Serverless-2016-10-31" 
Description: Create a thumbnail for an image uploaded to S3 
Resources: 

    ThumbnailFunction: 
    Type: "AWS::Serverless::Function" 
    Properties: 
     Role: !GetAtt LambdaExecutionRole.Arn 
     Handler: create_thumbnail.handler 
     Runtime: python2.7 
     Timeout: 30 
     Description: "A function computing the thumbnail for an image." 

    LambdaSecretEncryptionKey: 
    Type: "AWS::KMS::Key" 
    Properties: 
     Description: "A key used to encrypt secrets used in the Lambda functions" 
     Enabled: True 
     EnableKeyRotation: False 
     KeyPolicy: 
     Version: "2012-10-17" 
     Id: "lambda-secret-encryption-keyBRANCH_NAME" 
     Statement: 
      - 
      Sid: "Allow administration of the key" 
      Effect: "Allow" 
      Principal: 
       AWS: "arn:aws:iam::xxxxxxxxxxxxx:role/cloudformation-lambda-execution-role" 
      Action: 
       - "kms:Create*" 
       - "kms:Describe*" 
       - "kms:Enable*" 
       - "kms:List*" 
       - "kms:Put*" 
       - "kms:Update*" 
       - "kms:Revoke*" 
       - "kms:Disable*" 
       - "kms:Get*" 
       - "kms:Delete*" 
       - "kms:ScheduleKeyDeletion" 
       - "kms:CancelKeyDeletion" 
      Resource: "*" 
      - 
      Sid: "Allow use of the key" 
      Effect: "Allow" 
      Principal: 
       AWS: 
       - !GetAtt LambdaExecutionRole.Arn 
      Action: 
       - "kms:Encrypt" 
       - "kms:Decrypt" 
       - "kms:ReEncrypt*" 
       - "kms:GenerateDataKey*" 
       - "kms:DescribeKey" 
      Resource: "*" 

    LambdaExecutionRole: 
    Type: "AWS::IAM::Role" 
    Properties: 
     RoleName: "LambdaExecutionRoleBRANCH_NAME" 
     AssumeRolePolicyDocument: 
     Version: "2012-10-17" 
     Statement: 
     - Effect: Allow 
      Principal: 
      Service: 
      - "lambda.amazonaws.com" 
      Action: 
      - "sts:AssumeRole" 
     Policies: 
     - 
      PolicyName: LambdaKMSBRANCH_NAME 
      PolicyDocument: 
      Version: "2012-10-17" 
      Statement: 
       - 
       Effect: "Allow" 
       Action: 
        - "kms:Decrypt" 
       Resource: "*" 
       - 
       Effect: "Allow" 
       Action: 
        - "lambda:InvokeFunction" 
       Resource: "*" 
     ManagedPolicyArns: 
     - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 

    UserGroup: 
     Type: "AWS::IAM::Group" 

    LambdaTriggerUser: 
    Type: "AWS::IAM::User" 
    Properties: 
     UserName: "LambdaTriggerUserBRANCH_NAME" 

    LambdaTriggerUserKeys: 
    Type: "AWS::IAM::AccessKey" 
    Properties: 
     UserName: 
     Ref: LambdaTriggerUser 

    Users: 
    Type: "AWS::IAM::UserToGroupAddition" 
    Properties: 
     GroupName: 
     Ref: UserGroup 
     Users: 
     - Ref: LambdaTriggerUser 

    Policies: 
    Type: "AWS::IAM::Policy" 
    Properties: 
     PolicyName: UserPolicyBRANCH_NAME 
     PolicyDocument: 
     Statement: 
      - 
      Effect: "Allow" 
      Action: 
       - "lambda:InvokeFunction" 
      Resource: 
       - !GetAtt DispatcherFunction.Arn 
     Groups: 
     - Ref: UserGroup 

    PackageBucket: 
    Type: "AWS::S3::Bucket" 
    Properties: 
     BucketName: "package-bucketBRANCH_NAME" 
     VersioningConfiguration: 
     Status: "Enabled" 

Outputs: 
    LambdaTriggerUserAccessKey: 
    Value: 
     Ref: "LambdaTriggerUserKeys" 
    Description: "AWSAccessKeyId of LambdaTriggerUser" 

    LambdaTriggerUserSecretKey: 
    Value: !GetAtt LambdaTriggerUserKeys.SecretAccessKey 
    Description: "AWSSecretKey of LambdaTriggerUser" 

script.sh сменив "branch_name" в шаблоне:

#!/bin/bash 
echo $CODEBUILD_AGENT_ENV_CODEBUILD_BUILD_ARN 
if [[ "$CODEBUILD_AGENT_ENV_CODEBUILD_BUILD_ARN" == *"master"* ]]; then 
    sed "s/BRANCH_NAME//g" image_processing_sam.yml > generated_image_processing_sam.yml; 
fi 
if [[ "$CODEBUILD_AGENT_ENV_CODEBUILD_BUILD_ARN" == *"staging"* ]]; then 
    sed "s/BRANCH_NAME/staging/g" image_processing_sam.yml > generated_image_processing_sam.yml; 
fi 

buildspec.yml Сейчас:

version: 0.1 
phases: 
    install: 
     commands: 
      # Install required module for python 
      - pip install requests -t . 
      - pip install simplejson -t . 
      - pip install Image -t . 
      - bash ./script.sh 
      # To be able to see any issue in the generated template 
      - cat generated_image_processing_sam.yml 
      # Package the generated cloudformation template in order to deploy 
      - aws cloudformation package --template-file generated_image_processing_sam.yml --s3-bucket piximate-package-bucket --output-template-file new_image_processing_sam.yml 
artifacts: 
    type: zip 
    files: 
     - new_image_processing_sam.yml 

I надеюсь, что он может как-то помочь вам. Я был бы рад, если кто-нибудь сможет предоставить какие-либо улучшения или документацию, которые могли бы помочь.