[PYTHON] CodeCommit + CodePipeline avec CDK

introduction

Cet article présente le mécanisme de téléchargement de fichiers sur S3 avec CodeCommit + CodePipeline, que j'ai essayé de faire un prototype en étudiant AWS CDK. Dans l'équipe d'ingénieurs, il y avait une voix disant «Je veux le toucher», et cela m'intéressait, mais j'ai entendu une réputation d'ingénieurs d'un autre département dire «CDK est bon», alors je l'ai touché.

Qu'est-ce qu'AWS CDK?

Qu'est-ce que AWS CDK? ʻAWS Cloud Development Kit (AWS CDK) modélise et provisionne les ressources des applications cloud à l'aide d'un langage de programmation familier. C'est un cadre de développement de logiciel open source pour ce faire. Il est pratique de définir l'infrastructure avec Python ou TypeScript.

Contexte

Le plus tôt

Dans le passé, Cloud 9 était utilisé comme environnement de production, mais les exigences de sélection à l'époque sont

  1. Peut être édité en même temps
  2. Vous pouvez prévisualiser les artefacts
  3. La certification de base est incluse dans l'aperçu
  4. Le contrôle de version est possible

Donc, j'ai fait une chose que les fichiers html et les fichiers image peuvent être téléchargés de Cloud9 vers S3 via CodeCommit avec Cloud9 + Codecommit + Lambda + CloudFront + Lambda @ edge + S3 et peuvent être prévisualisés via CloudFront. Au début, il semblait bien tourner.

problème

Cloud9, qui semblait initialement bien fonctionner, est progressivement devenu problématique.

  1. Certains fichiers ne sont pas téléchargés vers S3. (Ceci est suspect que CodeCommit → S3 soit fait par Lambda)
  2. Le nombre de projets augmente et la capacité de Cloud9 est réduite (car c'est un produit d'image morimori ...)
  3. Il y a un signe que la fonction d'édition simultanée n'est pas utilisée en premier lieu ...

Il n'y avait donc pas besoin de Cloud9. Si tel est le cas, l'élan de la refonte s'est accéléré en disant qu'il serait préférable de le faire localement et de passer à S3. (Étant donné que les membres qui codent réellement ne sont pas ceux qui touchent AWS, je voulais également fournir un formulaire qui ne soit pas directement confronté à AWS autant que possible.)

Sujet principal

Pour le remake, nous avons adopté le CDK dont nous avons entendu des rumeurs dans l'entreprise. CDK est en charge de la création de ressources pour CodeCommit, CodePipeline et CodeBuild sur le côté gauche de la figure ci-dessous. (S3 + CloudFront + Lambda @ edge est identique au précédent.)

codecommit_diagram.png

À l'ère du Cloud9, ce qui était «1Cloud9 (instance 1EC2) = multiple matière = 1 référentiel» a été remplacé par «1 matière = 1 référentiel». Par cd k deploy au début du projet, le référentiel est créé et CodePipeline est préparé sur CodeCommit, et chaque fois que vous poussez vers master, le fichier est téléchargé sur S3 par CodeBuild.

la mise en oeuvre

Selon Documentation

$ npm install -g aws-cdk
$ mkdir test
$ cd test
$ cdk init test --language python
$ source .env/bin/activate
$ pip install -r requirements.txt

Commencez comme.

app.py


#!/usr/bin/env python3
import os
from os.path import join, dirname
from dotenv import load_dotenv

from aws_cdk import core
from test.test_stack import TestStack


dotenv_path = join(dirname(__file__), '.env_file')
load_dotenv(dotenv_path)


app = core.App()
TestStack(app,
          "test",
          repo_name=os.environ["REPOSITORY_NAME"],
          env={"account": "xxxxxxxxxxxx", "region": "ap-northeast-1"})
app.synth()

test_stack.py


from aws_cdk import core
from aws_cdk import aws_codecommit as codecommit
from aws_cdk import aws_codebuild as codebuild
from aws_cdk import aws_codepipeline as codepipeline
from aws_cdk import aws_codepipeline_actions as codepipeline_actions
from aws_cdk import aws_iam as iam

class TestStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, repo_name: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        #Nom du compartiment de la destination de sortie
        s3_bucket_name = "test-bucket"
    
        #Créer un référentiel CodeCommit
        repo = codecommit.Repository(self,
                                     "Repository",
                                     repository_name=repo_name,
                                     description="test.")
        repository = codecommit.Repository.from_repository_arn(self, repo_name, repo.repository_arn)

        #Définition du pipeline de code
        pipeline = codepipeline.Pipeline(self,
                                         id=f"test-pipeline-{repo_name}",
                                         pipeline_name=f"test-pipeline-{repo_name}")
        source_output = codepipeline.Artifact('source_output')

        #Ajouter CodeCommit
        source_action =  codepipeline_actions.CodeCommitSourceAction(repository=repository,
                                                                     branch='master',
                                                                     action_name='source_collect_action_from_codecommit',
                                                                     output=source_output,
                                                                     trigger=codepipeline_actions.CodeCommitTrigger.EVENTS)
        pipeline.add_stage(stage_name='Source', actions=[source_action])

        #Ajouter CodeBuild
        cdk_build = codebuild.PipelineProject(self,
                                              "CdkBuild",
                                              build_spec=codebuild.BuildSpec.from_object(dict(
                                                  version="0.2",
                                                  phases=dict(
                                                      build=dict(
                                                          commands=[f"aws s3 sync ./ s3://{s3_bucket_name}/"]
                                                      )
                                                  )
                                              )))
        cdk_build.add_to_role_policy(
            iam.PolicyStatement(
                resources=[f'arn:aws:s3:::{s3_bucket_name}', f'arn:aws:s3:::{s3_bucket_name}/*'],
                actions=['s3:*']
            )
        )

        build_output = codepipeline.Artifact("CdkBuildOutput")

        build_action = codepipeline_actions.CodeBuildAction(
                            action_name="CDK_Build",
                            project=cdk_build,
                            input=source_output,
                            outputs=[build_output])

        pipeline.add_stage(
            stage_name="Build",
            actions=[build_action]
        )

CodeBuild Quand j'y pense maintenant, je pense que CodeDeploy était bon pour CodeBuild, qui est juste s3 sync. Je veux approfondir la hiérarchie du côté du s3 s3 lorsque je fais s3 sync, mais y a-t-il une bonne solution ...

partie codebuild


#Ajouter CodeBuild
cdk_build = codebuild.PipelineProject(self,
                                      "CdkBuild",
                                      build_spec=codebuild.BuildSpec.from_object(dict(
                                        version="0.2",
                                        phases=dict(
                                        build=dict(commands=[f"aws s3 sync ./ s3://{s3_bucket_name}/"])
                                      ))))

Déployer

plus tard

$ cdk deploy

Vous pouvez le déployer en faisant, mais j'ai créé un script comme suit pour l'utilisateur.

make.sh


#!/bin/bash

if [ $# -ne 1 ]; then
  echo "Il nécessite un argument pour s'exécuter." 1>&2
  echo "Spécifiez le code du projet dans l'argument. (Partiellement utilisé pour l'URL au moment de l'aperçu)"
  exit 1
fi
echo REPOSITORY_NAME=$1 > .env_file
cdk deploy test --profile xxxxxxx
#commettre
git clone ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/$1 ../$1
mkdir ../$1/$1
touch ../$1/$1/.gitkeep
cd ../$1
git checkout -b master
git add -A
git commit -m "initial commit"
git push origin master

Maintenant, prenez le nom du référentiel que vous souhaitez créer comme argument

$ ./make.sh test_repository

Si c'est le cas, tout va bien.

Préoccupation

finalement

Cette fois, j'ai créé un mécanisme pour télécharger des fichiers de CodeCommit vers S3 via CodeBuild en utilisant CDK. Il semble avoir une meilleure réputation qu'à l'ère Cloud9, j'espère donc que vous pourrez l'utiliser tel quel et attendre les commentaires. Je pense que le CDK lui-même est bon car vous n'avez pas à combattre directement CloudFormation.

Recommended Posts

CodeCommit + CodePipeline avec CDK
[AWS] Construire ECR avec AWS CDK
Création d'AWS Fargate Service avec AWS CDK