dehio3’s diary

仕事、生活、趣味のメモ

serverless CI/CDを試してみた

f:id:dehio3:20200207133158p:plain

はじめに

serverlessからCI/CDの一般提供がアナウンスされました!

自分は簡単なバッチ処理などをlambdaで動かしており、lamdbaの構成管理やリリースにserverlessを利用していたので、早速CI/CDから実行してみました!

serverless.com

デプロイ手順

1.サインアップ

ダッシュボード画面にアクセス

GitHubのアカウントでSIGN UP f:id:dehio3:20200206132721p:plain

GitHubOAuthでの認証を許可 f:id:dehio3:20200206132916p:plain

「next」をクリック f:id:dehio3:20200206133242p:plain

ユーザー名(デフォルトだとGitHubユーザー名)を設定し、「next」をクリック
f:id:dehio3:20200206133456p:plain

アプリケーション名(デフォルトだと「myapp」)を設定し、「done」をクリック
f:id:dehio3:20200206133835p:plain

CLIでのdeployのコマンドが表示されるが、「close」をクリック
f:id:dehio3:20200206134109p:plain

ダッシュボード画面が表示される f:id:dehio3:20200206134215p:plain

2.appの設定

デフォルトで作成された「myapp」を開いて、アプリケーションを設定します。

デプロイサービスからGitHubを選択、デプロイしたいリポジトリを選択して画面下の「save settings」をクリック
(とりあえず動作するのを確認したいので、詳細な設定はデフォルトのままにしてます) f:id:dehio3:20200207113347p:plain

3.profileの設定

AWS環境へ接続権限を付与する為、profileを設定します。

(appを作成する際に、設定するprofileを指定する為、環境やアプリケーション毎に専用のprofileを作成する方が良さそうです。)

メニューから「profiles」を選択し、「default」をクリック f:id:dehio3:20200207120716p:plain

AWSへアクセスする為のロールを設定する画面が表示されるので、「shared AWS account」をクリック

「Create a role wizard」のリンクをクリック

f:id:dehio3:20200207121116p:plain

AWSのIAMロールのコンソール画面に遷移するので、CI/CDからアクセスするロールを作成

(デフォルトだとポリシーがAdministratorAccessになるので、作成するリソースに合わせて権限を変える方が安全) f:id:dehio3:20200207121722p:plain

作成したIAMロールのarnを入力し、「save」をクリック f:id:dehio3:20200207122226p:plain

4.デプロイ

とりあえず動くのを確認したいので、masterに対してテストのコミットを上げてみます。

デプロイが進行する画面が表示 f:id:dehio3:20200207114540p:plain

上部のメニューから「deployments」すると、デプロイ履歴の一覧が画面が表示されるので、対象のデプロイを選択 f:id:dehio3:20200207114855p:plain

デプロイのレポートやログを確認できる詳細画面が表示 f:id:dehio3:20200207115344p:plain

修正箇所

元々は以下の手順で手動でデプロイしていたのですが、そのままで失敗する為、いくつか修正を行いました。

# pluginをインストール
sls plugin install -n serverless-python-requirements
sls plugin install -n serverless-plugin-aws-alerts
sls plugin install -n serverless-pseudo-parameters
# デプロイ
sls deploy --verbose --stage dev --alexaskill <alexaSkill Id>

package.jsonリポジトリにあげる

Build step: serverless deploy
 
  Serverless Error ---------------------------------------
 
  Serverless plugin "serverless-python-requirements" not found. Make sure it's installed and listed in the "plugins" section of your serverless config file.

CI/CDではbuild Stepにてnpm installでインストールする為、package.jsonリポジトリに追加が必要です。

requirements.txtを作成する

Error --------------------------------------------------
 
  Error: pipenv not found! Install it with 'pip install pipenv'.
      at ServerlessPythonRequirements.pipfileToRequirements (/alexa-skill-seibu-bus/node_modules/serverless-python-requirements/lib/pipenv.js:28:13)
      at ServerlessPythonRequirements.tryCatcher (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/util.js:16:23)
      at Promise._settlePromiseFromHandler (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/promise.js:547:31)
      at Promise._settlePromise (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/promise.js:604:18)
      at Promise._settlePromiseCtx (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/promise.js:641:10)
      at _drainQueueStep (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/async.js:97:12)
      at _drainQueue (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/async.js:86:9)
      at Async._drainQueues (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/async.js:102:5)
      at Immediate.Async.drainQueues [as _onImmediate] (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/async.js:15:14)
      at runCallback (timers.js:705:18)
      at tryOnImmediate (timers.js:676:5)
      at processImmediate (timers.js:658:5)
      at process.topLevelDomainCallback (domain.js:121:23)
 
     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.

Pipfileでパッケージを管理していたのですが、pipenvがインストールされていないようなのでrequirements.txtを作成して、リポジトリに上げておきます。

pipenv run pip freeze > requirements.txt

serverless-python-requirementsがPipfileも存在していると、そちらを優先してpkgを取得するようなので、 usePipenv: falseのオプションを追加し、Pipfileを利用しないように設定します。

custom:
  defaultStage: dev
  pythonRequirements:
  #   dockerizePip: non-linux
      usePipenv: false

python3.6→3.7に変更

Error --------------------------------------------------
 
  Error: python3.6 not found! Try the pythonBin option.
      at pipAcceptsSystem (/alexa-skill-seibu-bus/node_modules/serverless-python-requirements/lib/pip.js:100:13)
      at installRequirements (/alexa-skill-seibu-bus/node_modules/serverless-python-requirements/lib/pip.js:168:9)
      at installRequirementsIfNeeded (/alexa-skill-seibu-bus/node_modules/serverless-python-requirements/lib/pip.js:551:3)
      at ServerlessPythonRequirements.installAllRequirements (/alexa-skill-seibu-bus/node_modules/serverless-python-requirements/lib/pip.js:630:29)
      at ServerlessPythonRequirements.tryCatcher (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/util.js:16:23)
      at Promise._settlePromiseFromHandler (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/promise.js:547:31)
      at Promise._settlePromise (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/promise.js:604:18)
      at Promise._settlePromise0 (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/promise.js:649:10)
      at Promise._settlePromises (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/promise.js:729:18)
      at _drainQueueStep (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/async.js:93:12)
      at _drainQueue (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/async.js:86:9)
      at Async._drainQueues (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/async.js:102:5)
      at Immediate.Async.drainQueues [as _onImmediate] (/alexa-skill-seibu-bus/node_modules/bluebird/js/release/async.js:15:14)
      at runCallback (timers.js:705:18)
      at tryOnImmediate (timers.js:676:5)
      at processImmediate (timers.js:658:5)
      at process.topLevelDomainCallback (domain.js:121:23)
 
     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.

python3.6がないので、runtimeをpython3.7に変更します。

provider:
  name: aws
  runtime: python3.7

オプションの渡し方を変更

  Error --------------------------------------------------
 
  Error: subscription 'type' is required
      at _class.setSubscription (/alexa-skill-seibu-bus/node_modules/@serverless/platform-sdk/src/deployments/index.js:129:13)
      at /alexa-skill-seibu-bus/node_modules/@serverless/lib/deployment/parse.js:267:20
      at Generator.next (<anonymous>)
      at asyncGeneratorStep (/alexa-skill-seibu-bus/node_modules/@serverless/enterprise-plugin/lib/deployment/parse.js:21:103)
      at _next (/alexa-skill-seibu-bus/node_modules/@serverless/enterprise-plugin/lib/deployment/parse.js:23:194)
 
     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.

デプロイ時に --alexaskillオプションで、環境差異の値を渡していたのですが、profileにて変数として設定し、変数から値を取得するように変更します。

    events:
      # - alexaSkill: ${opt:alexaskill}
      - alexaSkill: ${param:alexaSkillId}

profileの「parameters」を選択し、変数を追加後「Save」をクリック

f:id:dehio3:20200207130340p:plain

おわり

とりあえずserverless CI/CDを利用して、デプロイできるのを確認しました。

ブランチによるステージと本番のリリース分けなど、実際の運用には細かな設定が足りてませんが、簡単にローカルでのデプロイから変更することが出来ました!

CircleCIやGithub Actionsなどの汎用的に使えるCI/CDツールから、terraform CloudやserverlessCI/CDなどツールに特化したCI/CDツールも出てきて、選択肢の幅が広がりますね!

フリープランだとデプロイの同時実行数などに制限がある事も多いので、デプロイ処理自体が違う場合は、CI/CDツールを自体を分ける事で並行でデプロイできるので、個人の開発や予算がない組織では利用するのは良さそうです!