AWS CodePipeline Step by Step with .NET Core - Repository の作成

Pipelineの作成に伴いまずはRepositoryが必要となるので、今回はCodeCommitを利用。

AWSTemplateFormatVersion: 2010-09-09
Description: AWS CI/CD - CodeCommit

Parameters:
  RepositoryDescription:
    Type: String
    Default: Repository for CI/CD Blog
  RepositoryName:
    Type: String
    Default: ci_cd_blog
  UserName:
    Type: String
    Default: ci_cd_blog_user

Resources:
  Repository:
    Type: AWS::CodeCommit::Repository
    Properties:
      RepositoryDescription: !Ref RepositoryDescription
      RepositoryName: !Ref RepositoryName

  User:
    Type: AWS::IAM::User
    Properties:
      Policies: 
        - PolicyName: !Sub ${UserName}_policy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
                - Effect: Allow
                  Action:
                    - codecommit:GitPull
                    - codecommit:GitPush
                  Resource: !GetAtt Repository.Arn
      UserName: !Ref UserName

Outputs:
  CiCdBlogRepositoryId:
    Value: !Ref Repository
    Export:
      Name: CiCdBlogRepositoryId
  CiCdBlogRepositoryArn:
    Value: !GetAtt Repository.Arn
    Export:
      Name: CiCdBlogRepositoryArn
  CiCdBlogRepositoryCloneUrlHttp:
    Value: !GetAtt Repository.CloneUrlHttp
    Export:
      Name: CiCdBlogRepositoryCloneUrlHttp
  CiCdBlogRepositoryCloneUrlSsh:
    Value: !GetAtt Repository.CloneUrlSsh
    Export:
      Name: CiCdBlogRepositoryCloneUrlSsh
  CiCdBlogRepositoryName:
    Value: !GetAtt Repository.Name
    Export:
      Name: CiCdBlogRepositoryName

そこに対してPushするコードは、今回は.NET Core でLambda Templateを使用。

dotnet.microsoft.com

docs.aws.amazon.com

.NET Core をインストール後、LambdaのTemplateをインストールし、Projectを作成

dotnet new serverless.image.AspNetCoreWebAPI -n web

.NET のビルドをLocalでは行わないので、とりあえずコードのみ欲しい場合は下記のTemplateをCloudFormationで流してCodeCommitにコードを投入。コード作成後、不要になる為Stack毎消すことをお勧めします。

AWSTemplateFormatVersion: 2010-09-09
Description: AWS CI/CD - Repository Initialize

Parameters:
  ImageId:
    Type: AWS::EC2::Image::Id
    Default: ami-09b23e84684bb7149
    Description: ubuntu22.04
  InstanceType:
    Type: String
    Default: t4g.micro
  RepositoryName:
    Type: String
    Default: ci_cd_blog

Resources:
  Instance:
    Type: AWS::EC2::Instance
    Properties: 
      BlockDeviceMappings: 
        - DeviceName: /dev/sda1
          Ebs: 
            VolumeType: gp3
            DeleteOnTermination: true
            VolumeSize: 8
      CreditSpecification: 
        CPUCredits: standard
      ImageId: !Ref ImageId
      IamInstanceProfile: !Ref InstanceProfile
      InstanceType: !Ref InstanceType
      SecurityGroupIds: 
        - !Ref SecurityGroup
      UserData: 
        Fn::Base64:
          !Sub | 
            #!/bin/bash
            apt-get update
            apt-get -y upgrade
            apt-get install -y git unzip dotnet-sdk-6.0
            curl "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" -o "awscliv2.zip"
            unzip -q awscliv2.zip
            ./aws/install
            export HOME=/home/ubuntu
            dotnet new -i Amazon.Lambda.Templates
            mkdir $HOME/work && cd $HOME/work
            dotnet new serverless.image.AspNetCoreWebAPI -n web
            dotnet new gitignore
            git config --global user.name ubuntu
            git config --global user.email ubuntu@example.com
            git config --global credential.helper '!aws codecommit credential-helper $@'
            git config --global credential.UseHttpPath true
            git init -b main
            git add -A
            git commit -m "Newly Created"
            git remote add origin https://git-codecommit.${AWS::Region}.amazonaws.com/v1/repos/${RepositoryName}
            git push origin main
            shutdown -h now
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: ci_cd_blog_sg

  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles: 
        - !Ref RoleForInstanceProfile

  RoleForInstanceProfile:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement: 
          - Effect: Allow
            Principal: 
              Service: 
                - ec2.amazonaws.com
            Action: 
              - sts:AssumeRole

  PolicyForEc2:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          -  Effect: Allow
             Action:
                - codecommit:GitPull
                - codecommit:GitPush
             Resource: !Sub arn:${AWS::Partition}:codecommit:${AWS::Region}:${AWS::AccountId}:${RepositoryName}
      PolicyName: ci_cd_blog_iam_policy
      Roles: 
        - !Ref RoleForInstanceProfile

  # Schedule for Stop Ec2
  ScheduleGroup:
    Type: AWS::Scheduler::ScheduleGroup

  Schedule:
    Type: AWS::Scheduler::Schedule
    Properties:
      FlexibleTimeWindow: 
        Mode: 'OFF'
      GroupName: !Ref ScheduleGroup
      ScheduleExpression: cron(00 20 ? * * *)
      ScheduleExpressionTimezone: Japan
      State: ENABLED
      Target: 
        Arn: !Sub arn:${AWS::Partition}:scheduler:::aws-sdk:ec2:stopInstances
        Input:
          !Sub
          - | 
            {
              "InstanceIds": ["${InstanceId1}"]
            }
          - InstanceId1: !Ref Instance
        RoleArn: !GetAtt RoleForSchedule.Arn

  RoleForSchedule:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement: 
          - Effect: Allow
            Principal: 
              Service: 
                - scheduler.amazonaws.com
            Action: 
              - sts:AssumeRole

  PolicyForSchedule:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          -  Effect: Allow
             Action:
                - ec2:StopInstances
             Resource: !Sub arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/${Instance}
      PolicyName: ci_cd_blog_iam_policy
      Roles: 
        - !Ref RoleForSchedule

Code Commitにコードが投入されていれば下準備は完了。

AWS CodePipeline Step by Step with .NET Core - 概要

先日知り合いから、送られてきたリンク

AWS CodePipeline supports parameterized pipelines

AWS CodePipeline に新たなType v2が追加されたとのことで、試してみようかと思ったところ案の定CloudFormation Template やCDKが未対応。。。 なので時折Projectでお話が出てくるCodePipeline をおさらい。(その間にCFnやCDKが対応してくれるといい感じで連載できそう)

Pipeline Toolってたくさんあり、GitLab, Bamboo, Travis CI, Tekton, Jenkins, Github Actions, CircleCI等々。これらのToolに慣れてきた人たちにはちょっと使用法が異なるAWS CodePipeline(私が知る限り似たものはAzure Pipelines - Classic)大きく何が違うかといえば

枠組み作成の事前作成有無

ではないかと。

その前にPipelineの概要を説明すると、各製品毎に呼び名は様々また仕様が若干異なるが、Pipeline 自体は大きく分けて4つの要素から構成される。(今回はAzure Pipelineを元にした)

Pipeline

要素 説明 事前作成
Pipeline Frameであり、ここにはPipelineの実行タイミングや、使用する定数等を定義する。 毎日23時に起動等
Stage Frame。後述するJobを論理的に分割する役割し、Stage間の流れを定義。 Build StageとDeploy Stageの場合、Build Stageが成功した後、Deploy Stageを実行。もちろん1StageでBuildとDeployを包括することも可能。
Job これもFrame。後述するStepをまとめる役割を持つ。製品によってはこの単位で再実行が並列処理が可能だったりする。 複数ContaierをBuildする際、Build for C1, Build for C2, Build for C3 -
Step 実際の処理を定義。 Build Jobの中には、GitからのPull、PackageのRestore、Buildといった具合に処理を記述。 -

AWS CodePipeline や Azure Pipelines - Classic ではPipeline定義時に上記の事前作成が○の項目を用意しておく必要がある。後述する定義ファイル内への記述は不可。一方で他製品、Github Actionsではそれらの事前定義は不要であり、定義ファイルに全てを記述する事ができる。即ち、開発者目線で言えば、前者は一部のみ変更の余地があるが、後者は全て変更できるという事になる。(個人的には後者の方が好み。ただ状況によっては後者の方が適する場合もあるのでは?コンプライアンス的な。。。)

で、話をAWSに戻すと下記のように製品とのマッピングとなる。

要素 AWS
Pipeline Code Pipeline
Stage Code Pipeline
Job Code Pipeline & Code Build & Code Deploy
Step (Code Pipeline) & Code Build & Code Deploy

JobとStepについてはカオスが他のAWS Serviceとの連携は抜群である。正直最初にCodePipelineに触れた時、全く理解できなかった私(今よりも設定が少ない時に)。次回からはストーリーを作って最終的にLambdaあたりをDeployするものを作れたらと考えてます。

マネーボール

今年はお盆休みももう終了。猛暑&台風につき今回は在宅が多かった。。なんで在宅でのアクティビティが多い中、面白かったのが野球をよく知らない私でも楽しめたマネーボール

 

https://www.amazon.co.jp/gp/video/detail/B00KL02BWY/ref=atv_dp_share_cu_r

 

セイバーメトリクスという統計学を用いた戦略でメジャーリーグを勝ち抜いていくストーリー

点を取るために必要なのは、「ベースに出ること」まぁ当たり前なんでしょうけど。一方でスカウト人が探しているのはホームランの数(強力なプレイヤー?)


何が面白いか?

  • 見る目線を変えること
  • リーダーとして方向性を明確に示すこと

野球以外でも十分に通用する内容であるなぁと。ブラッドピット演じるビリーとコーチ陣がリプレイス探す際、最初誰も理解を示さないないという - まぁ新しい考えを持ち込むのっていつの時代も難しいですね。


一方でその考え方を受け入れてくれる人もいるという。特に最後のオファーのシーンで

Every time that happens whether it's a government, a way of doing business, whatever the people who are holding the reins they have their hands on the switch

を聞いた時、まさにそれです!と共感してしまいました。

youtu.be

 

さぁ明日からもがんばろっと!