すきま風

勉強したことのメモとか

serverless-artilleryでIP制限のあるAPIの負荷テストを行う

仕事で負荷テストツールの選定をしているので、得た知見をブログに書いていこうと思います。
ちなみに、今まで負荷テストは人任せで、ツールはほとんど触ったことがありませんでした 😑

serverless-artillery

serverless-artillery は負荷テストツールのArtilleryServerless 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を立てる方が良いかなー 🤔

参考

GitHub - Nordstrom/serverless-artillery: Combine serverless with artillery and you get serverless-artillery for instant, cheap, and easy performance testing at scale.

サーバレス時代の負荷テスト戦略 〜CircleCIで実現する継続的負荷テストとチューニングTips〜 - Qiita

AWS: aws_ip_ranges - Terraform by HashiCorp

Serverless Framework - AWS Lambda Guide - Serverless.yml Reference