CFnでGitHub + Fargate + CodePipelineを構築してみる
おはようございます、もきゅりんです。
CFnを使用してGitHub CodePipelineを作成してみたので、まとめておきます。
テンプレートの再利用等で役立てば幸いです。
先日、CodeCommitで構築したFargate+RDS(MySQL5.7)+FlaskをCFnで構築してみるを使った、GitHubでのケースになります。
実際に確認したい場合は、先にこの環境を構築する必要があります。
なお、やってから気付きましたが、こんなのも2年以上前にありました。
そして、上記内容を弊社ブログ記事が丁寧に補足説明しています。
前提条件
- Fargate+RDS(MySQL5.7)+FlaskをCFnで構築してみるが構築済みであること
注意として、今回はCodeCommitではなく、利用するGitHubに今回使うファイルをPushしておくことが変更点となります。
やること
- GitHubの個人用のアクセストークンを取得する
- CFnテンプレートの作成とスタック作成
GitHubの個人用のアクセストークンを取得する
個人用のアクセストークンを使用するようにパイプラインを設定する (GitHub と CLI)に記載されているように、以下の手順でGitHub 個人用アクセストークンを作成します。
- GitHub で、プロフィール写真のドロップダウンオプションから、[Settings] を選択します。
- [Developer settings] を選択してから [Personal access tokens] を選択します。
- [Generate new token] を選択します。
- [Select scopes] で、[admin:repo_hook] および [repo] を選択します。
こんな感じですね。
[Generate token]をクリックすると、トークンが生成されてるので保持しておきます。
ドキュメントにも記載されていますが、下記注意です。
この時点で、生成されたトークンを確実にコピーしてください。このページを閉じた後でトークンを表示することはできません
※ 注 以下ではトークンをそのままテンプレート内でパラメータとして扱っています。後日トークンをSecretsManagerで秘匿するやり方をまとめていますので、必要あればご参照下さい。
[小ネタ] SecretsManagerを使ってCFnのGitHubTokenをシークレットにする
CFnテンプレートの作成とスタック作成
あとは適当なローカルでテンプレートを作成して実行するだけです。
# create-stackコマンドで作成 aws cloudformation create-stack --stack-name github-fargate-pipeline \ --template-body file://`pwd`/sample-pipeline.yml \ --parameters file://`pwd`/paramas.json \ --capabilities CAPABILITY_NAMED_IAM
# deployコマンドで作成 aws cloudformation deploy --template-file sample-pipeline.yml \ --stack-name github-fargate-pipeline \ --parameter-overrides $(jq -r '.[] | [.ParameterKey, .ParameterValue] | join("=")' paramas.json) \ --capabilities CAPABILITY_NAMED_IAM
テンプレートは下記です。
# sample-pipeline.yml AWSTemplateFormatVersion: 2010-09-09 Description: CodePipeline For ECS Fargate with GitHub Parameters: Cluster: Type: String Service: Type: String ContainerName: Type: String ECRName: Type: String GitHubRepositoryName: Type: String GitHubAccountName: Type: String GitHubSecret: Type: String GitHubOAuthToken: Type: String Branch: Type: String PipelineName: Type: String Resources: # CodeBuildに適用するIAMRole CodeBuildServiceRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: codebuild.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: SampleCodeBuildAccess PolicyDocument: Version: "2012-10-17" Statement: - Resource: "*" Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - Resource: !Sub arn:aws:s3:::${ArtifactBucket}/* Effect: Allow Action: - s3:GetObject - s3:PutObject - s3:GetObjectVersion - s3:GetBucketAcl - s3:GetBucketLocation - Resource: "*" Effect: Allow Action: - ecr:GetAuthorizationToken - ecr:BatchCheckLayerAvailability - ecr:GetDownloadUrlForLayer - ecr:GetRepositoryPolicy - ecr:DescribeRepositories - ecr:ListImages - ecr:DescribeImages - ecr:BatchGetImage - ecr:InitiateLayerUpload - ecr:UploadLayerPart - ecr:CompleteLayerUpload - ecr:PutImage # CodePipelineに適用するIAMRole CodePipelineServiceRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: codepipeline.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: SamplePipeline PolicyDocument: Version: 2012-10-17 Statement: - Resource: - !Sub arn:aws:s3:::${ArtifactBucket}/* Effect: Allow Action: - s3:PutObject - s3:GetObject - s3:GetObjectVersion - s3:GetBucketVersioning - Resource: "*" Effect: Allow Action: - codecommit:GetRepository - codecommit:ListBranches - codecommit:GetUploadArchiveStatus - codecommit:UploadArchive - codecommit:CancelUploadArchive - codedeploy:CreateDeployment - codedeploy:GetApplication - codedeploy:GetApplicationRevision - codedeploy:GetDeployment - codedeploy:GetDeploymentConfig - codedeploy:RegisterApplicationRevision - codebuild:StartBuild - codebuild:StopBuild - codebuild:BatchGet* - codebuild:Get* - codebuild:List* - codecommit:GetBranch - codecommit:GetCommit - s3:* - ecs:* - elasticloadbalancing:* - autoscaling:* - iam:PassRole # S3Bucket ArtifactBucket: Type: AWS::S3::Bucket # 外部イベント発生のwebhook PipelineWebhook: Type: "AWS::CodePipeline::Webhook" Properties: Authentication: GITHUB_HMAC AuthenticationConfiguration: SecretToken: !Ref GitHubSecret Filters: - JsonPath: "$.ref" MatchEquals: 'refs/heads/{Branch}' TargetPipeline: !Ref Pipeline TargetAction: SourceAction Name: GitHubPipelineWebhook TargetPipelineVersion: !GetAtt Pipeline.Version RegisterWithThirdParty: "true" # CodeBuild CodeBuildProject: Type: AWS::CodeBuild::Project Properties: Artifacts: Type: CODEPIPELINE Source: Type: CODEPIPELINE BuildSpec: | version: 0.2 phases: pre_build: commands: - echo Logging in to Amazon ECR... - $(aws ecr get-login --no-include-email) - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7) - IMAGE_TAG=${COMMIT_HASH:=latest} build: commands: - echo Build started on `date` - echo Building the Docker image... - docker build -t $REPOSITORY_URI:latest . - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG post_build: commands: - echo Build completed on `date` - echo Pushing the Docker images... - docker push $REPOSITORY_URI:latest - docker push $REPOSITORY_URI:$IMAGE_TAG - echo Writing image definitions file... - echo "[{\"name\":\"${ContainerName}\",\"imageUri\":\"${REPOSITORY_URI}:${IMAGE_TAG}\"}]" > imagedefinitions.json artifacts: files: imagedefinitions.json Environment: PrivilegedMode: true ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/docker:18.09.0-1.7.0 Type: LINUX_CONTAINER EnvironmentVariables: - Name: AWS_DEFAULT_REGION Value: !Ref AWS::Region - Name: REPOSITORY_URI Value: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECRName} - Name: ContainerName Value: !Ref ContainerName Name: !Ref AWS::StackName ServiceRole: !Ref CodeBuildServiceRole # CodePipeLine Pipeline: Type: AWS::CodePipeline::Pipeline Properties: RoleArn: !GetAtt CodePipelineServiceRole.Arn Name: !Ref PipelineName ArtifactStore: Type: S3 Location: !Ref ArtifactBucket Stages: - Name: Source Actions: - Name: SourceAction ActionTypeId: Category: Source Owner: ThirdParty Version: 1 Provider: GitHub Configuration: Owner: !Ref GitHubAccountName Repo: !Ref GitHubRepositoryName PollForSourceChanges: false Branch: !Ref Branch OAuthToken: !Ref GitHubOAuthToken RunOrder: 1 OutputArtifacts: - Name: App - Name: Build Actions: - Name: Build ActionTypeId: Category: Build Owner: AWS Version: 1 Provider: CodeBuild Configuration: ProjectName: !Ref CodeBuildProject RunOrder: 1 InputArtifacts: - Name: App OutputArtifacts: - Name: BuildOutput - Name: Deploy Actions: - Name: Deploy ActionTypeId: Category: Deploy Owner: AWS Version: 1 Provider: ECS Configuration: ClusterName: !Ref Cluster ServiceName: !Ref Service FileName: imagedefinitions.json RunOrder: 1 InputArtifacts: - Name: BuildOutput
# paramas.json [ { "ParameterKey": "Cluster", "ParameterValue": "demo-flask-cluster" }, { "ParameterKey": "Service", "ParameterValue": "demo-flask-service" }, { "ParameterKey": "ContainerName", "ParameterValue": "demo-flask-container" }, { "ParameterKey": "ECRName", "ParameterValue": "ECRName" }, { "ParameterKey": "GitHubRepositoryName", "ParameterValue": "RepositoryName" }, { "ParameterKey": "GitHubAccountName", "ParameterValue": "GitHubAccountName" }, { "ParameterKey": "GitHubSecret", "ParameterValue": "secret" }, { "ParameterKey": "GitHubOAuthToken", "ParameterValue": "xxxxxxxxxxxxxxxxxxxxxxxxx" }, { "ParameterKey": "Branch", "ParameterValue": "master" }, { "ParameterKey": "PipelineName", "ParameterValue": "cfn-github-pipeline" } ]
ファイルを適当に変更してGitHubリポジトリにプッシュしてみます。
$ git add . $ git commit -m "index changed" $ git push
しばらくすると、変更が反映されました。
以上です、どなたかのお役に立てば幸いです。