秘伝のServerlessFrameworkをアップデートする

# はじめに
こんにちは。本年度からSREになりました蔭山です。
今回はサービスローンチ時より使い続けているServerlessFrameworkを（作業当時の）1系最新バージョンだった1.83.0へバージョンアップ対応を行いました。
そこでどのようにアップデートを行ったのか、実際の取り組み内容を元にご紹介します。

# 当時の状況
私達のチームが運営しているサービスはAWSのLambdaをメイン基板としたシステムとなっています。サービスローンチ時より、アプリケーション側のリリース管理フレームワークとして[ServerlessFramework](https://www.serverless.com/)を利用してきました。
ServerlessFrameworkを導入してからバージョンは[1.36.2(2019/01/21リリース)](https://github.com/serverless/serverless/blob/master/CHANGELOG.md#1362-2019-01-21)　で固定し、サービスを成長させてきました。

## 発生した問題
このような状態でプロダクトを成長・運用してきていましたが、月日が経つと以下のような問題も発生してきました。

- クラウドベンダー（AWS）でのアップデートに追従できない
- ServerlessFrameworkの新機能に追従できない
- npmパッケージの脆弱性に対応できない

### クラウドベンダー（AWS）でのアップデートに追従できない
Lambdaのようなサーバーレスなサービスは近年注目されていることもあり、クラウドベンダーでのアップデートは頻繁に実施されています。そういったアップデートでの新機能は有効なものが多く、プロダクトに取り込みたいものが数多くありました。
ですがServerlessFramework側はバージョン固定しているため基本的には対応できておらず、採用を見送ることも多々ありました。

### ServerlessFrameworkの新機能に追従できない
もちろんですがServerlessFrameworkも日々バージョンアップが進められています。そういったアップデートでは記述の簡略化など開発体験の向上につながるものを多くあります。
そういった新機能はもちろん利用できないためServerlessFrameworkのテンプレート上にリソース定義を書く、独自のServerless Pluginsを作成しフックする、別のCloudFormationテンプレート上に起こすなどの冗長的な対応が発生していました。

### npmパッケージの脆弱性に対応できない
アプリケーションはPythonでできているためnode.js製のパッケージが本番環境に乗ることはありませんが、ServerlessFrameworkのバージョンを固定してることで依存しているパッケージの脆弱性に対応できていない状況でした。
アプリケーションのコードはGithubで管理しているため脆弱性が公表されるたびに[Dependabot](https://dependabot.com/)がアップデート対応のPRを生成してくれますが、対応を取り込むことによってServerlessFrameworkが動かなくなる懸念が拭えず取り込みを断念してきました。

このような問題を解決するために、今回ServerlessFrameworkおよび利用しているServerless Pluginsのバージョンアップ対応を推し進めることにしました。

# やったこと
上記の問題を解消するために、以下の対応を行いました。

- ServerlessFrameworkのバージョン検討
- ローカル環境・CI環境でのnode.jsのバージョンアップ
- package.json、package-lock.json更新
- 動作確認

## ServerlessFrameworkのバージョン検討
アップデートを検討した段階で、Serveless Frameworkは2系がすでにリリースされていました。そのため、1系のままで最新版にするか、メジャーバージョンまで上げるかの検討を行いました。
当時の結論としては2系へのメジャーバージョンアップは行わず、1系の最新バージョンまでアップデートすることとしました。
主な理由としては以下となります。

- 当時2系がリリースされたばかりで潜在の不具合がある可能性があった
- 1系の古いバージョンからのアップデートであるため2系への変更時のbreaking changeやその他の影響が読めない
- 2系へ上げることのメリットが上記の懸念に比べると大きくなかった

## ローカル環境・CI環境でのnode.jsのバージョンアップ
リリース時よりローカル環境・CI環境もnode.jsのバージョンを古いもの（8.11.1）で固定していた状態でしたので、まずはnode.jsのバージョンを14.10.0までアップデートを行いました。
ローカル環境は開発者の好みでさまざまなnode.jsのバージョン管理ツールを利用している状況だったため、アップデート方法に関しては開発者各自で行ってもらいました。
CI環境については独自にDocker Imageを準備していましたので、そちらのImageで対応を行いました。

## package.json、package-lock.json更新
package.jsonの更新は[npm-check-updates](https://www.npmjs.com/package/npm-check-updates)を利用し、ServerlessFrameworkのバージョンアップを実施しました。
lockファイルに関してはpackage.json更新後に `npm install` を行って更新を行いました。

## 動作確認
実際に開発環境にリリースし、以下の観点で動作確認を行いました。

- ServerlessFrameworkで生成されるCloudFormationスタックのリソースで消えたリソースはないか
- CloudFormationスタックで不審な変更はないか
- アプリケーションのパッケージング内容に差はないか
- 実際にアプリケーションを動かし、動作に問題ないか

# 問題
動作確認が無事完了し、実際に本番リリースすることができました。ですが、実際に本番へリリースしてみると以下の問題が発生してしまいました。

## 一時的にAWSリソースへの権限がなくなり、アクセスできなくなる
リリース直後に一時的に一部の処理でDynamoDBやS3、SQSといったAWSリソースへのアクセス権限がなくなり、エラーとなる事象が発生しました。
急遽切り戻して確認を行っていくと、LambdaのIAMロールのインラインポリシーの名前で命名規則が修正された改修があり、こちらが原因でAWS内部で一時的に権限が確認できなかったと仮説を立てました。
更に調査を進めて行くと発生率としては0.5%程度、発生期間は10分ほどであったため、リリース時のみの瞬断として対応を行うことなくリリースを続行しました。

# まとめ
以上、今回対応したServerlessFrameworkのバージョンアップ対応について紹介しました。
リリース時には問題はあったものの、その後は安定稼働を続けており冒頭で挙げた問題点も解消されています。

ですが、今回は1系の最新バージョンにバージョンアップする方針としたため、まだ最新版に追いつけていないのが現状となります。
こちらに関しても引き続き対応を進めていく所存です。

**それでは、快適なServerlessライフを！**