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 テンプレート には、以下に説明するすべてのパーツがすでに含まれています。

次の例では

  1. 基本的なAWS Lambda Node.js関数を作成します。
  2. API GatewayGET のエンドポイントに関数をリンクします。

ステップ

この例は以下のステップで構成されています:

  1. ラムダハンドラ関数の作成
  2. serverless.yml ファイルの作成。
  3. .gitlab-ci.yml ファイルの作成。
  4. GitLabアカウントでAWS認証情報を設定します。
  5. 機能をデプロイします。
  6. デプロイ機能のテスト。

一歩ずつ進んでいきましょう。

ラムダハンドラ関数の作成

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.hellohello ハンドラを定義しています。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

このコード例は次のようになります:

  1. すべての GitLab CI/CD ビルドにnode:latest イメージを使用します。
  2. deploy ステージ:
    • Serverless Frameworkをインストールします。
    • 上記で定義した AWS 認証情報を使用して、サーバーレス機能を AWS アカウントにデプロイします。

GitLabアカウントとAWS認証情報の設定

AWSアカウントとやり取りするために、GitLabのCI/CDパイプラインは、AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY の両方を設定 > CI/CD > 変数でGitLabの設定で定義する必要があります。 詳細については、UIでカスタム変数を作成するを参照してください。

注:提供する AWS 認証情報には、AWS Lambda、API Gateway、CloudFormation、および IAM リソースへの正しいアクセス制御を提供する IAM ポリシーが含まれている必要があります。

機能のデプロイ

git push を GitLab リポジトリに追加すると、GitLab ビルドパイプラインが自動的に関数をデプロイします。

GitLab のデプロイステージのログには、AWS Lambda のエンドポイント URL がコンテナで出力されます。 ログ行は以下のようになります:

endpoints:
  GET - https://u768nzby1j.execute-api.us-east-1.amazonaws.com/production/hello

機能の手動テスト

以下のcurl コマンドを実行すると、関数が起動します。

Note:URLはGitLabのデプロイステージのログから取得したものにしてください。
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 プラグインを使用すると、コードを内部で実行できます。 ローカルでコードを実行するには、次のようにします:

  1. serverless.ymlに以下を追加してください:

    plugins:
      - serverless-offline
    
  2. 以下のコマンドを実行してサービスを開始します:

    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 を追加することを忘れないでください。

注意:AWS環境にアクセスできる人であれば、ラムダ定義で永続化された変数の値を見ることができるかもしれません。

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は、開発者がサーバーレスアプリケーションを構築し、デプロイすることを可能にします:

次の例では

  • SAM CLI をインストールします。
  • Lambda 関数と API Gateway を含むサンプル SAM アプリケーションを作成します。
  • GitLab CI/CDを使ってアプリケーションをビルドし、AWSアカウントにデプロイします。

ステップ

この例は以下のステップで構成されています:

  1. SAM CLI のインストール。
  2. SAM CLI を使用して AWS SAM アプリケーションを作成します。
  3. .gitlab-ci.yml ファイルの作成。
  4. GitLabアカウントでAWS認証情報を設定します。
  5. アプリケーションをデプロイします。
  6. デプロイ機能のテスト。

SAM CLI のインストール

AWS SAMは、アプリケーションの作成と管理を容易にするために、AWS SAM CLIというCLIを提供しています。

このドキュメントの一部の手順では、SAM CLI を使用します。SAM CLI のインストール手順に従って、SAM CLI をインストールおよび構成します。

AWS Cloud9をインテグレーション開発環境(IDE)として利用する場合、以下のものがインストールされます:

SAM CLI を使用した AWS SAM アプリケーションの作成

新しい AWS SAM アプリケーションを作成します:

  1. 新しいGitLabプロジェクトを作成します。
  2. git clone プロジェクトをローカル環境にインストールします。
  3. 新しくクローンしたプロジェクトに移動し、以下のコマンドを使用して新しい SAM アプリを作成します:

    sam init -r python3.8 -n gitlabpoc --app-template "hello-world"
    
  4. 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_IDAWS_SECRET_ACCESS_KEYの両方をプロジェクトのCI/CD変数に設定する必要があります。

これを設定するには

  1. プロジェクトの{設定}設定 >CI /CDに移動します。
  2. 変数セクションを展開し、AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYのエントリを作成します。
  3. Maskedトグルを使用して、ログに表示されないようにクレデンシャルをマスクします。
注:提供する AWS 認証情報には、AWS Lambda、API Gateway、CloudFormation、および IAM リソースへの正しいアクセス制御を提供する IAM ポリシーが含まれている必要があります。

.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認証情報で設定した環境変数を確認してください。
    • サーバーレスアプリケーションをデプロイする権限がない可能性があります。 サーバーレスアプリケーションをデプロイするために必要なすべての権限が与えられていることを確認してください。

デプロイしたアプリケーションのテスト

デプロイしたアプリケーションをテストするには、ビルドログにアクセスし、以下の手順に従ってください:

  1. 右上の「Show complete raw」をクリック:

    sam-complete-raw

  2. 以下のような HelloWorldApi - API Gateway エンドポイントを探します:

    sam-api-endpoint

  3. 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"}