Lambda 拡張機能でパラメータやシークレットを取得する時のパフォーマンスを計測してみた

この記事を書いたメンバー:

那須 隆

Lambda 拡張機能でパラメータやシークレットを取得する時のパフォーマンスを計測してみた

目次

こんにちは、那須です。

10/18 に AWS Parameters and Secrets Lambda Extension のアナウンスがありました。今までは Lambda 関数から SSM パラメータストアのパラメータを取得したり Secrets Manager のシークレットを取得する場合は、SDK を使うことが多かったと思います。今回のアナウンスで、Lambda Layer 経由で HTTP GET を使って取得する方法も追加されました。この方法で Lambda 関数の実行時間が短くなりパフォーマンスが向上し、SDK での API アクセスも削減できコスト削減につながりますね。とても素晴らしいアップデートだと思いましたので、試してみることにしました。


Announcing AWS Parameters and Secrets Lambda Extension

aws.amazon.com

og_img


この新機能を使うべき理由

アナウンスやドキュメントに、パフォーマンスの向上とコストの削減という 2 つのメリットの記載があります。Lambda のローカルキャッシュにパラメータやシークレットが保存されることでパフォーマンス向上が見込めます。また SDK 経由で API リクエストを送信していたのを HTTP で取得するので、API コールが減ってコスト削減につながります。

Web システムやモバイルアプリのバックエンドで大量のリクエストがあるようなシステムで Lambda が使われていて、その関数の中で SSM パラメータストアや Secrets Manager への API コールがあるなら、この新機能を検証したうえで使うべきかどうか検討するのがいいですね。


パフォーマンスは本当に向上するのか?

ドキュメントに書いてあるからといって確かめもせずに鵜呑みにするのはよくないですね(信用してないわけではないです)。よくなるだろうという思い込みで実装してもあまりいい結果は得られなかった、なんて経験はないでしょうか? そういったことを避けるためには実際にやってみるのが一番です。


応答時間を計測してみた

Python 3.9 の Lambda 関数でパフォーマンス計測するためのサンプルコードを作ってみました。time でリクエストのみを計測しながら、New Relic の Lambda Monitoring でも計測します。細かい実装の内容は本記事では触れませんので、AWS ドキュメントや他社のブログ記事をご参照ください。

import time
import boto3
import os
import urllib.request
import urllib.parse

token = os.environ['AWS_SESSION_TOKEN']
ssm = boto3.client('ssm')

def get_text_parameter():
    base_url = generate_ssm_base_url()
    path_query = urllib.parse.quote_plus('name=/test/param_name', safe='=&')
    return request_open(base_url, path_query)

def get_secret_parameter():
    base_url = generate_ssm_base_url()
    path_query = urllib.parse.quote_plus('name=/test/secret_name&withDecryption=true', safe='=&')
    return request_open(base_url, path_query)

def generate_ssm_base_url():
    return 'http://localhost:2773/systemsmanager/parameters/get?'

def request_open(base_url, path_query):
    url = base_url + path_query
    request = urllib.request.Request(url)
    request.add_header('X-Aws-Parameters-Secrets-Token', token)
    start = time.perf_counter()
    with urllib.request.urlopen(request) as f:
        body = f.read().decode('utf-8')
    end = time.perf_counter()
    print(end-start)
    return body

def get_text_parameter_by_sdk():
    start = time.perf_counter()
    param = ssm.get_parameter(
        Name='/test/param_name'
    )
    end = time.perf_counter()
    print(end-start)
    return param

def get_secret_parameter_by_sdk():
    start = time.perf_counter()
    param = ssm.get_parameter(
        Name='/test/secret_name',
        WithDecryption=True
    )
    end = time.perf_counter()
    print(end-start)
    return param

def lambda_handler(event, context):
    print(get_text_parameter())
    print(get_secret_parameter())
    print(get_text_parameter_by_sdk())
    print(get_secret_parameter_by_sdk())

やっていることは以下の 4 つです。他にも様々なパターンが考えられるので、皆さんも是非計測してみてください。

  1. 新機能で SSM パラメータストアから String パラメータを取得
  2. 新機能で SSM パラメータストアから SecureString パラメータを取得
  3. SDK を使って SSM パラメータストアから String パラメータを取得
  4. SDK を使って SSM パラメータストアから SecureString パラメータを取得

サンプルコードは厳密なパフォーマンス計測手法を使ったものではないと思いますので、あくまで参考値として読んでください。それではこのサンプルコードを何度か実行して計測していきます。


計測結果

サンプルコード内の time で計測した応答時間は以下の通りです。なんかバラつきが大きい気もしますが、いずれも新機能を使う方が SDK を使うよりも応答時間が 50% 以上短縮される結果となりました。少なくとも何度やっても新機能を使ったパラメータ取得の方が応答時間が短かったので、特に理由がなければ積極的に使うべきかなと思います。


新機能&String新機能&SecureStringSDK&StringSDK&SecureString
1 回目20.1 ms19.8 ms63.6 ms49.2 ms
2 回目59.4 ms20.2 ms193.7 ms64.9 ms
3 回目19.6 ms19.8 ms212.4 ms54.3 ms
4 回目40.6 ms19.6 ms192.3 ms57.1 ms
5 回目1.3 ms18.8 ms202.0 ms67.1 ms


上記の time での結果とは微妙に数値はずれていますが、New Relic Lambda Monioring でも同様の計測結果を確認できました。上記の表の数値だけでもわかりますが、チャート表示すると視覚的にわかりやすいですね。

1 回目

2 回目

3 回目

4 回目

5 回目


注意すべきこと

この新機能を使う Lambda 関数には GetParameter アクションが実行できる IAM ロールをアタッチする必要があります。ということは SSM の API にアクセスしているということなので、サービスクオータの影響を受けるのではないかと想像できますよね。例えば Parameter Store はデフォルトスループットが 40 TPS(GetParameter、GetParameters、GetParametersByPathで共有)です。キャッシュがない状態だったりキャッシュの有効期限が切れている場合、また Lambda 関数がコールドスタート時もこのクオータの影響を受けますので、キャッシュがない時の Lambda 関数の同時実行には注意を払わないといけません。

Parameter Store の場合はスループット制限を引き上げることである程度緩和できますが、Secrets Manager の場合は上限緩和できません。Lambda 関数が大量に同時実行される可能性がある環境の場合は、API リクエスト部分に Exponential Backoff を実装しましょう。以上の注意点を 1 枚にまとめるとこのようになります。


さいごに

AWS からのアナウンスで Lambda Layer 経由で SSM パラメータストアや Secrets Manager から情報を取得できることと、新機能を使うことでパフォーマンス向上が見込めることがお分かりいただけたかと思います。アプリケーション開発でもインフラ自動化でもそうですが、とりあえず動けばいいやというところから少しでも早い方がいい!という意識をもって作ることはとても大切なことだと思います。実践し続けるのは難しいですが、こういうところから少しずつ試していきましょう!

BeeX は SAP BASIS とかインフラとかの専門の会社だと思われていることが多いですが、実はアプリケーション開発やお客様と事業を共創したりするメンバーがたくさんいます。インフラとアプリの両方を扱ってお客様のビジネスの成功を支援できますので、インフラや SAP BASIS に限らずお気軽にご相談ください!

エンジニアも募集していますので、少しでも気になる方はお気軽にお問合せください。もちろん直接応募していただいでも OK です!


採用情報|株式会社BeeX

世界に先駆け企業の基幹システムをクラウド環境へ数多くマイグレーション(移行)してきた実績を持つ、株式会社BeeXの採用情報ページです。業務拡大につき、一緒に成長できるメンバーを募集しております。

beex-inc.com

og_img


カテゴリー
タグ

SAPシステムや基幹システムのクラウド移行・構築・保守、
DXに関して
お気軽にご相談ください

03-6260-6240 (受付時間 平日9:30〜18:00)