ウェブサイト検索

Gitから安全なLambdaデプロイメントを自動化する方法


Lambdaには、あなたが過去に関数を書くために使ったことがあるであろうウェブベースのテキストエディタがあります。これはプラットフォームを学ぶ初心者には素晴らしいですが、更新の管理に最適な方法ではありません。ここでは、あなたのLambda関数をGitで追跡する方法を紹介します。

LambdaのためのCI/CDの仕組み

手動エディタを使用する代わりに、ローカルで関数を開発し、Gitリポジトリに変更をコミットしてプッシュし、CodePipelineにビルドとデプロイを処理させるべきです。

CodePipelineは、ソース管理で変更を検出するたびに自動的に実行され、変更をCodeBuild(またはJenkins)に送信してビルドを行います。このステップはオプションで、Lambdaでは使用しないかもしれませんが、TypeScriptのようなものを使用している場合は、このステージが必要です。ビルド後、変更はCodeDeployにプッシュされ、デプロイメントを処理します。

CodeDeployは自動的にLambda関数を更新し、新しいバージョンをプッシュします。デプロイメントプロセスを円滑にするために、エイリアスを使用してトラフィックを徐々にシフトさせ、最終的に100%のトラフィックが新しい関数に向けられるようにします。

実際のデプロイメントを扱うために、CodeDeployはAWSのサーバーレスアプリケーションモデル(SAM)を使用します。SAMは、インフラストラクチャをコードとして管理するサービスであるCloudFormationの拡張です。基本的には、人間が読みやすいデータシリアライズ言語(YAML)テンプレートであり、Lambda関数やその前提条件に関連するすべての設定を扱うために使用され、コードのみを使用してデプロイできるための重要な部分です。

ソース管理の設定

このステップは非常に簡単です。すべてのコードを格納する新しいプロジェクトディレクトリを作成し、Gitで初期化する必要があります。このディレクトリのルートには、SAMテンプレートが配置されます。

template.yml

各機能はそれぞれのフォルダーに入れられ、ルートはそれぞれのindex.jsになります。これにより、すべてが明確に分かれ、管理が容易になります。

ProjectDirectory

|--template.yml

|--Function

| |--index.js

|--AnotherFunction

|--index.js

CodePipelineは、ソース管理のためにGithubとBitBucketをサポートしています。これらのいずれかを使用している場合、デプロイメント用の新しいブランチを作成するだけで済みます(または、問題ない場合はmasterをそのまま使用してください)。別のサービスを使用している場合は、AWSの独自のCodeCommitをセカンダリリポジトリとして使用し、更新を行いたいときに変更をプッシュすることをお勧めします。

SAMテンプレートを書く

このステップは最も複雑で、あなたの機能とその要件に最も特化したものになります。あなたは、Lambda関数とそのすべての必要なリソースを設定するSAMテンプレートを作成する必要があります。

基本的なテンプレートは、次のようになります:

AWSTemplateFormatVersion: '2010-09-09'

Transform: AWS::Serverless-2016-10-31

Description: An AWS Serverless Specification template describing your function

Resources:

HelloWorld:

Type: AWS::Serverless::Function

Properties:

Handler: HelloWorld/index.handler

Runtime: nodejs8.10

これは、NodeJSで実行され、ハンドラーがHelloWorld/index.jsにある1つのリソース、Lambda関数を登録します。

SAM テンプレートから他のリソースもデプロイできます。たとえば、API Gateway に関数を呼び出す権限を与え、特定の API パスで関数を実行するように設定するには、次のように追加します:

AWSTemplateFormatVersion: '2010-09-09'

Transform: AWS::Serverless-2016-10-31

Description: An AWS Serverless Specification template describing your function

Resources:

HelloWorld:

Type: AWS::Serverless::Function

Properties:

Handler: HelloWorld/index.handler

Runtime: nodejs8.10

Events:

HelloWorldApi:

Type: Api

Properties:

Path: /helloworld

Method: GET

HelloWorldPermission:

Type: AWS::Lambda::Permission

Properties:

Action: lambda:InvokeFunction

FunctionName:

Fn::GetAtt:

- HelloWorld

- Arn

Principal: apigateway.amazonaws.com

SourceArn:

Fn::Sub: arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*/*/*/*

ここに挙げられるもの以上の具体的な使用方法が必要になるでしょうので、SAMに関する詳細情報については、私たちのガイドやAWSの開発者ガイド、GitHubの完全なスキーマをお読みください。

動作するテンプレートができたら、SAM CLIをインストールしてデプロイをテストできます。

pip install aws-sam-cli

次に、プロジェクトをパッケージ化し、アーティファクトをS3バケットに保存します:

sam package 

--template-file template.yml

--output-template-file package.yml

--s3-bucket bucket-name

そして、あなたは手動でデプロイメントを実行します:

sam deploy 

--template-file package.yml

--stack-name sam-hello-world

--capabilities CAPABILITY_IAM

すべてが正常に機能した場合、新しいCloudFormationスタックと、あなたの関数を含むLambdaのアプリケーションが表示されるはずです。

CodePipelineを使用したプロジェクトのパッケージングとデプロイ

このステージはオプションではありません。コンパイルされた言語を使用していない場合でも同様です。SAMテンプレートを使用して、ここでCodeBuildがプロジェクトをCodeDeployで非常に簡単にデプロイできる形にパッケージ化する処理を担当します。オプションとして、パッケージ化の前にnpm run buildやnpm installなどの他のコマンドを実行することができます。

まず、CloudFormationの更新を処理できる実行ロールが必要です。IAM管理コンソールを開いて新しいロールを追加します。このロールを使用するリソースとして「CloudFormation」を選択し、その後「AWSLambdaExecute」権限ポリシーを添付します。

ロールを保存し、それを開いて、以下のインラインポリシーを添付してください。

{

"Statement": [

{

"Action": [

"apigateway:*",

"codedeploy:*",

"lambda:*",

"cloudformation:CreateChangeSet",

"iam:GetRole",

"iam:CreateRole",

"iam:DeleteRole",

"iam:PutRolePolicy",

"iam:AttachRolePolicy",

"iam:DeleteRolePolicy",

"iam:DetachRolePolicy",

"iam:PassRole",

"s3:GetObject",

"s3:GetObjectVersion",

"s3:GetBucketVersioning"

],

"Resource": "*",

"Effect": "Allow"

}

],

"Version": "2012-10-17"

}

CodePipeline コンソールから新しいパイプラインを作成します。新しいサービスロールを作成するデフォルト設定を選択します。これにより、自動的に設定されます。

ソース管理ステージでは、ソース管理タイプ、リポジトリ、およびリリースブランチを選択してください。

ビルドステージでは、CodeBuildに新しいプロジェクトを作成する必要があります。デフォルトの構成で問題ありませんので、ビルドオペレーティングシステムとしてAmazon Linux 2を選択し、標準ランタイムと標準イメージを選択してください。

CodePipelineに必要な主なものは、プロジェクトディレクトリのルートに配置されたbuildspec.ymlファイルです。これにより、CodeBuildが実行するために必要なコマンドが設定されます。以下の設定は、TypeScriptをインストールし、すべてのNPMパッケージをインストールし、npm run buildを実行し、その後CloudFormation用にすべてをパッケージ化する例です。

version: 0.2

phases:

install:

runtime-versions:

nodejs: 10

commands:

- npm install -g typescript

build:

commands:

- echo Build started on `date`

- npm install time

- npm run build

- export BUCKET=typescript-lambda

- aws cloudformation package --template-file template.yml --s3-bucket $BUCKET --output-template-file outputtemplate.yml

artifacts:

type: zip

files:

- template.yml

- outputtemplate.yml

おそらく、これをあなたのプロジェクトに合わせて修正する必要があります。

それが完了したら、最終段階を設定できます。ただし、CodeDeployを使用するのではなく、CloudFormationを使用して直接更新します。すべてのパッケージングはビルドフェーズで行われたためです。「CloudFormation」をデプロイプロバイダーとして選択し、アクションモードを「変更セットを作成または置き換える」に設定します。新しい名前を入力し、変更セット名を変更してください。

テンプレートでは「BuildArtifact」を選択し、前のステップからoutputtemplate.ymlを入力します。「Capability IAM」を能力に追加し、以前に手動で作成したサービスロールを選択します。

「作成」をクリックすると、パイプラインがエラーなく実行されるはずです。しかし、CloudFormationステージでは変更セットが作成され、これは変更のプレビューのようなものです。実際に変更をデプロイするには、変更セットを実行する必要があります。

作成したパイプラインの「編集」をクリックします。「デプロイ」セクションで「編集」をクリックし、作成済みのアクションの後に「アクショングループを追加」をクリックします。この新しいアクションをこのアクションの前に作成すると、機能しません。

プロバイダーとして「CloudFormation」を選択します。「BuildArtifact」を入力アーティファクトとして選択します。アクションモードと変更セット名には、最初のデプロイメントアクションで作成したのと同じ値を入力します。

「保存」をクリックすると、パイプラインのメイン画面に戻ります。「変更をリリース」をクリックして、パイプラインを手動で再実行してください。これで完了し、変更がLambdaコンソールに表示されるはずです。

エラーが発生している場合、それを追跡するのは比較的簡単です。CodePipelineのエラーメッセージの横にある「詳細を見る」をクリックすることができます。エラーの原因は、ビルドの失敗、不完全なSAMテンプレート、またはCodeBuildやCloudFormationの権限が不十分である可能性が高いです。

ソースコントロールに変更をコミットすると、CodePipeline によって検出され、この全プロセスが再び始まるはずです。

関連記事: