search
LoginSignup
0

posted at

updated at

Organization

オンプレミスとEC2 AutoScalingで負荷分散できる構成を検討した

概要

負荷が小さい夜間はオンプレミスのみ、負荷が大きい日中はEC2 AutoScalingでインスタンスを増やしハイブリッドに処理を分散させたいという要件があり、構成を検討しました。

課題

日中のみAutoScalingを稼働させるのはScheduled scalingで実現できるので、オンプレミスとEC2で負荷分散させる方法を考えました。
httpリクエストを受け付けるシステムのため、前段にはALBを配置します。オンプレミスのサーバーをターゲットにするため、ターゲットグループはIPターゲットにする必要があります。しかしIPターゲットにするとAutoScalingが新しいインスタンスをターゲットグループに自動登録してくれません。

ターゲットグループは、instance のターゲットタイプを指定する必要があります。Auto Scaling グループを使用する場合、ipのターゲットタイプを指定することはできません。

そのためターゲットグループへの登録はStepFunctionsで行うことにしました。

構成図

Untitled (1).png
stepfunctions_graph (1).png

実装

StepFunctionsでステートマシンを実装します。LambdaではなくSDK統合を使用します。

ステートマシン
{
  "StartAt": "DescribeInstances",
  "States": {
    "DescribeInstances": {
      "Type": "Task",
      "Parameters": {
        "InstanceIds.$": "States.Array($.detail.EC2InstanceId)"
      },
      "Resource": "arn:aws:states:::aws-sdk:ec2:describeInstances",
      "Next": "RegisterTargets",
      "ResultSelector": {
        "PrivateIpAddress.$": "$.Reservations[0].Instances[0].NetworkInterfaces[0].PrivateIpAddress"
      }
    },
    "RegisterTargets": {
      "Type": "Task",
      "End": true,
      "Parameters": {
        "TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-3:138067193396:targetgroup/asg-ip-targets/73a5kssn5s42t96u",
        "Targets": [
          {
            "Id.$": "$.PrivateIpAddress"
          }
        ]
      },
      "Resource": "arn:aws:states:::aws-sdk:elasticloadbalancingv2:registerTargets"
    }
  }
}

StepFunctionsをトリガーするイベントとしてAutoScalingのEC2 Instance Launch Successfulを使用します。

AWSコンソールで確認できるサンプルイベント
{
  "version": "0",
  "id": "3e3c153a-8339-4e30-8c35-687ebef853fe",
  "detail-type": "EC2 Instance Launch Successful",
  "source": "aws.autoscaling",
  "account": "123456789012",
  "time": "2015-11-11T21:31:47Z",
  "region": "us-east-1",
  "resources": ["arn:aws:autoscaling:us-east-1:123456789012:autoScalingGroup:eb56d16b-bbf0-401d-b893-d5978ed4a025:autoScalingGroupName/sampleLuanchSucASG", "arn:aws:ec2:us-east-1:123456789012:instance/i-b188560f"],
  "detail": {
    "StatusCode": "InProgress",
    "AutoScalingGroupName": "sampleLuanchSucASG",
    "ActivityId": "9cabb81f-42de-417d-8aa7-ce16bf026590",
    "Details": {
      "Availability Zone": "us-east-1b",
      "Subnet ID": "subnet-95bfcebe"
    },
    "RequestId": "9cabb81f-42de-417d-8aa7-ce16bf026590",
    "EndTime": "2015-11-11T21:31:47.208Z",
    "EC2InstanceId": "i-b188560f",
    "StartTime": "2015-11-11T21:31:13.671Z",
    "Cause": "At 2015-11-11T21:31:10Z a user request created an AutoScalingGroup changing the desired capacity from 0 to 1.  At 2015-11-11T21:31:11Z an instance was started in response to a difference between desired and actual capacity, increasing the capacity from 0 to 1."
  }
}

当初DescribeInstancesにインスタンスIDを渡す部分を以下のようにしており、エラーで保存できませんでしたが

The value for the field 'InstanceIds.$' must be a STRING that contains a JSONPath but was an ARRAY

NG
      "Parameters": {
        "InstanceIds.$": [
          "$.detail.EC2InstanceId"
        ]
      },

組み込み関数のStates.Arrayを使うことで解決できました。

OK
      "Parameters": {
        "InstanceIds.$": "States.Array($.detail.EC2InstanceId)"
      },

課題

本番運用する場合はリトライやエラー処理、スケールイン時のターゲット削除を追加したほうが良いでしょう。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0