【aws】CodeCommitにpushするだけでlambda関数をデプロイするパイプラインを作る【CodePipeline】

CodeCommitにPushするだけでLambdaをデプロイできるCodePipeLineを作る

①ユーザーがCodeCommitのリポジトリにpushした時CodePipeLineが検知する
②CodePipelineでCodeBuildを動かす
③CodeBuild(buildspec.yaml)packageコマンドで資源をS3に配置
④③で作成したpackaged.yamlでスタック作成
⑤CloudFormationがS3に配置された関数を読み取る形でlambdaを作成

AWSコンソール側で構築

S3の作成

これで作成完了です。バケット名はcodespec.yamlで使用します。

CodeCommit

単純にCodeCommitでリポジトリを作成してgit cloneします。
git clone時に出てくる認証はIAM->ユーザー->[ユーザー名]->認証情報から
AWS CodeCommit の HTTPS Git 認証情報を使います。

cloneしたリポジトリで最初のコミットを行いましょう。ブランチがないとパイプラインを設定出来ないのでreadmeファイルあたりをコミット&プッシュします。

CodePipeline

CodePipelineからパイプラインの作成

サービスロールに関してはパイプラインは全てこのcode-pipeline-2021を使いたいのでロールを事前に作成しておくのが良いです。
(ベストプラクティスは最小権限なので本来であれば必要な権限のみを付与してください)
高度な設定でカスタムロケーションにしなくても良いですが、パイプラインでの生成物が自動的に作られるバケットに生成されるため設定しておくと吉です。

ソースプロバイダでCodeCommitをを設定
先程作ったリポジトリとブランチ名(ここはpushされた時検知するブランチ)を選択します。

Codebuild

ここはCodebuildの設定です。プロジェクトがないのでプロジェクトを作成します。

ロールARNは先程のcode-pipeline-2021を選択しています。

パイプライン実行時aws –versionのコマンドが実行出来ないエラー(cannot execute binary file)が出た場合はここのイメージを見直してください。64bitのマシンイメージで実行しましょう。(buildspecのコードにて、awsコマンドのインストールを64bitで行っています。)

CloudWatchの設定は何も入れないとプロジェクト名でログが吐かれます。
ここでCodePipelineに進むことが出来なかったらIAMからサービスロールを探して信頼関係にcodebuild.amazonaws.comを付与しましょう。

CodePipelineに戻ったら次へ。デプロイでcloudformationの設定も行いたいのですが、一旦lambdaを作成するまでをCodeBuildで行ってしまうので、導入段階をスキップします。CodePipelineでcloudformationを作る方法は別記事で・・・。
(AssumeRoleうんたら~のエラーが出た場合は信頼関係にcodepipeline.amazonaws.comを追加してください)

これでパイプラインが作成出来ました。

buildは何もyamlファイルが無いので失敗します。

ローカル側で構築

lambdaの関数作成

なんでも良いのですがこのようなディレクトリ構造にしています。

export function handler(event: any, context: any, callback: any): void {
  console.log("pipeline test");
}

各種ファイル作成

buildspec.yamlとtemplate.yamlを作成します。

version: 0.2

phases:
  install:
    commands:
      - npm install -g typescript
  build:
    commands:
      - curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
      - unzip awscliv2.zip
      - ls -l /root/.pyenv/shims/aws
      - ./aws/install --bin-dir /root/.pyenv/shims --install-dir /usr/local/aws-cli --update
      - tsc src/functions/test/index.ts
  post_build:
    commands:
      - aws --version
      - aws cloudformation package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket test-pipeline-repository
      - aws cloudformation deploy --template-file packaged.yaml --stack-name testFunction --capabilities CAPABILITY_IAM
artifacts:
  files:
    - packaged.yaml

・install commandでtscコマンドを使う準備をしています。(javascriptであれば不要です)
–capabilities CAPABILITY_IAMに関してはエラーを調べてみたらこれ入れろって書かれていたので入れています。

  - curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
  - unzip awscliv2.zip
  - ls -l /root/.pyenv/shims/aws
  - ./aws/install --bin-dir /root/.pyenv/shims --install-dir /usr/local/aws-cli --update

aws cliのversionを2にするコードです。

post_build:
    commands:
      - aws --version
      - aws cloudformation package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket test-pipeline-repository
      - aws cloudformation deploy --template-file packaged.yaml --stack-name testFunction --capabilities CAPABILITY_IAM
artifacts:
  files:
    - packaged.yaml

・packageしてdeployしています。packageコマンドでソース及びtemplate.yamlを含むファイルをzip化し、deployで今作成したpackaged.yamlを使いcloudformationのスタックを作成しています。

誤解を恐れずに言うと、
※packageコマンドはtemplate.yamlのCodeUriを見て「どれが今回デプロイしたいものか?」を判断しています。template.yamlにCodeUriがない場合は現在位置から下の階層全てパッケージ化し、コマンドラインで設定したS3バケットに配置しています。

※また、packageコマンドでoutputされるファイル「packaged.yaml」はtemplate.yamlを踏襲しつつ、パッケージ化したデータの配置場所をCodeUriに上書きする形で作られています。
(パッケージコマンド後- cat packaged.yamlすると見れる。)


詳しくはcloudfrontのコマンドリファレンスへ・・

・lambdaの中身が変わったことを認識してくれる(deployだけだとlambda.zipを指定するためコードの差分を見てくれず、スタックが作成されない)

AWSTemplateFormatVersion: "2010-09-09"
Transform: "AWS::Serverless-2016-10-31"
Resources:
  TestFunction:
    Type: "AWS::Serverless::Function"
    Properties:
      FunctionName: testFunction
      Handler: index.handler
      Runtime: nodejs14.x
      CodeUri: src/functions/test

CodeUriはindex.jsがsrc/functions/test/に配置されるなら
/src/functions/testと記述します。(tsの場合jsコンパイル後の場所を選ばなければ同じ位置に配置されます。)

上手く行かない場合はIAMの信頼関係に

"Service": "lambda.amazonaws.com"

を追加してください。(
https://stackoverflow.com/questions/36419442/the-role-defined-for-the-function-cannot-be-assumed-by-lambda

実際にcodecommitにpushしてみる

pipelineが自動で動きます。

無事スタックが作成されました。

無事lambdaも作成されました。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です