AWS Lambdaのランタイムサポートポリシーについて、および、廃止が迫った場合の対処法

# TL;DR

知っているようで知らないAWS Lambdaのランタイムポリシー、そして、これまで使っていたランタイムが使えなくなったらどうしよう？

そんな疑問にお答えします。

# 背景

AWS Lambdaは2019/12/22現在、サポートランタイムが12個あり、それらは以下のとおり。これはマネージメントコンソールからいつでも確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6088/8db8c6fa-aa3d-e176-d939-662abd683464.png)

### re:Inventで新しいランタイムのサポートがアナウンスされました。

* AWS Lambda now supports Node.js 12
    * https://aws.amazon.com/about-aws/whats-new/2019/11/aws-lambda-supports-node-js-12/
* AWS Lambda now supports Java 11
    * https://aws.amazon.com/about-aws/whats-new/2019/11/aws-lambda-supports-java-11/
* AWS Lambda now supports Python 3.8
    * https://aws.amazon.com/about-aws/whats-new/2019/11/aws-lambda-now-supports-python-3-8/

新しいランタイムが増えるのは開発者としては嬉しいですよね。

でも、来る者あれば、去る者あり、、、

### こんなメールが来てたりします？

「AWS Lambda: Node.js 8.10 is EOL, please migrate your functions to a newer runtime version」というタイトルで開くと、、

```
Hello,

We are contacting you as we have identified that your AWS Account currently has one or more Lambda functions using Node.js 8.10, which will reach its EOL at the end of 2019.

> What’s happening?

The Node community has decided to end support for Node.js 8.x on December 31, 2019 [1]. From this date forward, Node.js 8.x will stop receiving bug fixes, security updates, and/or performance improvements. To ensure that your new and existing functions run on a supported and secure runtime, language runtimes that have reached their EOL are deprecated in AWS [2].

For Node.js 8.x, there will be 2 stages to the runtime deprecation process:

1. Disable Function Create – Beginning January 6, 2020, customers will no longer be able to create functions using Node.js 8.10
2. Disable Function Update – Beginning February 3, 2020, customers will no longer be able to update functions using Node.js 8.10
After this period, both function creation and updates will be disabled permanently. However, existing Node 8.x functions will still be available to process invocation events.

> What do I need to do?

We encourage you to update all of your Node.js 8.10 functions to the newer available runtime version, Node.js 10.x[3] or Node.js 12.x[4]. You should test your functions for compatibility with either the Node.js 10.x or Node.js 12.x language version before applying changes to your production functions.

> What if I have issues/What if I need help?

Please contact us through AWS Support [5] or the AWS Developer Forums [6] should you have any questions or concerns.

[1] https://github.com/nodejs/Release
[2] https://docs.aws.amazon.com/lambda/latest/dg/runtime-support-policy.html
[3] https://aws.amazon.com/about-aws/whats-new/2019/05/aws_lambda_adds_support_for_node_js_v10/
[4] https://aws.amazon.com/about-aws/whats-new/2019/11/aws-lambda-supports-node-js-12/
[5] https://aws.amazon.com/support
[6] https://forums.aws.amazon.com/forum.jspa?forumID=186

Sincerely,
Amazon Web Services
```


これって、端的に言うとランタイムの廃止予定の連絡なんですよね。
今回は、Node.js 8.xについてですが、他のランタイムもEOLのアナウンスが来ることでしょう。

これが来るとドキドキしますよね。

ちなみに、ランタイム自体のLTSを決めているのは、そのランタイムごとの運営管理母体があり、AWSではありません。ですので足の速いランタイムや長く使えるランタイムなどの個性がでます。

### 古いランタイムってどうなるの？

# ランタイムサポートポリシーを理解する

過去のメールを見逃してないか、公式サイトも見ておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6088/531a9938-0b19-01e1-5027-0c96c1ab5699.png)
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/runtime-support-policy.html

AWSの公式サイトにいくと、ランタイムの廃止スケージュールが書かれているのですが、よく見ると「End of Life」以外にいろいろな項目があるのがわかります。廃止 (作成) 、廃止 (更新)と書かれているのですよね。 

End of Lifeがアナウンスがアナウンスされると、この廃止 (作成) 、廃止 (更新)のスケジュールが重要になります。

* `廃止 (作成)`の意味は、End of Lifeアナウンス対象のランタイムのLambda関数が、この日以降`作成`できなくなるという意味です。作成済みであれば、更新は可能です。
* `廃止 (更新)`の意味は、作成済みであれば、この日まで更新は可能ですが、この日以降は`更新`もできなくなるという意味です。

ここまでは、おそらく直感的に理解できると思います。

さて、疑問なのは更新もできなくなった関数がいつまで`実行`できるかです。公式サイトの表にも記載がありません。
実行については数ヶ月間の期間をおいて、停止されますがそのスケジュールがこの表に明記されることはありません。逆に言えば廃止（更新）後もしばらくは実行できるということですね。

しばらく実行できるとは言っても、EOLアナウンスがされたLambda関数の管理者は、すみやかな対処をした方が良いでしょう。

# 対処法

プロダクト、サービスのワークロードに応じて様々な対処法が考えられると思います。ここに挙げている対処がすべてではありませんので、ご自身の管理されているワークロードに応じて決定してください。

1. ランタイムのversion upがstraight forwardな方法です。ただし、syntaxの修正や依存ライブラリの解決など個別対応が必要となる場合があります。
2. カスタムランタイムの使用もできます。これは現行ランタイムのversionを維持する方法ですが、この場合には、カスタム実装したランタイムはAWSサポート対象外になりますし、カスタムランタイムの構築もユーザー側で行う必要があります。
3. 比較的、小さなコードブロックの場合、別の言語へのポーティングも考えられます。例えば足の速いNodejsから比較的長期で使えるPythonへのコードポーティングなどもできるでしょう。顧客に利益にならない裏側の実装のことで時間やコストがかかるのは嬉しくないでしょうし、あくまでも運用上利用している小さな関数の場合という感じでしょうか。
4. 3rd Partyのランタイムで良いのであれば、 出来合いのカスタムランタイムをユーザーの責任で使用することもできます。

プロジェクトの人的、時間的リソースが割り当てられる場合、１の対処法を選ぶ場合が多いでしょう。しかし様々な理由から古いランタイムを維持することを選ばざるを得ないケースもあることでしょう。

ここからは、そういったケースのお話しになります。


# カスタムランタイムの実装

カスタムランタイムの実装によるサポート対象外となってしまったランタイムの維持ができます。
[カスタム AWS Lambda ランタイム](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/runtimes-custom.html)

ここに、書かれているようにカスタムランタイムをつかえば古いバージョンの実行も可能になります。
問題点としては、

* AWSのサポートが受けられないこと。つまり何かランタイムの挙動についてサポートを使いたいとしてもAWSサポートはの守備範囲外になってしまいます。
* カスタムランタイムにおけるセキュリティ的な脆弱性が発見された場合にも、ユーザー側でパッチを当てるなどの対処が必要になります。またランタイムを利用している全ての関数に対して行う必要が出て来ます。
* そもそもカスタムランタイムを実装するのにコストと時間をかけなければならない。

AWSサポートが使えないというのは、しょうがないとしても、少なくともカスタムランタイムを実装するのにかかるコストと時間をなんとか軽減できないでしょうか？

# Lambda Layers

そこで、本日ご紹介するのが[awesome-layers](https://github.com/mthenw/awesome-layers)です。

Layersの欄にNode.js v8があります。この3rd party Runtimeが使えるのであれば、これをワークアラウンドとして採用することもできます。もちろんユーザーの責任範囲でこの対処方法を選択してください。

### 2019/12/22時点で[awesome-layers](https://github.com/mthenw/awesome-layers)の内容

| Name | ARN / Link | Compatible Runtimes |
|------|------------|---------------------|
| C++ (official) | Link: [awslabs/aws-lambda-cpp](https://github.com/awslabs/aws-lambda-cpp) | `provided` |
| Rust (official) | Link: [awslabs/aws-lambda-rust-runtime](https://github.com/awslabs/aws-lambda-rust-runtime) | `provided` |
| Bash | ARN: `arn:aws:lambda:<region>:744348701589:layer:bash:<version>`<br>Link: [`gkrizek/bash-lambda-layer`](https://github.com/gkrizek/bash-lambda-layer) | `provided` |
| [Ballerina](https://ballerina.io/) | Link: [ballerina.io/deployment/aws-lambda](https://ballerina.io/deployment/aws-lambda/) | `provided` |
| [Crystal](https://crystal-lang.org/) | Link: [lambci/crambda](https://github.com/lambci/crambda) | `provided` |
| [Nim](https://nim-lang.org/) | Link: [lambci/awslambda.nim](https://github.com/lambci/awslambda.nim) | `provided` |
| Node.js v8 - N\|Solid | ARN: `arn:aws:lambda:<region>:800406105498:layer:nsolid-node-8:<version>`<br>Link: [accounts.nodesource.com/downloads/nsolid-lambda](https://accounts.nodesource.com/downloads/nsolid-lambda) | `provided` |
| Node.js v10 | ARN: `arn:aws:lambda:<region>:553035198032:layer:nodejs10:<version>`<br>Link: [`lambci/node-custom-lambda`](https://github.com/lambci/node-custom-lambda) | `provided` |
| Node.js v10 - N\|Solid | ARN: `arn:aws:lambda:<region>:800406105498:layer:nsolid-node-10:<version>`<br>Link: [accounts.nodesource.com/downloads/nsolid-lambda](https://accounts.nodesource.com/downloads/nsolid-lambda) | `provided` |
| Node.js v12 | ARN: `arn:aws:lambda:<region>:553035198032:layer:nodejs12:<version>`<br>Link: [`lambci/node-custom-lambda`](https://github.com/lambci/node-custom-lambda) | `provided` |
| Perl 5.3.0 | ARN: `arn:aws:lambda:<region>:445285296882:layer:perl-5-30-runtime:4`<br>Link:[`shogo82148/p5-aws-lambda`](https://github.com/shogo82148/p5-aws-lambda) - see links to other version and [Paws](https://metacpan.org/pod/Paws) builds in repo | `provided` |
| PHP 7.1 & 7.3 | ARN: `arn:aws:lambda:<region>:887080169480:layer:php71:3`<br>Link:[`stackery/php-lambda-layer`](https://github.com/stackery/php-lambda-layer) | `provided` |
| PHP 7.2 & 7.3<br>cli & fpm | ARN: [`arn:aws:lambda:<region>:209497400698:layer:php-73:<version>`](https://runtimes.bref.sh/)<br>Link:[`brefphp/bref`](https://github.com/brefphp/bref) | `provided` |
| Pypy 3.5 | ARN: `arn:aws:lambda:<region>:146318645305:layer:pypy35:<version>`<br>Link: [IOpipe Pypy Layer](https://github.com/iopipe/lambda-runtime-pypy3.5) | `pypy3.5` |
| Brainfuck | ARN: `arn:aws:lambda:<region>:444134189787:layer:brainfuck:1`<br>Built for fun, will not process events! | `provided` |
| LOLCODE | ARN: `arn:aws:lambda:<region>:444134189787:layer:lolcode:1`<br>Built for fun, will not process events! | `provided` |
| Java 11 | Link: [andthearchitect/aws-lambda-java-runtime](https://github.com/andthearchitect/aws-lambda-java-runtime) | `provided` |
| Haskell | ARN: `arn:aws:lambda:<YOUR REGION>:785355572843:layer:aws-haskell-runtime:2` <br>Link: [Getting Started with the Haskell AWS Lambda Runtime](https://medium.com/the-theam-journey/getting-started-with-the-haskell-aws-lambda-runtime-951b2322c7a3) | `provided` |


このように、かなり豊富なランタイムの種類が列挙されています。中には3rd Party企業のサポートを受けれるものもありますので、そういう場合は直接その企業にコンタクトを取って見るのも良いでしょう。

さらに、ついでに紹介しておくと、[awesome-layers](https://github.com/mthenw/awesome-layers)はランタイムだけでなく、PandocやparamikoといったUtilitiesや、DatadogやEpsagonといったMonitoringのLayersも列挙してくれています。

これら3rd Party Layersを使うことで、ランタイムの維持だけでなく、新しい価値を生み出すLayerを取り込むことでビジネスの速度を上げていただければと思います！