serverless-artilleryでIP制限のあるAPIの負荷テストを行う
仕事で負荷テストツールの選定をしているので、得た知見をブログに書いていこうと思います。
ちなみに、今まで負荷テストは人任せで、ツールはほとんど触ったことがありませんでした 😑
serverless-artillery
serverless-artillery は負荷テストツールのArtillery を Serverless Framework を使ってAWS LambdaにDeployしてくれるプロジェクトです。 負荷テストを実行する際にテストサーバのスケールを考慮しなくて良くなり、簡単に大量リクエストのテストを実行することができます。
日本語の記事だと、こちらに詳しい解説が載っていて、ものすごく参考になりました。
サーバレス時代の負荷テスト戦略 〜CircleCIで実現する継続的負荷テストとチューニングTips〜 - Qiita
で、公開Webサービスなら問題ないのですが、IP Addressのアクセス制限をしているWebアプリケーション (開発中のAPIとか、社内からのアクセス限定のAPIとか) をテストする場合はLambdaからのアクセスを許容してあげる必要があります。
1. VPC内にLambdaをDeployする
VPC内のPrivate subnetにLambdaを配置して、NAT-Gatewayに設定したElastic IPからのアクセスを許可します。 この場合、Subnetに割り当てたIP Address数までしかスケールできないので、せっかくLambdaを使っているのになあ感があって正直あんまりやりたくありません😐
serverless-artilleryをVPC内にデプロイする場合、serverless.ymlに設定します。
# ... 前略 functions: loadGenerator: # !!Do not edit this name!! handler: handler.handler # the serverlessArtilleryLoadTester handler() method can be found in the handler.js source file timeout: 300 # set timeout to be 5 minutes (max for Lambda) # ここに設定する vpc: # Optional VPC. But if you use VPC then both subproperties (securityGroupIds and subnetIds) are required securityGroupIds: - 'sg-123456789' subnetIds: - 'subnet-123456789' - 'subnet-987654321' # 後略 ...
2. AWSのLambdaからのアクセスを一時的に許可する
テストのときだけLambda (EC2) のIP Rangesからのアクセスを許容するようにします。 この場合、継続的なテストができない点が課題になります。また、一時的にIP制限が緩くなることを許容する必要があります。
terraformを利用する場合、簡単にSecurity Groupを作成できます。
data "aws_ip_ranges" "tokyo_ec2" { regions = ["ap-northeast-1"] services = ["ec2"] } resource "aws_security_group" "from_tokyo" { name = "from-tokyo" vpc_id = local.vpc_id ingress { # httpsなら443 from_port = "80" to_port = "80" protocol = "tcp" cidr_blocks = data.aws_ip_ranges.tokyo_ec2.cidr_blocks ipv6_cidr_blocks = data.aws_ip_ranges.tokyo_ec2.ipv6_cidr_blocks } description = "from-tokyo" tags = { CreateDate = data.aws_ip_ranges.tokyo_ec2.create_date SyncToken = data.aws_ip_ranges.tokyo_ec2.sync_token } }
あとはターゲットのLoad Balancerなりに作成したSecurity groupを設定すればOKです。 IP Rangesは不定期に更新されるので、テストのたびにsecurity groupを最新化する必要があります。
まとめ
ある程度のセキュリティリスクを許容できるなら、EC2からのアクセスを許容するのが良いと思います。
許容できないなら、制限のある環境でLambdaを使うよりも、Locustを利用してdocker-composeでslaveを立てる方が良いかなー 🤔
参考
サーバレス時代の負荷テスト戦略 〜CircleCIで実現する継続的負荷テストとチューニングTips〜 - Qiita
AWS: aws_ip_ranges - Terraform by HashiCorp
Serverless Framework - AWS Lambda Guide - Serverless.yml Reference