テクマトリックス株式会社の会田です。
テクマトリックスでは、TestRailクラウドサービスやRedmineクラウドサービスを提供しており、AWSを利用しています。
クラウドサービスを担当するインフラチームでは、稼働の監視時の通知や内部処理の自動化のためにAWS Lambdaを利用しており、Pythonで処理を実装している関数が多くあります。AWS Lambdaでは、さまざまなランタイムが利用できるのですが、我々が利用しているPythonのランタイムがend-of-lifeとなると、AWSのサポートも終了するため、定期的にランタイムを更新しなければなりません。
We are contacting you as we have identified that your AWS Account currently has one or more AWS Lambda functions using the Python 3.8 runtime.
We are ending support for Python 3.8 in Lambda on October 14, 2024. This follows Python 3.8 End-Of-Life (EOL) which is scheduled for October, 2024 [1].
お知らせ:AWS Lambdaにおける Python 3.8 のサポート終了について(通知メールから抜粋)
今回は、AWS LambdaでPython 3.8のランタイムを利用している関数をPython3.12に変更する際に実施したことをまとめます。
目次
ランタイム更新の流れ
Pythonのランタイムを更新する流れは以下の通りです。
- Lambda関数を複製し、ランタイム更新を検証するための関数を作成する。
- Pythonのランタイムを更新する。
- Pythonのレイヤーを更新する。
- 関数をテストする。
- オリジナルのLambda関数を変更する。
1. Lambda関数を複製し、ランタイム更新を検証するための関数を作成する
本番環境で稼働しているLambda関数を直接変更するのは障害が発生するリスクがあります。そのため、同様の関数を検証用に複製し、問題なくランタイムの更新ができることを確認した後、本番環境のLambda関数を更新します。
Lambda関数を複製する方法はいくつかあります。具体的な内容は割愛します。
- AWSマネジメントコンソールを用いて手作業で複製する。
- AWS CLIを用いて関数のコードおよび設定情報を取得し、その内容を使って新規関数を作成する。
AWS CLIを使っても、VPCの設定など一部の設定は手動で行う必要があります。(AWS CLIで全てできるのかもしれませんが、私はわかりませんでした)
なお、手動で複製した際に陥りがちな問題として以下があります。Lambda関数をテストした際のエラーログを見れば、問題の原因がほぼわかります。
- 関数の実行時間を変更しておらず、関数の実行がデフォルト設定の3秒を超え、失敗する。
- 適切なIAMロールを割り当てておらず、関数の実行が権限エラーで失敗する。
- 適切なVPCを割り当てておらず、関数が接続するリソースに到達できない。
2. Pythonのランタイムを更新する
Pythonのランタイムを更新します。AWSマネジメントコンソール上でランタイムを変更するだけで済みます。
AWSのマネジメントコンソールから、Lambdaを開き、ランタイムを更新する関数を開きます。[コード] タブの [ランタイム設定] から [編集] を選択します。
(クリックで拡大)AWSマネジメントコンソール > Lambda > 関数 > 対象の関数 > コードタブ
ランタイム設定の編集の画面にて、ランタイムを変更します。今回は Python 3.8 から Python 3.12 に変更し、[保存] します。
(クリックで拡大)AWSマネジメントコンソール > Lambda > 関数 > 対象の関数 > コードタブ > ランタイム設定 > 編集
レイヤーを使っていない場合は、Pythonのランタイムを更新するだけで作業は終わりです。テストに移りましょう。レイヤーを使っている場合は、レイヤーの更新が必要です。
3. Pythonのレイヤーを更新する
レイヤーとは?
AWS Lambdaでは、AWSが標準ライブラリとして用意してくれているライブラリ以外を使いたい場合、自身でライブラリをLambda関数に関連付けをしなければなりません。このとき、Lambda関数に関連付けをするライブラリのことをレイヤーと呼びます。
Pythonのランタイムごとに、どのライブラリが標準で利用できるか(レイヤーを関連付けしなくても利用できるか)は、標準ライブラリの内容を取得すれば確認ができます。クラスメソッドさんが調査した内容を公開(2024年1月20日時点の情報)してくれています。
例えば、Python 3.8 の場合、標準で使えるパッケージは以下でした。(2024年5月14日時点)
PyMySQL 1.1.0
urllib3 1.26.18
six 1.16.0
s3transfer 0.10.0
python-dateutil 2.8.2
jmespath 1.0.1
botocore 1.34.42
boto3 1.34.42
setuptools 56.0.0
rapid-client 0.0.0
pip 23.0.1
レイヤーは、Python のランタイムごとに利用できる内容が異なるため、レイヤーを使っている場合は、ランタイムだけではなく、レイヤーも更新しなければなりません。
レイヤー更新の方法 1. パブリックなレイヤーを入れ替える
レイヤーは、ライブラリのコードがzip化されたものをアップロードする必要があります。有志の方が公開してくれているレイヤーが存在するので、自分でアップロードしなくても利用できることがあります。有名なのは、以下のKlayersでしょうか。
requests や pandas など、よく使うライブラリがレイヤーとして公開されているので、Python 3.12 で使いたいライブラリが既に公開されていれば、現在のレイヤーを削除し、新しいレイヤーを追加するだけでレイヤーの更新は終わりです。
[レイヤー] の [編集] から Python 3.8 のレイヤーを削除します。
(クリックで拡大)AWSマネジメントコンソール > Lambda > 関数 > 対象の関数 > コードタブ
[レイヤーの追加] から、Python 3.12 のレイヤーを追加する。
(クリックで拡大)AWSマネジメントコンソール > Lambda > 関数 > 対象の関数 > コードタブ > レイヤー > 編集
レイヤー更新の方法 2. 自分でzipファイルをアップロードし、レイヤーを作成する
今回、ランタイムを更新した Lambda関数の中には、Klayersで公開されていた Python 3.8 のレイヤーが、3.12では公開されていないものを使っていたため、自分でレイヤーを作成する必要がありました。例えば、以下のPyMySQLはKlayersで3.8ランタイムで公開されていますが、3.12では公開されていません。
Package Version | arn | Package |
---|---|---|
1.1.0 | arn:aws:lambda:ap-northeast-1:770693421928:layer:Klayers-p38-PyMySQL:2 | PyMySQL |
AWS Cloud9やLinux環境を用いて作成する手順もありますが、今回はWindowsマシン上でレイヤーを作ったため、その手順を記載します。
- Windows 10 Pro 22H2
- Docker for Windows 4.30.0 (149282)
実施した手順は以下です。
- Dockerコンテナで対象のPythonバージョンとパッケージを固める。
- 固めたzipをアップロードし、AWS Lambda Layerとして作成する。
1. Dockerコンテナで対象のPythonバージョンとパッケージを固める。
以下のDockerfileを用意しました。Pythonバージョンやパッケージ名を変えれば、他のパッケージでも使えます。
# 基本イメージを指定
FROM public.ecr.aws/lambda/python:3.12
# Pythonバージョンとパッケージ名を環境変数として設定
ENV PYTHON_VERSION="3.12"
ENV PACKAGE_NAME="pymysql"
# 必要なパッケージのインストール
RUN dnf update && dnf install -y zip findutils
# パッケージをインストール
RUN pip install ${PACKAGE_NAME} -t /python/lib/python${PYTHON_VERSION}/site-packages/
# 余分なファイルを削除
RUN rm -rf /python/lib/python${PYTHON_VERSION}/site-packages/*.dist-info
RUN find /python/lib/python${PYTHON_VERSION}/site-packages/ -name "*.pyc" -delete
ENTRYPOINT [""]
# レイヤーコンテンツをZIPファイルに圧縮
CMD zip -r /output/layer_${PACKAGE_NAME}_${PYTHON_VERSION}.zip /python/
- 5行目:Pythonのバージョンを指定
- 6行目:レイヤー化したいPythonパッケージ名(pipで指定するパッケージ名)を指定
- 21行目:パッケージをzipで固める
このDockerfileを使ってコンテナを起動することで、目的とするPythonパッケージのみをzip化することができます。
Dockerfileを作成したら、Windows PowerShellでDockerfileを配置している場所に移動し、以下のコマンドを実行します。
docker build -t lambda-layer-pymysql .
docker run --rm -v ${PWD}/output:/output lambda-layer-pymysql
outputフォルダー以下に layer_pymysql_3.12.zip というファイルができます。
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2024/05/22 11:24 44483 layer_pymysql_3.12.zip
2. 固めたzipをアップロードし、AWS Lambda Layerとして作成する。
AWSのマネジメントコンソールから、Lambdaを開き、 [レイヤー] から [レイヤーの作成] を選択します。作成したzipファイルをアップロードし、レイヤーを作成します。
(クリックで拡大)AWSマネジメントコンソール > Lambda > レイヤー > レイヤーの作成
レイヤーを作成できたら、arnの値をコピーしておきます。
(クリックで拡大)AWSマネジメントコンソール > Lambda > レイヤー > 作成したレイヤー
ランタイムを更新するLambda関数を開き、[コード] タブの [レイヤー] から [レイヤーの追加] を選択します。[ARNを指定]をチェックし、さきほどコピーしたarnの値をペースト、検証して追加します。
(クリックで拡大)AWSマネジメントコンソール > Lambda > 関数 > 対象の関数 > コードタブ > レイヤー > レイヤーの追加
以上の手順でレイヤーが更新できました。
4. 関数をテストする
関数が正しく動くことを確認しましょう。
今回更新した関数は、イベントを受け取って通知を行うアプリだったのですが、テスト用のJSON形式のデータは生成AIに提供してもらいました。こういうときに生成AIは便利です。
(クリックで拡大)生成AIでAWS SNSのイベントをテスト用に生成
Lambdaの[テスト]タブから、準備したJSONデータを使ってテストデータを作成、テストを実施します。
(クリックで拡大)AWSマネジメントコンソール > Lambda > 関数 > 対象の関数 > テストタブ
5. オリジナルのLambda関数を変更する
テスト用に作成した関数が無事に動くことが確認できたら、オリジナルのLambda関数を変更してランタイムの更新は完了です。おつかれさまでした。
まとめ
AWS Lambda関数でレイヤーを使っている場合、ランタイムの更新は少し面倒な作業だと感じていました。Dockerコンテナを利用することで、Linux環境やAWSのCloud9環境を使わずともレイヤーを自作できるため、今回の更新は比較的楽に行うことができました。
Lambda関数のメンテナンスで苦労されている方の助けとなれば幸いです。
☁️ 弊社が提供しているクラウドサービス ☁️
- 「TestRail」は、世界で250,000人以上のユーザーが利用しているWebベースのテスト管理ツールです。テストケース、テスト結果、テストの進捗状況、不具合の検出状況など、テストに係わるさまざまな”管理すべき”ものをシンプルに、快適に、かつ効率的に管理できます。
- RedmineやJIRAといった課題管理ツールや、RanorexなどのUIテスト自動化ツールとの連携がサポートされており、開発やテストの効率アップを推進できます。
- 「Redmine」ならびに「Lychee Redmine」を利用できるサービスを提供しています。
- Lychee Redmineは、オープンソースソフトウェアで人気のあるRedmineのプロジェクト管理機能を強化したプラグインです。
- さわれるガントチャートによる直感的操作でのスケジュール管理をはじめ、プロジェクト進捗状況の可視化、工数の予実管理、プロジェクトレポート作成、EVMなど、プロジェクトマネージャーにとって、使い勝手の良いさまざまな機能を搭載しています。