こんにちは!オルターブースのいけだです! 熱い夏が続きますね!最近は夏バテを払拭しようと辛い食べ物を食べすぎて、お腹の調子が悪くなりました💪
さて、今回はAWSのCodeシリーズの簡単な解説と、 実際にCodeCommit、CodeBuild、CodePiplineを試してみました🙂
AWS Codeシリーズ
AWS Codeシリーズは、AWSが提供する開発者向けの一連のサービスで、 ソフトウェアの開発とデプロイを効率化するためのツール群です。 以下は代表的なサービスです。
また、以下の表は用途毎で分類した表になります。
主な用途 | サービス名 |
---|---|
ソースコード管理 | AWS CodeCommit |
IssueベースのProject管理 | Amazon CodeCatalyst |
デプロイパイプライン | AWS CodeBuild / AWS CodeDeploy / AWS CodePipeline |
コードスキャニング | Amazon CodeGuru セキュリティ |
AIによるサポート | Amazon CodeWhisperer |
目的によって複数のサービスを組み合わせて実現していくイメージでしょうか。
CodeCommit / CodeBuild / CodePipeline を試してみる。
さて、これらを早速試してみようと思います。
下記のCI/CD on AWS ワークショップが非常に分かりやすかったので、こちらに沿って進めます。
因みにこちらのワークショップを進めるにあたり、AWS CDKが利用可能であることが前提です。
セットアップが済んでいない場合はCDKワークショップを参考に環境とCDKの使用感を確認しておくのが良いと思います。
また、CI/CDワークショップはLab 6までありますが、今回はLab3までを割愛して記載しています。
大まかな手順としては以下の通りです。
- ローカルにReactアプリとDockerfileを準備。
- CDKでCodeCommitレポジトリを作成し、ソースコードをプッシュする。
- CodeBuildによるビルドとテスト、ECRへの継続的デリバリー。
1の手順については割愛し、2.の手順に入っていきます。
まずCDKでCodeCommitレポジトリを準備します。
#cdkプロジェクトの作成 cdk init app --language=typescript
#lib/pipeline-cdk-stack.ts import { CfnOutput, Stack, StackProps } from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as codecommit from 'aws-cdk-lib/aws-codecommit'; export class PipelineCdkStack extends Stack { constructor(scope: Construct, id: string, props: StackProps) { super(scope, id, props); //CodeCommitレポジトリ作成 const sourceRepo = new codecommit.Repository(this, 'CICD_Workshop', { repositoryName: 'CICD_Workshop', description: 'Repository for my application code and infrastructure', }); //作成したレポジトリのURLを出力 new CfnOutput(this, 'CodeCommitRepositoryUrl', { value: sourceRepo.repositoryCloneUrlHttp }); } }
#bin/app-cdk.ts import 'source-map-support/register'; import * as cdk from 'aws-cdk-lib'; import { AppCdkStack } from '../lib/app-cdk-stack'; import { PipelineCdkStack } from '../lib/pipeline-cdk-stack' const app = new cdk.App(); new AppCdkStack(app, 'AppCdkStack', {}); new PipelineCdkStack(app, 'pipeline-stack', {});
#デプロイ cdk deploy pipeline-stack
コンソールで確認すると、レポジトリができているのが確認できます。
今回、このレポジトリにはユーザID/パスワード による認証(HTTPS)で接続してみようと思います。
因みに、HTTPS(GRC)認証というIAMユーザーの権限設定のみで利用可能な方法もあるようです。 複数アカウント持っているならこの方法が良さそうです。
IAMに移動し、CodeCommitを利用するIAMユーザー(今回は自分の)に、AWSCodeCommitFullAccess
を割り当てます。
ついでに、この後使うCodeBuildとCodePipelineについてもフルアクセスのポリシーを割り当てておきます。
次にIAMユーザー
のセキリュティ認証情報
にAWS CodeCommit の HTTPS Git 認証情報
から認証情報を生成します。
ここで得られるユーザー名とパスワードがレポジトリへプッシュする際に必要になります。
プルリクエストなどを試してみた所感としては、CodeCommitの操作はシンプルで直感的にも分かりやすい印象を持ちました。
CodeBuildとCodePipeline
Lab3では、CodeBuild/CodePiplineでソースコードのビルド&テスト → Dockerfileのビルド → ECRにイメージをプッシュするところまで行います。
以下は最終的なCDKファイルと設定ファイルになります。
# lib/ecr-cdk-stack.ts //ECR用のスタックを新しく作成 import { Stack, StackProps } from "aws-cdk-lib"; import { Construct } from "constructs"; import * as ecr from "aws-cdk-lib/aws-ecr"; export class EcrCdkStack extends Stack { public readonly repository: ecr.Repository; constructor(scope: Construct, id: string, props: StackProps) { super(scope, id, props); this.repository = new ecr.Repository(this, "my_app"); } }
# lib/pipeline-cdk-stack.ts import { CfnOutput, Stack, StackProps } from "aws-cdk-lib"; import { Construct } from "constructs"; import * as codecommit from "aws-cdk-lib/aws-codecommit"; import * as codepipeline from "aws-cdk-lib/aws-codepipeline"; import * as codebuild from "aws-cdk-lib/aws-codebuild"; import * as codepipeline_actions from "aws-cdk-lib/aws-codepipeline-actions"; import * as ecr from "aws-cdk-lib/aws-ecr"; import * as iam from 'aws-cdk-lib/aws-iam'; interface ConsumerProps extends StackProps { ecrRepository: ecr.Repository; } export class PipelineCdkStack extends Stack { constructor(scope: Construct, id: string, props: ConsumerProps) { super(scope, id, props); //CodeCommit const sourceRepo = new codecommit.Repository(this, "CICD_Workshop", { repositoryName: "CICD_Workshop", description: "Repository for my application code and infrastructure", }); //CodePipeline const pipeline = new codepipeline.Pipeline(this, "CICD_Pipeline", { pipelineName: "CICD_Pipeline", crossAccountKeys: false, }); //CodeBuild(ソースコードをテスト) const codeQualityBuild = new codebuild.PipelineProject( this, "Code Quality", { environment: { buildImage: codebuild.LinuxBuildImage.STANDARD_5_0, privileged: true, computeType: codebuild.ComputeType.LARGE }, // 設定ファイルはbuildspec_test.ymlを参照する buildSpec: codebuild.BuildSpec.fromSourceFilename("buildspec_test.yml"), } ); //CodeBuild (DockerfileをビルドしてECRにプッシュする) const dockerBuildProject = new codebuild.PipelineProject( this, "DockerBuildProject", { environmentVariables: { IMAGE_TAG: { value: "latest" }, IMAGE_REPO_URI: { value: props.ecrRepository.repositoryUri }, AWS_DEFAULT_REGION: { value: process.env.CDK_DEFAULT_REGION }, }, environment: { buildImage: codebuild.LinuxBuildImage.STANDARD_5_0, privileged: true, computeType: codebuild.ComputeType.LARGE }, //設定ファイルはbuildspec_docker.ymlを参照する buildSpec: codebuild.BuildSpec.fromSourceFilename( "buildspec_docker.yml" ), } ); //ECRへのアクセスを許可するIAMポリシー const dockerBuildRolePolicy = new iam.PolicyStatement({ effect: iam.Effect.ALLOW, resources: ["*"], actions: [ "ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:GetRepositoryPolicy", "ecr:DescribeRepositories", "ecr:ListImages", "ecr:DescribeImages", "ecr:BatchGetImage", "ecr:InitiateLayerUpload", "ecr:UploadLayerPart", "ecr:CompleteLayerUpload", "ecr:PutImage", ], }); //作成したIAMポリシーをアタッチ dockerBuildProject.addToRolePolicy(dockerBuildRolePolicy); //各ステージで出力されるArtifact(ファイルのグループを用意) const sourceOutput = new codepipeline.Artifact(); const unitTestOutput = new codepipeline.Artifact(); const dockerBuildOutput = new codepipeline.Artifact(); //CodeCommitのmainからソースコードを取得し、次のステージに渡す pipeline.addStage({ stageName: "Source", actions: [ new codepipeline_actions.CodeCommitSourceAction({ actionName: "CodeCommit", repository: sourceRepo, output: sourceOutput, branch: "main", }), ], }); //このステージではソースコードのテストを行う pipeline.addStage({ stageName: "Code-Quality-Testing", actions: [ new codepipeline_actions.CodeBuildAction({ actionName: "Unit-Test", project: codeQualityBuild, input: sourceOutput, outputs: [unitTestOutput], }), ], }); //このステージではDockerFileをビルドし、ECRへプッシュする pipeline.addStage({ stageName: "Docker-Push-ECR", actions: [ new codepipeline_actions.CodeBuildAction({ actionName: "docker-build", project: dockerBuildProject, input: sourceOutput, outputs: [dockerBuildOutput], }), ], }); new CfnOutput(this, "CodeCommitRepositoryUrl", { value: sourceRepo.repositoryCloneUrlHttp, }); } }
# buildspec_test.yml # ソースコードのビルド仕様 version: 0.2 phases: install: runtime-versions: nodejs: 14 pre_build: commands: - cd ./my-app - echo Installing npm packages... - npm install build: commands: - echo run tests... - CI=true npm run test
# buildspec_docker.yml # Dockerfileビルド仕様 version: 0.2 phases: install: runtime-versions: nodejs: 14 pre_build: commands: - echo Logging in to Amazon ECR... - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $IMAGE_REPO_URI build: commands: - cd ./my-app - echo Build started on `date` - echo Building the Docker image... - docker build -t myapp:$IMAGE_TAG . - docker tag myapp:$IMAGE_TAG $IMAGE_REPO_URI:$IMAGE_TAG post_build: commands: - echo Build completed on `date` - echo Pushing the Docker image... - docker push $IMAGE_REPO_URI:$IMAGE_TAG
buildspec_docker.yml
で使用している環境変数ですが、
CodeBuildにはビルドコマンドで使用できる環境変数がいくつか用意されているようです。
#bin/app-cdk.ts import "source-map-support/register"; import * as cdk from "aws-cdk-lib"; import { AppCdkStack } from "../lib/app-cdk-stack"; import { PipelineCdkStack } from "../lib/pipeline-cdk-stack"; import { EcrCdkStack } from "../lib/ecr-cdk-stack"; const app = new cdk.App(); const ecrCdkStack = new EcrCdkStack(app, "ecr-stack", {}); new AppCdkStack(app, "AppCdkStack", {}); const pipelineCdkStack = new PipelineCdkStack(app, "pipeline-stack", { ecrRepository: ecrCdkStack.repository, });
CDKの変更をデプロイします。
cdk deploy pipeline-stack
新しく、ECRレポジトリ、CodeBuildアクション、CodePipelineが作成されます。
変更をCodeCommitへgit push
します。
各パイプラインが実行されました。
ECRへもプッシュできていますね。
さいごに
今回はワークショップの3章まで記載しましたが、本来はこの後ECSへのCI/CDまで続いています。
CDKでリソースを作成しているので、使い終わったら削除も簡単です!
次回はGitHubとCodeシリーズの組み合わせパターンなんかもやってみようと思います💪
拙い内容で恐縮ですが、ここまでご覧いただきありがとうございました!