0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LambdaをCodePipelineでデプロイする

Last updated at Posted at 2024-09-24

はじめに

テリーの発売を記念して、記事を1つ公開します。
今回は、CodePipeline(CodeBuild/CodeDeploy)を使ってLambdaのデプロイを試みました。業務で使うのでその学習のためです。CodePipelineを使ったデプロイについては、ネット上であまり情報が見当たらず、デプロイにはCloudFormationを使用するのが主流かもしれません。

そこで、(しんどいので) あえてCloudFormationを使わずに、CodePipelineを活用したデプロイに挑戦します。本記事の目的は、CodePipelineを使用する手順を解説することであり、設定内容の妥当性については評価の対象外とします。

なお、Lambdaをデプロイするだけなら、CodeBuildだけで十分に対応可能ですが、CodeDeployを利用することで、より高度なデプロイプロセスを実現しようと試行錯誤しました。

追記)Qiitaで検索すると結構記事が見つかった。
https://qiita.com/search?q=Lambda%E3%82%92CodePipeline%E3%81%A7%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%99%E3%82%8B

まずはテリーの新動画が出たので見ましょう。9/24テリー発売です。

構成図

これに近い。

image.png

違い

  • 承認者はいない(がプルリクエストをするなら承認者の運用は可能)
  • Lambdaのエンドポイントは開発用と本番用で分けた(ここだけオリジナルで工夫した)

利用するリージョン

どこでもいいですが、ap-northeast-1とする。検証で軽く使う分にはどこを使っても差はコストに差は出ない。

AWS CLIインストール

用途

API Gatewayの権限設定で必要になるので、インストールしておく。

AWS CLIインストール方法(Windows)

本手順を読むときの注意事項

  • バケット名は一意となる名前が必要なので手順そのままは使えないと思います。バケット名、ロール名、パイプライン名等の名前の設定ではzangiefという文字を使っています。そのためこの部分を自分の好きな名前に変えれば困らないと思います。

IAMロールの作成

用途

  • CodeDeploy用のロールを作ります

作成手順

  1. 「ロールを作成」をクリックし、以下の設定内容でロールを作成します。

    画面名 項目 設定値
    信頼されたエンティティを選択 信頼されたエンティティタイプ - AWS のサービス
    ユースケース サービスまたはユースケース Lambda
    許可を追加 許可ポリシー AmazonS3FullAccess
    AWSCodeDeployRole
    AWSCodeDeployRoleForLambda
    許可の境界を設定 - オプション -
    名前、確認、および作成 ロールの詳細 ロール名 test-codedeploy-zangief-service-role
    説明 -
    信頼ポリシー - -
    許可ポリシーの概要 - -
    タグを追加 - オプション - -
  2. ポリシーを追加
    IAM→ロール→test-codedeploy-zangief-service-roleを検索→許可タブ→許可を追加→ポリシーをアタッチ→AmazonS3FullAccess

TODO

不要なポリシーもあるかも。精査せずとりあえずFullAccessを与えてるので、過剰だとは思う

S3バケットの作成

用途

  • CodeBuildでlambda.zipを保存。lambda.zipにはラムダ本体のプログラムファイル(lambda_function.py)が入ってます。ラムダのアップデートするときはzipにする必要があります。

作成手順

「バケットを作成」をクリックし、以下の設定内容でバケットを作成します。

バケットを作成 一般的な設定 バケットタイプ 汎用
バケット名 test-codepipeline-zangief
既存のバケットから設定をコピー - オプション -
オブジェクト所有者 - ACL 無効 (推奨)
このバケットのブロックパブリックアクセス設定 - 「パブリックアクセスをすべて ブロック」のチェックを入れる
バケットのバージョニング バケットのバージョニング 有効にする
※今回は必要ないのだが、S3にファイル設置を契機にパイプラインを動かすときに必要な設定なので、設定しておく
タグ - オプション (0) - -
デフォルトの暗号化 暗号化タイプ Amazon S3 マネージドキーを使用したサーバー側の暗号化 (SSE-S3)
バケットキー 有効にする
詳細設定 オブジェクトロック 無効にする

以下の解説が詳しいです

CodeCommit(リポジトリ)の作成

用途

  • デプロイに必要なコードを管理(保存)します。

作成手順

「リポジトリを作成」をクリックし、以下の設定内容でリポジトリを作成します。

画面名 項目 設定値
リポジトリを作成 リポジトリの設定 リポジトリ名 test-codepipeline-zangief
説明 - オプショナル -
タグ -
追加設定 -
- 「Amazon CodeGuru Reviewer for Java and Python を有効にする - オプショナル」のチェックを外す

以下のコードを登録する。今回は画面のUI上から登録する。

  • buildspec.yml

    buildspec.yml
    version: 0.2
    
    env:
      variables:
        LAMBDA_FUNCTION_NAME: "test-hello-world-zangief"  # Lambda関数名を変数として定義
    
    phases:
      install:
        commands:
          - aws --version
    
      build:
        commands:
          - echo Build started on `date`
          - zip -r lambda.zip lambda_function.py
          - aws lambda update-function-code --function-name $LAMBDA_FUNCTION_NAME --zip-file fileb://lambda.zip
          - sleep 10 # wait for update-function-code complete
          - aws lambda publish-version --function-name $LAMBDA_FUNCTION_NAME --description "update version"
          # 今回は扱わないが、prodを最新バージョンに切り替える場合は以下のようにすればOK
          # - NEW_VERSION=$(aws lambda publish-version --function-name $LAMBDA_FUNCTION_NAME --description "update version" --query 'Version' --output text)
          # - aws lambda update-alias --function-name $LAMBDA_FUNCTION_NAME --name prod --function-version $NEW_VERSION
    
    artifacts:
      files:
        - lambda.zip
        - appspec.yml
    
  • appspec.yml

    appspec.yml
    version: 0.0
    
    Resources:
      - MyLambdaFunction:
          Type: AWS::Lambda::Function
          Properties:
            Name: "test-hello-world-zangief"
            Alias: "prod"
            CurrentVersion: "1" # prod(エイリアス)が指すバージョン
            TargetVersion: "2" # 新しいバージョン、これに切り替えるということ
    
    # prodの指すバージョンが間違ってたりすると以下のエラーになるので注意
    # The deployment failed because the AppSpec file that specifies the AWS Lambda deployment configuration is missing or has an invalid configuration. 
    # The input AppSpec file is a not well-formed yaml. The template cannot be parsed.
    # CurrentVersion と TargetVersionが同じでもエラーにならない。デプロイを動かしたいだけなら同じにしておけばよい。
    
  • lambda_function.py

    lambda_function.py
    import json
    
    def lambda_handler(event, context):
        # TODO implement
        return {
            'statusCode': 200,
            'body': json.dumps('this is the dev environment.')
        }
    

Lambdaの作成

用途

  • ラムダを使いたいので使う。ラムダ本体の作りはメッセージを表示する程度のものです。

作成手順

  1. 「関数の作成」をクリックし、以下の設定内容で関数(lambda)を作成します。

    画面名 項目 設定値
    関数の作成 - - 一から作成
    基本的な情報 関数名 test-hello-world-zangief
    ランタイム Python 3.12
    アーキテクチャ x86_64
    アクセス権限 -
    デフォルトの実行ロールの変更 -
    詳細設定 - -
  2. コードを修正→保存(ctrl + s)→Deployをクリックする

    lambda_function.py
    import json
    
    def lambda_handler(event, context):
        # TODO implement
        return {
            'statusCode': 200,
            'body': json.dumps('this is the prod environment.')
        }
    
  3. 「バージョン」タブ→「新しいバージョンを発行」をクリックし、新しいバージョンを発行します。

    画面名 項目 設定値
    $LATEST から新しいバージョンを発行します。 バージョンの説明 - オプション -

    バージョン1が発行されます。

  4. コードを修正→保存(ctrl + s)→Deployをクリックする

    lambda_function.py
    import json
    
    def lambda_handler(event, context):
        # TODO implement
        return {
            'statusCode': 200,
            'body': json.dumps('this is the dev environment.')
        }
    
  5. 「バージョン」タブ→「新しいバージョンを発行」をクリックし、新しいバージョンを発行します。

    画面名 項目 設定値
    $LATEST から新しいバージョンを発行します。 バージョンの説明 - オプション -

    バージョン2が発行されます。

  6. 「エイリアス」タブ→「エイリアス作成」をクリックし、以下の設定内容でエイリアスを作成します。エイリアスは2つ作ります。$LATESTはバージョン2を指すことになります。(発行している最新バージョンを指す意味となります。バージョンが6つあれば、$LATESTは6を指します)

    画面名 項目 設定値
    エイリアスを作成 エイリアス設定 名前 dev
    説明 - オプション -
    バージョン $LATEST
    加重エイリアス -
    エイリアス設定 名前 prod
    説明 - オプション -
    バージョン 1
    加重エイリアス -

    こうなっていればOK
    image.png

動作確認

まだこの段階ではできません。API Gatewayの設定が必要です。

API Gatewayの作成

用途

  • 作ったラムダを実行するにはこれが必要。

作成手順

  1. 「APIを作成」をクリックし、以下の設定内容でAPI Gatewayを作成します。

    画面名 設定値 設定値
    API タイプを選択 - - REST API
    REST API を作成 API の詳細 - 新しい API
    API 名 test-hello-world-zangief-api
    説明 - オプション -
    API エンドポイントタイプ -
  2. 「リソース作成」をクリックし、以下の設定内容でリソースを作成します。

    画面名 項目 設定値
    リソースを作成 リソースの詳細 プロキシのリソース 無効(左に〇が寄っていればOK)
    リソースパス /
    リソース名 test
    - 「CORS (クロスオリジンリソース共有」のチェックを入れる

    「CORS (クロスオリジンリソース共有」は今回は使わないけど、今後の設定で使うのでつけておくよ。

  3. 「メソッドを作成」をクリックし、以下の設定内容でメソッドを作成します。

    画面名 項目 設定値
    メソッドを作成 メソッドの詳細 メソッドタイプ GET
    統合タイプ Lambda 関数
    Lambda プロキシ統合 無効(左に〇が寄っていればOK)
    Lambda 関数 arn:aws:lambda:ap-northeast-1:XXXXXXXXXXX:function:test-hello-world-zangief:${stageVariables.alias}
    統合のタイムアウト 29000
    メソッドリクエストの設定 - -
    URL クエリ文字列パラメータ - -
    HTTP リクエストヘッダー - -
    リクエスト本文 - -

    許可の追加コマンドサンプル。id等は個々で違うので画面に出てきたものを使ってね。${stageVariables.alias}はdevとprodに読み替えてね。ここはPowerShellからコマンド実行するよ。aliasの運用するとこの操作が必要なようだ。

    # PowerShell
    # dev用
    $ aws lambda add-permission `
    --function-name "arn:aws:lambda:ap-northeast-1:XXXXXXXXXX:function:test-hello-world-zangief:dev" `
    --source-arn "arn:aws:execute-api:ap-northeast-1:XXXXXXXXXX:ghl87hy91k/*/GET/test" `
    --principal apigateway.amazonaws.com `
    --statement-id 9f349d02-95e1-4ac1-a25e-dd9b99a2a8d6 `
    --action lambda:InvokeFunction
    
    # prod
    $ aws lambda add-permission `
    --function-name "arn:aws:lambda:ap-northeast-1:XXXXXXXXXX:function:test-hello-world-zangief:prod" `
    --source-arn "arn:aws:execute-api:ap-northeast-1:XXXXXXXXXX:ghl87hy91k/*/GET/test" `
    --principal apigateway.amazonaws.com `
    --statement-id 9f349d02-95e1-4ac1-a25e-dd9b99a2a8d6 `
    --action lambda:InvokeFunction
    
  4. 「APIをデプロイ」をクリックし、以下の設定内容でAPIをデプロイします。

    画面名 項目 設定値
    Deploy API ステージ 新しいステージ
    ステージ名 dev
    デプロイメントの説明 -
    Deploy API ステージ 新しいステージ
    ステージ名 prod
    デプロイメントの説明 -
  5. 左メニューの「ステージ」をクリックし、以下の設定内容でステージ変数を作成します。
    devを選択→ステージ変数タブをクリック

    画面名 項目 設定値
    ステージ変数を追加 名前 alias
    dev

    prodを選択→ステージ変数タブをクリック

    画面名 項目 設定値
    ステージ変数を追加 名前 alias
    prod

    こうなっていればOK。(prodも同様)
    image.png

動作確認

  1. ブラウザで以下にアクセスする。URLはAPI GATEWAYの画面に表示されてます
    https://XXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/test

  2. {"statusCode": 200, "body": "\"this is the dev environment.\""}が表示されればOK。これが開発環境用の動作確認となります。

  3. ブラウザで以下にアクセスする
    https://XXXXX.execute-api.ap-northeast-1.amazonaws.com/prod/test

  4. {"statusCode": 200, "body": "\"this is the prod environment.\""}が表示されればOK。これが本番環境用の動作確認となります。

CodeBuildの作成

※単体ではpush契機で動作しない

用途

  • ラムダ本体のアップデート
  • appspec.ymlをS3バケットにアップロード

作成手順

  1. 「プロジェクトを作成」をクリックし、以下の設定内容でプロジェクトを作成します。

    画面名 項目 設定値
    ビルドプロジェクトを作成する プロジェクトの設定 プロジェクト名 test-codebuild-zangief
    追加設定 -
    ソース ソースプロバイダ AWS CodeCommit
    リポジトリ test-codepipeline-zangief
    リファレンスタイプ ブランチ
    ブランチ main
    コミット ID - オプショナル -
    環境 環境イメージ マネージド型イメージ
    コンピューティング Lambda
    オペレーティングシステム Amazon Linux
    ランタイム Python
    イメージ 最新を選ぶ(今回はx86_64用を選んでね)
    イメージのバージョン -
    サービスロール 新しいサービスロール
    ロール名 codebuild-test-codebuild-zangief-service-role
    ※自動で入力されてます
    追加設定 -
    Buildspec ビルド仕様 buildspec ファイルを使用する
    ビルドコマンド -
    Buildspec 名 - オプショナル buildspec.yml
    バッチ設定 - -
    アーティファクト タイプ Amazon S3
    バケット名 test-codepipeline-zangief
    名前 deploy-artifacts
    セマンティックバージョニングの有効化 チェックを入れない
    パス - オプショナル -
    名前空間のタイプ - オプショナル なし
    アーティファクトのパッケージ化 なし
    アーティファクト暗号化の削除 チェックを入れない
    追加設定 -
    ログ CloudWatch Logs - オプショナル チェックを入れる
    グループ名 - オプショナル -
    ストリーム名のプレフィックス - オプショナル -
    S3 ログ - オプショナル チェックを入れない
  2. ロールにlambdaのポリシーをアタッチします。
    IAM→ロール→codebuild-test-codebuild-zangief-service-roleを検索→許可タブ→許可を追加→ポリシーをアタッチ→AWSLambda_FullAccessAWSLambda_FullAccess

  3. 「ビルドを開始」をクリックします
    ビルドが成功するはずです。

    ビルドをするたびにバージョンは増加します。
    image.png

memo

  • ロール:CodeBuildBasePolicy-test-codebuild-zangief-ap-northeast-1が自動生成される。CodeBuildを作り直す場合は、削除が必要。
  • ポリシー:codebuild-test-codebuild-zangief-service-roleが自動生成される。CodeBuildを作り直す場合は、削除が必要。

CodeDeployの作成

※単体ではpush契機で動作しない

用途

  • 本番環境のラムダを指定したバージョンにアップデートする。
  • appspec.ymlはS3にアップロードされたものを使っています。このアップロードはCodeBuildのArtifactの設定で行っています。CodeCommitからappspec.ymlを取得する機能はない(はず)。ここで結構はまりました。

作成手順

  1. 「アプリケーションの作成」をクリックし、以下の設定内容でアプリケーションを作成します。

    画面名 項目 設定値
    アプリケーションの作成 アプリケーションの設定 アプリケーション名 test-codedeploy-zangief
    コンピューティングプラットフォーム AWS Lambda
    タグ -
  2. 「デプロイグループの作成」をクリックし、以下の設定内容でデプロイグループを作成します。

    画面名 項目 設定値
    デプロイグループの作成 アプリケーション アプリケーション名 -
    コンピューティングタイプ
    -
    デプロイグループ名 デプロイグループ名の入力 test-codedeploy-zangief-group
    サービスロール サービスロールの入力 CodeDeployServiceRole
    デプロイ設定 デプロイ設定 CodeDeployDefault.LambdaAllAtOnce
    詳細 – オプション - -
  3. 「デプロイの作成」をクリックし、以下の設定内容でデプロイを作成します。

    画面名 項目 設定値
    Create deployment デプロイ設定 アプリケーション -
    デプロイグループ test-codedeploy-zangief-group
    コンピューティングプラットフォーム -
    デプロイタイプ -
    リビジョンタイプ アプリケーションは Amazon S3 に格納されています
    リビジョンの場所 s3://test-codepipeline-zangief/deploy-artifacts/appspec.yml
    リビジョンファイルの種類 .yaml
    デプロイの説明 デプロイの説明: オプション -
    デプロイグループのオーバーライド - -
    ロールバック設定の上書き - -
  4. デプロイが成功することを確認します。

    image.png

  5. ブラウザで以下にアクセスする
    https://XXXXX.execute-api.ap-northeast-1.amazonaws.com/prod/test

  6. {"statusCode": 200, "body": "\"this is the dev environment.\""}が表示されればOK。devと表示されますが、バージョン2のプログラムはdevとなっているので問題ありません。prodと表示されるのはバージョン1のみです。 prodと表示したければそのバージョンを用意して、そのバージョンに切り替えればOKです。

CodePipelineの作成

用途

  • CodeBuildとCodePipelineを連動させます。またCodeCommitにコードをpushすると動き出します

作成手順

  1. 「パイプラインを作成」をクリックし、以下の設定内容でパイプラインを作成します。

    画面名 項目
    パイプラインの設定を選択する パイプラインの設定 パイプライン名 test-codepipeline-zangief
    パイプラインタイプ キュー (パイプラインタイプ V2 が必須)
    サービスロール 新しいサービスロール
    ロール名 test-codepipline-zangief-service-role
    ※自動入力される名前を修正する
    AWS CodePipeline がサービスロールを作成できるようになるため、この新しいパイプラインでの使用が可能になります。 チェックを入れる
    変数 - -
    高度な設定 アーティファクトストア カスタムロケーション
    バケット test-codepipeline-zangief
    暗号化キー デフォルトの AWS マネージド型キー
    ソースステージを追加する ソース ソースプロバイダー AWS CodeCommit
    リポジトリ名 test-codepipeline-zangief
    ブランチ名 main
    検出オプションを変更する Amazon CloudWatch Events (推奨)
    出力アーティファクト形式 CodePipeline のデフォルト
    ビルドステージを追加する 構築する - オプショナル プロバイダーを構築する AWS CodeBuild
    リージョン アジアパシフィック(東京)
    入力アーティファクト SourceArtifact
    プロジェクト名 test-codebuild-zangief
    環境変数 - オプショナル -
    ビルドタイプ
    単一ビルド
    デプロイステージを追加する デプロイ - オプショナル デプロイプロバイダー AWS CodeDeploy
    リージョン アジアパシフィック(東京)
    入力アーティファクト BuildArtifact
    アプリケーション名 test-codedeploy-zangief
    デプロイグループ test-codedeploy-zangief-group
    ステージ障害時の自動ロールバックを設定 チェックを入れない
  2. デプロイが成功することを確認します。ですが、ここは失敗するはずです。appspec.ymlCurrentVersionTargetVersionを適切な値に修正して、再度実行しましょう。

    ※S3_triggerは次の「おまけ」を実施しないと表示されません
    image.png

    修正版appspec.yml
    version: 0.0
    
    Resources:
      - MyLambdaFunction:
          Type: AWS::Lambda::Function
          Properties:
            Name: "test-hello-world-zangief"
            Alias: "prod"
            CurrentVersion: "2" # prod(エイリアス)が指すバージョン
            TargetVersion: "3" # 新しいバージョン、これに切り替えるということ
    

おまけ(任意)

意味はないが、S3に何かデータを置いたら動作するようにもしたい。

以下の画像のようにS3_triggerというのを追加してみた。これでS3にtest.txtを設置または、CodeCommitのファイルを更新するとパイプラインが先頭から動き出す。通常の運用でSourceのアクショングループが2種類あることは少ないと思う
image.png

画面名 項目
アクション名 S3_trigger
アクションプロバイダー Amazon S3
バケット test-codepipeline-zangief
S3 オブジェクトキー test.txt
検出オプションを変更する - オプショナル Amazon CloudWatch Events (推奨)
変数の名前空間 - オプショナル -
出力アーティファクト S3_Artifact

トラブルシューティング

  • codedeployではappspec.ymlを使うのですが、prodのバージョン等のバージョンの設定を間違えるとビルドがこけます。エラーメッセージが分かりづらいです。

    # 例
    The deployment failed because the AppSpec file that specifies the AWS Lambda deployment configuration is missing or has an invalid configuration. The Lambda function alias version does not match the current version in AppSpec file.
    
  • appspec.ymlで、ラムダのデプロイの前後処理でシェルスクリプトは実行できません。実行できるのはラムダのみ。シェルスクリプトはEC2のデプロイのときにしかできないと思われる。マニュアルにはシェルスクリプトは実行できないとは書いてないが、ラムダは実行できるとちゃんと書いてあります。AI(ChatGpt)は実行できると思ってるので、かなりこれではまりました。

Lambdaバージョン管理の運用方法

  • dev(開発環境)prod(本番環境) ではラムダ本体のプログラム(lambda_function.py)は同じですが、エンドポイントは微妙に異なります。

  • dev(開発環境) では、lambda_function.pyを更新するたびに、CodePipeline(CodeBuild)を実行して変更を反映させます。これで日々の開発作業ができるはずです。

  • prod(本番環境) では、appspec.ymlで明示的に目的のLambdaのバージョンを指定し、CodePipeline(CodeDeploy)を実行するたびに反映されます。バージョンを変更しない限り、日々の開発で本番環境に影響が出ません。ただし、バージョン指定が誤っていたり、連続デプロイをするとエラーがおきます。業務ではプルリクエストを使用してコードをマージするため、必ず確認作業(承認作業)が入ります。そのため、勝手に本番環境が更新されることはありません。とはいえ、面倒ですがDeploy処理は本番反映するときのみ有効にした方がいいですね。イケてないので、この運用ではダメでしょう。(おそらくパイプラインを開発環境(CodeBuildのみ)と本番環境(CodeDeployのみ)で分割すれば問題は解消するでしょう)

    「移行を無効にする」をクリック
    image.png

さいごに

  • この手順を実施すれば、CodePipelineはおそらく動作すると思いますが、最初から最後まで一貫して通しで行ったわけではありません。

  • まだ書きたいことはありますが、少し疲れてきたので、ひとまずここまでとします。応用編も試してみましたが、執筆が大変なので途中で止めることにしました。

  • 手作業でこれだけの運用作業を正確に実施するのは無理だと思いましたので、業務では積極的にCloudFormationを使いましょう。

  • ラムダのバージョン管理、ラムダのところが初見では難しいと思います。ページ末尾に参考リンク集を用意したのでそちらをみて理解を深めましょう。

  • ネットの記事を見るとAWSのUIのレイアウトが今と違うものが多くて苦労しました。

  • AWSのマニュアルは、読みづらいと感じました。途中で読むのを諦めてしまいました。

  • AI(ChatGpt)を使ってみましたが、応答は遅いし、細かい部分の説明が不十分で、間違いも多かったです。金返せ

  • 今回の活動で結構AWSの知識が身についたと感じています。もう少し頑張って引退しようと思います。

応用編

CloudFrontの作成

用途

作成手順

動作確認

WAFの作成

用途

作成手順

動作確認

Route53の作成

用途

作成手順

動作確認

ACMの作成

用途

作成手順

動作確認

CloudForamationの作成

全部はしんどいので、ラムダ周りを

用途

作成手順

動作確認

Batchの作成

用途

作成手順

動作確認

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?