Help us understand the problem. What is going on with this article?

あえて継続的にデプロイしないElasticBeanstalkへのデプロイ環境を構築しました。

お疲れさまです。@naokiurです。

最近ElasticBeanstalkを用いて、
アプリケーションを構築・稼働させることが、たまにあります。

開発を続けていく上で、欲しい仕組みの一つとして、
継続的デプロイ(Continuous Deployment)があるかと存じます。
AWSの公式でも、クイックスタートとして
AWS CodePipeline を使用した AWS Elastic Beanstalk 環境へのデプロイが掲載されています。
(Continuous DeploymentとContinuous Deliveryは意味が異なる、ということを初めて認識しました…。)

これはとても素晴らしいものだと思うのですが、
局所的な例で恐縮ながら、以下があるとき、
この例を組み替えると、よりマッチしたもの
(いざリリースするときにできなくなったりしなかったり、
作成するリソースを減らすことができたり)
になるのでは、とおもい、検討致しました。

  • 前提
    • アプリケーションのリリースによるシステム閉塞(数分〜数十分)が認められる
    • masterブランチにマージされ、リリース可能となってから、実際にリリースするまで1日以上のラグが発生する場合がある
      • リリースフローに承認がいるとか
        • そのリリースフローを改善したほうがよい、という話はさておき…
      • Manual Approvalは7日間以内に承認・拒否する必要があるので、それ以上間が開くときとか

内容

構成図

structure.png

ビルドまでと、ビルド以降を、CodeBuildとCodePipelineに分けました。
エンジニアがmasterブランチにマージしたら、
CodeBuildによってS3に格納します。

その後、
CodePipelineの「変更をリリースする」クリックすることによって、
ElasticBeanstalkにデプロイされる、
という流れです。
button_for_release.png

最近個人的にAWS CDKが好みなのですが、
今回はCloudFormationで構築しました。
AWS CDKは、ElasticBeanstalkDeployAction的なものがまだ実装されてないとお見受けしたため…。
https://github.com/aws/aws-cdk/issues/2516

ElasticBeanstalkサンプルアプリケーション

簡単Djangoアプリケーションを予め稼働させておきます。
* アプリケーション名
* MyApp
* 環境名
* MySampleEnvironment

/quickstartにアクセスすると、
テキストが返ってくる、という単純なものです。
quickstart_before.png

CodeBuild構築

ビルドしてS3に格納するCodeBuildです。
Github Access Tokenは予めSecrets Managerに入れておきます。
デプロイに使用する際、バージョニングが必要なので、
S3のバージョニングは trueに設定しておきます。

Resources:
    # First: Build Source and Zip, Save to S3(Build Bucket).
    ## This Need
    ##     * S3 Bucket for after Build.
    ##         * This Bucket need versioning for deploy to ElasticBeanstalk.
    ##     * CodeBuild Project
    ##     * GithubCredential for CodeBuild Project
    ##     * IAM Role for CodeBuild Project
    DjangoBuildRole:
        Type: AWS::IAM::Role
        Properties:
            RoleName: DjangoBuildRole
            AssumeRolePolicyDocument:
                Version: "2012-10-17"
                Statement:
                    -
                        Effect: Allow
                        Principal:
                            Service:
                                - codebuild.amazonaws.com
                        Action:
                            - sts:AssumeRole
            Policies:
                - PolicyName: DjangoBuildRoleRolePolicy
                  PolicyDocument:
                      Version: "2012-10-17"
                      Statement:
                          - Sid: S3FullAccess
                            Effect: Allow
                            Action:
                                s3:*
                            Resource:
                                - '*'
                          - Sid: CloudWatchLogAccess
                            Effect: Allow
                            Action:
                                - logs:CreateLogGroup
                                - logs:CreateLogStream
                                - logs:PutLogEvents
                            Resource:
                                - '*'
    SysopsBucket:
        Type: AWS::S3::Bucket
        Properties:
            BucketName: !Sub "naokiur-sysops-bucket-${AWS::AccountId}"
            VersioningConfiguration:
                Status: Enabled
    EBBuildGithubCredential:
        Type: AWS::CodeBuild::SourceCredential
        Properties:
            AuthType: PERSONAL_ACCESS_TOKEN
            ServerType: GITHUB
            Token: '{{resolve:secretsmanager:personal-secrets:SecretString:github-access-token}}'
    DjangoAppEBBuild:
        Type: AWS::CodeBuild::Project
        Properties:
            Name: django-app-build-project
            Source:
                Auth:
                    Type: OAUTH
                BuildSpec: buildspec.yml
                GitCloneDepth: 1
                Location: https://github.com/naokiur/django_app.git
                Type: GITHUB
            ServiceRole: !GetAtt DjangoBuildRole.Arn
            Environment:
                Type: LINUX_CONTAINER
                ComputeType: BUILD_GENERAL1_SMALL
                Image: aws/codebuild/standard:2.0
            Artifacts:
                Type: S3
                Location: !Ref SysopsBucket
                Path: /builds
                Name: django_app.zip
                Packaging: ZIP
            Triggers:
                FilterGroups:
                    - - Type: EVENT
                        Pattern: PULL_REQUEST_CREATED,PULL_REQUEST_UPDATED,PUSH
                      - Pattern: refs/heads/master
                        Type: HEAD_REF
                Webhook: true

CodePipeline構築

上記のS3からファイルを取得し、
ElasticBeanstalkにデプロイするCodePipelineです。
CodePipelineのArtifactStore用のS3 Bucketも作成しました。
こっちはバージョニングがいらないと考えたためです。
OutputArtifactsで指定した内容を、S3に蓄積していくという動きをすると思うのですが、毎回別名で保存されるので)

    # Second: Download Source Zip from S3, Deploy to ElasticBeanstalk.
    ## This Need
    ##     * S3 Bucket
    ##         * This Bucket is not same with 'First'. It is no need versioning.
    ##     * CodePipeline
    ##     * IAM Role for CodePipeline
    CodepipelineBucket:
        Type: AWS::S3::Bucket
        Properties:
            BucketName: !Sub "naokiur-codepipeline-bucket-${AWS::AccountId}"
            VersioningConfiguration:
                Status: Enabled
    EBDeployPipelineRole:
        Type: AWS::IAM::Role
        Properties:
            RoleName: EBDeployPipelineRole
            AssumeRolePolicyDocument:
                Version: "2012-10-17"
                Statement:
                    -
                        Effect: Allow
                        Principal:
                            Service:
                                - codepipeline.amazonaws.com
                        Action:
                            - sts:AssumeRole
            Policies:
                - PolicyName: EBDeployPipelineRolePolicy
                  PolicyDocument:
                      Version: "2012-10-17"
                      Statement:
                          - Sid: S3FullAccess
                            Effect: Allow
                            Action:
                                s3:*
                            Resource:
                                - '*'
                          - Sid: EBFullAccess
                            Effect: Allow
                            Action:
                                - elasticbeanstalk:*
                                - cloudformation:*
                                - autoscaling:*
                                - elasticloadbalancing:*
                            Resource:
                                - '*'
    EBDeployPipeline:
        Type: AWS::CodePipeline::Pipeline
        Properties:
            Name: EBDeployPipeline
            RoleArn: !GetAtt EBDeployPipelineRole.Arn
            ArtifactStore:
                Type: S3
                Location: !Ref CodepipelineBucket
            Stages:
                - Name: Source
                  Actions:
                      - Name: download-source
                        ActionTypeId:
                            Category: Source
                            Owner: AWS
                            Version: "1"
                            Provider: S3
                        Configuration:
                            S3Bucket: !Ref SysopsBucket
                            S3ObjectKey: builds/django_app.zip
                            PollForSourceChanges: false
                        OutputArtifacts:
                            - Name: SourceOutput
                - Name: Deploy
                  Actions:
                      - InputArtifacts:
                            - Name: SourceOutput
                        Name: deploy
                        ActionTypeId:
                            Category: Deploy
                            Owner: AWS
                            Version: "1"
                            Provider: ElasticBeanstalk
                        Configuration:
                            ApplicationName: MyApp
                            EnvironmentName: MySampleEnvironment

トライ

Djangoアプリケーションの内容を変更し、masterへpushします。
django_modify.png

CodeBuildがmasterブランチへのpushを検知し、動きます。
codebuild_begin_build.png

CodeBuild完了後、手動で、CodePipelineを実行します。
codepipeline_start_source.png

返却されるテキストが変わりました!
quickstart_after.png

今後

ビジネスに応じて、参考になれば幸いです。
パラメータ化した方が使いやすくなる部分が結構あると思うので、
もし実務で使うときがあったら、そのようなテンプレートにしていけたらと思っています。

デプロイする際に、AWSコンソール上にログインして、ボタンを押さなければならない
というのがめんどうだな…と思うのですが…
機密性と利便性のトレードオフの部分かも…? と考えています(見当違いだったらすみません)

参考にさせて頂きました

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした