GitLab CI/CDを使ったAWS Lambda関数のデプロイ
GitLabでは、AWS Lambda関数を簡単にデプロイし、リッチなサーバーレスアプリケーションを作成することができます。
GitLabでは、以下のServerlessフレームワークを利用したGitLab CI/CDによるAWS Lambda関数のデプロイをサポートしています:
サーバーレスフレームワーク
Serverless FrameworkはAWSにデプロイできます。
簡単な関数を作成し、AWS上にデプロイするステップバイステップの例を用意しました。
さらに、How Toのセクションでは、次のようなさまざまな使用例について読むことができます:
- ローカルで関数を実行
- シークレットを扱うこと。
- CORSの設定
また、テンプレートを使って新しいプロジェクトを素早く作成することもできます。Serverless Framework/JS
テンプレート には、以下に説明するすべてのパーツがすでに含まれています。
例
次の例では
- 基本的なAWS Lambda Node.js関数を作成します。
- API Gateway
GET
のエンドポイントに関数をリンクします。
ステップ
この例は以下のステップで構成されています:
- ラムダハンドラ関数の作成
-
serverless.yml
ファイルの作成。 -
.gitlab-ci.yml
ファイルの作成。 - GitLabアカウントでAWS認証情報を設定します。
- 機能をデプロイします。
- デプロイ機能のテスト。
一歩ずつ進んでいきましょう。
ラムダハンドラ関数の作成
Lambda関数はリクエストのプライマリハンドラーとなります。 今回は非常にシンプルなNode.jshello
関数を作成します:
'use strict';
module.exports.hello = async event => {
return {
statusCode: 200,
body: JSON.stringify(
{
message: 'Your function executed successfully!'
},
null,
2
),
};
};
このコードをファイルsrc/handler.js
に記述します。
src
はサーバーレス関数の標準的な場所ですが、カスタマイズすることも可能です。
この例では、module.exports.hello
がhello
ハンドラを定義しています。serverless.yml
AWS Lambda Node.js 関数ハンドラとその様々なオプションについては、こちらを参照してください:https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html
serverless.yml
ファイルの作成
プロジェクトのルートに、サーバーレスフレームワークの設定仕様を含むserverless.yml
ファイルを作成します。
次のコードをファイルに記述してください:
service: gitlab-example
provider:
name: aws
runtime: nodejs10.x
functions:
hello:
handler: src/handler.hello
events:
- http: GET hello
この関数にはハンドラとイベントが含まれています。
ハンドラ定義は、src/handler.hello
にあるソースコードを使ってラムダ関数をプロビジョニングします。
events
宣言は、AWS API GatewayGET
のエンドポイントを作成し、外部からのリクエストを受け取り、サービスインテグレーションを介して Lambda ファンクションに渡します。
サーバーレス・フレームワークの利用可能なプロパティと追加設定の可能性については、こちらをご覧ください。
.gitlab-ci.yml
ファイルの作成
プロジェクトのルートにある.gitlab-ci.yml
ファイルに、以下のコードを記述します:
image: node:latest
stages:
- deploy
production:
stage: deploy
before_script:
- npm config set prefix /usr/local
- npm install -g serverless
script:
- serverless deploy --stage production --verbose
environment: production
このコード例は次のようになります:
- すべての GitLab CI/CD ビルドに
node:latest
イメージを使用します。 -
deploy
ステージ:- Serverless Frameworkをインストールします。
- 上記で定義した AWS 認証情報を使用して、サーバーレス機能を AWS アカウントにデプロイします。
GitLabアカウントとAWS認証情報の設定
AWSアカウントとやり取りするために、GitLabのCI/CDパイプラインは、AWS_ACCESS_KEY_ID
とAWS_SECRET_ACCESS_KEY
の両方を設定 > CI/CD > 変数でGitLabの設定で定義する必要があります。 詳細については、UIでカスタム変数を作成するを参照してください。
機能のデプロイ
git push
を GitLab リポジトリに追加すると、GitLab ビルドパイプラインが自動的に関数をデプロイします。
GitLab のデプロイステージのログには、AWS Lambda のエンドポイント URL がコンテナで出力されます。 ログ行は以下のようになります:
endpoints:
GET - https://u768nzby1j.execute-api.us-east-1.amazonaws.com/production/hello
機能の手動テスト
以下のcurl
コマンドを実行すると、関数が起動します。
curl https://u768nzby1j.execute-api.us-east-1.amazonaws.com/production/hello
と出力されるはずです:
{
"message": "Your function executed successfully!"
}
これで GitLab CI/CD 経由で AWS Lambda 関数がデプロイされました。
よくやったわ!
ハウツー
このセクションでは、基本的な例を基に、どのように構築するかを紹介します:
- ローカルで関数を実行します。
- シークレット変数を設定します。
- CORSを設定します。
ローカルでの関数実行
serverless-offline
プラグインを使用すると、コードを内部で実行できます。 ローカルでコードを実行するには、次のようにします:
-
serverless.yml
に以下を追加してください:plugins: - serverless-offline
-
以下のコマンドを実行してサービスを開始します:
serverless offline
以下のcurl
コマンドを実行すると、関数が起動します。
curl http://localhost:3000/hello
と出力されるはずです:
{
"message": "Your function executed successfully!"
}
シークレット変数
シークレットは環境変数を使って関数に注入します。
serverless.yml
のproviderセクションで変数を定義することで、デプロイされた関数の環境に変数を追加します:
provider:
...
environment:
A_VARIABLE: ${env:A_VARIABLE}
設定 > CI/CD > 変数で、GitLab の CI/CD 変数にA_VARIABLE
を追加することを忘れないでください。
CORSの設定
テンプレートで行ったように、あなたの関数への呼び出しを行うウェブページを設定したい場合、クロスオリジン・リソース共有(CORS)に対処する必要があります。
手っ取り早い方法は、serverless.yml
の HTTP エンドポイントにcors: true
フラグを追加することです:
functions:
hello:
handler: src/handler.hello
events:
- http: # Rewrite this part to enable CORS
path: hello
method: get
cors: true # <-- CORS here
また、関数のレスポンスでCORS固有のヘッダーを返す必要があります:
'use strict';
module.exports.hello = async event => {
return {
statusCode: 200,
headers: {
// Uncomment the line below if you need access to cookies or authentication
// 'Access-Control-Allow-Credentials': true,
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify(
{
message: 'Your function executed successfully!'
},
null,
2
),
};
};
詳細については、Serverless Frameworkチームによるブログ記事「Your CORS and API Gateway survival guide」をご覧ください。
自動テストの作成
Serverless Framework のサンプルプロジェクトでは、Jest、Axios、serverless-offline
プラグインを使用して、ローカルとデプロイの両方のサーバーレス機能を自動テストする方法を示しています。
例とテンプレート
サンプルコードがあります:
GitLab UI 内からテンプレート(テストとシークレット変数を含むバージョンに基づく)を使うこともできます(Serverless Framework/JS
テンプレートを参照)。
AWSサーバーレスアプリケーションモデル
AWS Serverless Application Modelは、サーバーレスアプリケーションを構築するためのオープンソースのフレームワークです。 サーバーレスアプリケーションの構築とデプロイを容易にします。 詳細は、AWSServerless Application Modelに関するAWSのドキュメントをご覧ください。
AWS SAMとGitLab CI/CDを使ったAWS Lambda関数のデプロイ
GitLabは、開発者がサーバーレスアプリケーションを構築し、デプロイすることを可能にします:
- AWS Serverless Application Model (AWS SAM)。
- GitLab CI/CD。
例
次の例では
- SAM CLI をインストールします。
- Lambda 関数と API Gateway を含むサンプル SAM アプリケーションを作成します。
- GitLab CI/CDを使ってアプリケーションをビルドし、AWSアカウントにデプロイします。
ステップ
この例は以下のステップで構成されています:
- SAM CLI のインストール。
- SAM CLI を使用して AWS SAM アプリケーションを作成します。
-
.gitlab-ci.yml
ファイルの作成。 - GitLabアカウントでAWS認証情報を設定します。
- アプリケーションをデプロイします。
- デプロイ機能のテスト。
SAM CLI のインストール
AWS SAMは、アプリケーションの作成と管理を容易にするために、AWS SAM CLIというCLIを提供しています。
このドキュメントの一部の手順では、SAM CLI を使用します。SAM CLI のインストール手順に従って、SAM CLI をインストールおよび構成します。
AWS Cloud9をインテグレーション開発環境(IDE)として利用する場合、以下のものがインストールされます:
- AWSコマンドラインインタフェース
- SAM CLI
- Dockerと必要なDockerイメージ。
SAM CLI を使用した AWS SAM アプリケーションの作成
新しい AWS SAM アプリケーションを作成します:
- 新しいGitLabプロジェクトを作成します。
-
git clone
プロジェクトをローカル環境にインストールします。 -
新しくクローンしたプロジェクトに移動し、以下のコマンドを使用して新しい SAM アプリを作成します:
sam init -r python3.8 -n gitlabpoc --app-template "hello-world"
-
git push
アプリケーションを GitLab プロジェクトに戻します。
これは、デフォルトの構成、Amazon API Gatewayのエンドポイントから呼び出される単一のPython 3.8関数を使用して、gitlabpoc
という名前のSAMアプリを作成します。 SAMでサポートされるその他のランタイムと、sam init
のオプションを確認するには、 を実行します:
sam init -h
GitLabアカウントとAWS認証情報の設定
AWSアカウントとやり取りするために、GitLabのCI/CDパイプラインはAWS_ACCESS_KEY_ID
とAWS_SECRET_ACCESS_KEY
の両方をプロジェクトのCI/CD変数に設定する必要があります。
これを設定するには
- プロジェクトの{設定}設定 >CI /CDに移動します。
-
変数セクションを展開し、
AWS_ACCESS_KEY_ID
とAWS_SECRET_ACCESS_KEY
のエントリを作成します。 - Maskedトグルを使用して、ログに表示されないようにクレデンシャルをマスクします。
.gitlab-ci.yml
ファイルの作成
プロジェクトのルートにある.gitlab-ci.yml
ファイルに以下を追加し、<S3_bucket_name>
をパッケージを保存する S3 バケットの名前に置き換えてください:
image: python:latest
stages:
- deploy
production:
stage: deploy
before_script:
- pip3 install awscli --upgrade
- pip3 install aws-sam-cli --upgrade
script:
- sam build
- sam package --output-template-file packaged.yaml --s3-bucket <S3_bucket_name>
- sam deploy --template-file packaged.yaml --stack-name gitlabpoc --s3-bucket <S3_bucket_name> --capabilities CAPABILITY_IAM --region us-east-1
environment: production
設定ファイルを詳しく見てみましょう:
-
image
はこのビルドに使用するDockerイメージを指定します。 サンプルアプリケーションはPythonで書かれているので、これは最新のPythonイメージです。 - AWS CLI と AWS SAM CLI は、
before_script
セクションにインストールします。 - SAM build、package、deploy コマンドは、アプリケーションのビルド、パッケージ化、デプロイに使用します。
アプリケーションのデプロイ
GitLab リポジトリに変更をプッシュすると、GitLab のビルドパイプラインが自動的にアプリケーションをデプロイします。 もし変更があれば、GitLab のビルドパイプラインが自動的にアプリケーションをデプロイします:
- ビルドとデプロイが成功したら、デプロイしたアプリケーションをテストします。
-
ビルドに失敗したら、ビルド・ログを見て、なぜビルドに失敗したかを調べてください。 ビルドに失敗する可能性のある一般的な理由には、以下のようなものがあります:
- 例えば、Pythonのランタイムのバージョンが、ビルドマシンのPythonと異なる場合があります。 必要なバージョンのソフトウェアをインストールすることで、この問題に対処します。
- GitLabからAWSアカウントにアクセスできない可能性があります。 AWS認証情報で設定した環境変数を確認してください。
- サーバーレスアプリケーションをデプロイする権限がない可能性があります。 サーバーレスアプリケーションをデプロイするために必要なすべての権限が与えられていることを確認してください。
デプロイしたアプリケーションのテスト
デプロイしたアプリケーションをテストするには、ビルドログにアクセスし、以下の手順に従ってください:
-
右上の「Show complete raw」をクリック:
-
以下のような HelloWorldApi - API Gateway エンドポイントを探します:
-
curlを使ってAPIをテストしてください:
curl https://py4rg7qtlg.execute-api.us-east-1.amazonaws.com/Prod/hello/
出力はこうあるべきです:
{"message": "hello world"}
現地でのテスト
AWS SAMは、アプリケーションをローカルでテストする機能を提供します。 ローカルでテストするには、AWS SAM CLIがローカルにインストールされている必要があります。
まず、関数をテストします。
SAMは、events/event.json
、メッセージボディを含むデフォルトイベントを提供します:
{\"message\": \"hello world\"}
そのイベントをHelloWorldFunction
に渡すと、同じボディで応答するはずです。
関数を実行します:
sam local invoke HelloWorldFunction -e events/event.json
出力はこうあるべきです:
{"message": "hello world"}
Lambda関数が期待通りに動作することを確認したら、以下の手順でAPI Gatewayをテストします。
ローカルでAPIを起動します:
sam local start-api
SAMは再びDockerコンテナを起動し、今回はモックしたAmazon API Gatewayをlocalhost:3000
でリッスンします。
を実行してhello
API を呼び出します:
curl http://127.0.0.1:3000/hello
出力はまた
{"message": "hello world"}