Elasticache for RedisでAutoScalingを利用できるようになりました

2021.09.07

中山(順)です

少し前にElasticache for RedisでAutoScalingが利用できるようになりました。

Amazon ElastiCache for Redis now supports auto scaling

早速試してみましょう。

要件

まずは動作要件を確認します。

Prerequisites

  • Redis (cluster mode enabled) clusters running Redis engine version 6.x onwards
  • Instance type families - R5, R6g, M5, M6g
  • Instance sizes - Large, XLarge, 2XLarge
  • Auto Scaling in ElastiCache for Redis is not supported for clusters running in Global datastores, Outposts or Local Zones.
  • AWS Auto Scaling for ElastiCache for Redis is available in the following regions: US East (N. Virginia), EU (Ireland), Asia Pacific (Mumbai) and South America (Sao Paulo).

本記事を作成時点では東京リージョンでの利用はサポートされていません(2021年9月7日)。 早く東京で使いたいという方は、ユースケースを添えて(ここ大事)AWSさんに要望しましょう!

やってみた

以下の手順で検証を行います。

  • 前提リソースの作成
  • レプリケーショングループの作成
  • シャードのスケールアウト
  • シャードのスケールイン

今回はバージニアリージョンを利用します。

また、一部マネージメントコンソールでサポートされていない設定があるので、基本的にCLIで作業を行います。

前提リソースの作成

レプリケーショングループを作成する前に前提となるリソースを作成します。

VPCはDefault VPCを利用するものとして、Subnet GroupとSecurity Groupを作成します。

まずはSubnet Groupを作成します。

aws elasticache create-cache-subnet-group \
    --cache-subnet-group-name "test-autoscaling" \
    --cache-subnet-group-description "test autoscaling for elasticache" \
    --subnet-ids "subnet-0b99c27878f8bb2fe" "subnet-0963abf36aa173b28" "subnet-03a36d242da23ef1f" "subnet-0ad4f589b204f5d35" "subnet-0d959af0cf3e86217" "subnet-002ee427150558415"
{
    "CacheSubnetGroup": {
        "VpcId": "vpc-0198b9e518ae70d94", 
        "CacheSubnetGroupDescription": "test autoscaling for elasticache", 
        "Subnets": [
            {
                "SubnetIdentifier": "subnet-002ee427150558415", 
                "SubnetAvailabilityZone": {
                    "Name": "us-east-1c"
                }
            }, 
            {
                "SubnetIdentifier": "subnet-0d959af0cf3e86217", 
                "SubnetAvailabilityZone": {
                    "Name": "us-east-1b"
                }
            }, 
            {
                "SubnetIdentifier": "subnet-0ad4f589b204f5d35", 
                "SubnetAvailabilityZone": {
                    "Name": "us-east-1e"
                }
            }, 
            {
                "SubnetIdentifier": "subnet-03a36d242da23ef1f", 
                "SubnetAvailabilityZone": {
                    "Name": "us-east-1a"
                }
            }, 
            {
                "SubnetIdentifier": "subnet-0963abf36aa173b28", 
                "SubnetAvailabilityZone": {
                    "Name": "us-east-1d"
                }
            }, 
            {
                "SubnetIdentifier": "subnet-0b99c27878f8bb2fe", 
                "SubnetAvailabilityZone": {
                    "Name": "us-east-1f"
                }
            }
        ], 
        "ARN": "arn:aws:elasticache:us-east-1:521539043457:subnetgroup:test-autoscaling", 
        "CacheSubnetGroupName": "test-autoscaling"
    }
}

Security Groupを作成します。

aws ec2 create-security-group \
    --group-name TestAutoScalingElasticache \
    --description "Test AutoScaling for Elasticahe" \
    --vpc-id vpc-0198b9e518ae70d94
{
    "GroupId": "sg-0f3f37924b1881e5e"
}
aws ec2 authorize-security-group-ingress \
    --group-id sg-0f3f37924b1881e5e \
    --protocol tcp \
    --port 6379 \
    --cidr 172.31.0.0/16
{
    "Return": true, 
    "SecurityGroupRules": [
        {
            "SecurityGroupRuleId": "sgr-09ad457d644852671", 
            "FromPort": 6379, 
            "GroupOwnerId": "521539043457", 
            "ToPort": 6379, 
            "IpProtocol": "tcp", 
            "CidrIpv4": "172.31.0.0/16", 
            "GroupId": "sg-0f3f37924b1881e5e", 
            "IsEgress": false
        }
    ]
}

レプリケーショングループの作成

スケールアウトさせるレプリケーショングループを作成します。 今回は、Shardを2 / Shardあたりのレプリカを1 / 合計ノード数4のレプリケーショングループを作成します。

aws elasticache create-replication-group \
    --replication-group-id "test-autoscaling" \
    --replication-group-description "test autoscaling" \
    --automatic-failover-enabled \
    --multi-az-enabled \
    --num-node-groups 2 \
    --replicas-per-node-group 1 \
    --cache-node-type cache.m6g.large \
    --engine "redis" \
    --engine-version "6.x" \
    --cache-parameter-group-name "default.redis6.x.cluster.on" \
    --cache-subnet-group-name test-autoscaling \
    --security-group-ids "sg-0f3f37924b1881e5e" \
    --port 6379 \
    --no-transit-encryption-enabled \
    --no-at-rest-encryption-enabled \
    --log-delivery-configurations "LogType=slow-log,Enabled=false" "LogType=engine-log,Enabled=false"
{
    "ReplicationGroup": {
        "Status": "creating", 
        "MultiAZ": "enabled", 
        "Description": "test autoscaling", 
        "AtRestEncryptionEnabled": false, 
        "ClusterEnabled": true, 
        "LogDeliveryConfigurations": [], 
        "ReplicationGroupId": "test-autoscaling", 
        "GlobalReplicationGroupInfo": {}, 
        "SnapshotRetentionLimit": 0, 
        "AutomaticFailover": "enabled", 
        "TransitEncryptionEnabled": false, 
        "SnapshotWindow": "07:30-08:30", 
        "MemberClusters": [
            "test-autoscaling-0001-001", 
            "test-autoscaling-0001-002", 
            "test-autoscaling-0002-001", 
            "test-autoscaling-0002-002"
        ], 
        "CacheNodeType": "cache.m6g.large", 
        "ARN": "arn:aws:elasticache:us-east-1:521539043457:replicationgroup:test-autoscaling", 
        "PendingModifiedValues": {}
    }
}

シャードのスケールアウト

まずはシャードのスケールアウトを試します。

スケーリングは、Target tracking scalingとScheduled scalingの2種類がサポートされています。 スケールアウトではScheduled scaling(1回)で試してみます。

シャードを2から3に増やす場合、マネージメントコンソールの場合には以下のように設定します。

CLIの場合、最初に register-scalable-target コマンドでリソースを登録します。 なお、 --scalable-dimension "elasticache:replication-group:NodeGroups" でシャードをスケールさせることを指定しています。

aws application-autoscaling register-scalable-target \
    --service-namespace "elasticache" \
    --scalable-dimension "elasticache:replication-group:NodeGroups" \
    --resource-id "replication-group/test-autoscaling" \
    --min-capacity 2 \
    --max-capacity 3

設定を確認します。

aws application-autoscaling describe-scalable-targets \
    --service-namespace elasticache
{
    "ScalableTargets": [
        {
            "ServiceNamespace": "elasticache",
            "ResourceId": "replication-group/test-autoscaling",
            "ScalableDimension": "elasticache:replication-group:NodeGroups",
            "MinCapacity": 2,
            "MaxCapacity": 3,
            "RoleARN": "arn:aws:iam::521539043457:role/aws-service-role/elasticache.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ElastiCacheRG",
            "CreationTime": "2021-09-07T11:35:39.091000+00:00",
            "SuspendedState": {
                "DynamicScalingInSuspended": false,
                "DynamicScalingOutSuspended": false,
                "ScheduledScalingSuspended": false
            }
        }
    ]
}

リソースの登録後にスケーリングポリシーを設定します。

aws application-autoscaling put-scheduled-action \
    --scheduled-action-name "test-scheduled-policy" \
    --service-namespace "elasticache" \
    --resource-id "replication-group/test-autoscaling" \
    --scalable-dimension "elasticache:replication-group:NodeGroups" \
    --schedule "at(2021-9-7T20:40:00)" \
    --timezone "Asia/Tokyo" \
    --scalable-target-action "MinCapacity=3,MaxCapacity=3"

設定を確認します。

aws application-autoscaling describe-scheduled-actions \
    --service-namespace elasticache
{
    "ScheduledActions": [
        {
            "ScheduledActionName": "test-scheduled-policy",
            "ScheduledActionARN": "arn:aws:autoscaling:us-east-1:521539043457:scheduledAction:b0a9f212-6668-455c-bb96-ad1b1f966bec:resource/elasticache/replication-group/test-autoscaling:scheduledActionName/test-scheduled-policy",
            "ServiceNamespace": "elasticache",
            "Schedule": "at(2021-9-7T20:40:00)",
            "Timezone": "Asia/Tokyo",
            "ResourceId": "replication-group/test-autoscaling",
            "ScalableDimension": "elasticache:replication-group:NodeGroups",
            "ScalableTargetAction": {
                "MinCapacity": 3,
                "MaxCapacity": 3
            },
            "CreationTime": "2021-09-07T11:37:09.251000+00:00"
        }
    ]
}

指定した時刻になったらスケールアウトを開始します。 処理が完了したら、アクティビティを確認します。

以下の通り、何もデータが無い状態で20分ほどで完了しました。

aws application-autoscaling describe-scaling-activities \
    --service-namespace elasticache
{
    "ScalingActivities": [
        {
            "ActivityId": "10813319-4531-417a-abb2-174ae667c4bf",
            "ServiceNamespace": "elasticache",
            "ResourceId": "replication-group/test-autoscaling",
            "ScalableDimension": "elasticache:replication-group:NodeGroups",
            "Description": "Setting NodeGroups of ElastiCache cluster to 3.",
            "Cause": "minimum capacity was set to 3",
            "StartTime": "2021-09-07T11:40:11.263000+00:00",
            "EndTime": "2021-09-07T12:00:49.229000+00:00",
            "StatusCode": "Successful",
            "StatusMessage": "Successfully set NodeGroups of ElastiCache cluster to 3. Change successfully fulfilled by elasticache."
        },
        {
            "ActivityId": "9c3e68a5-bd13-4079-bf81-864eb6a4c8d3",
            "ServiceNamespace": "elasticache",
            "ResourceId": "replication-group/test-autoscaling",
            "ScalableDimension": "elasticache:replication-group:NodeGroups",
            "Description": "Setting min capacity to 3 and max capacity to 3",
            "Cause": "scheduled action name test-scheduled-policy was triggered",
            "StartTime": "2021-09-07T11:40:10.233000+00:00",
            "EndTime": "2021-09-07T11:40:10.246000+00:00",
            "StatusCode": "Successful",
            "StatusMessage": "Successfully set min capacity to 3 and max capacity to 3"
        }
    ]
}

レプリケーションの状態も確認してみましょう。

以下の通り、Shardが指定した数に増えています。 また、スケールアウトに際してスロットのリバランスも行われているように見受けられます。

aws elasticache describe-replication-groups
{
    "ReplicationGroups": [
        {
            "ReplicationGroupId": "test-autoscaling",
            "Description": "test autoscaling",
            "GlobalReplicationGroupInfo": {},
            "Status": "available",
            "PendingModifiedValues": {},
            "MemberClusters": [
                "test-autoscaling-0001-001",
                "test-autoscaling-0001-002",
                "test-autoscaling-0002-001",
                "test-autoscaling-0002-002",
                "test-autoscaling-0003-001",
                "test-autoscaling-0003-002"
            ],
            "NodeGroups": [
                {
                    "NodeGroupId": "0001",
                    "Status": "available",
                    "Slots": "0-1575,4306-8191",
                    "NodeGroupMembers": [
                        {
                            "CacheClusterId": "test-autoscaling-0001-001",
                            "CacheNodeId": "0001",
                            "PreferredAvailabilityZone": "us-east-1c"
                        },
                        {
                            "CacheClusterId": "test-autoscaling-0001-002",
                            "CacheNodeId": "0001",
                            "PreferredAvailabilityZone": "us-east-1d"
                        }
                    ]
                },
                {
                    "NodeGroupId": "0002",
                    "Status": "available",
                    "Slots": "10923-16383",
                    "NodeGroupMembers": [
                        {
                            "CacheClusterId": "test-autoscaling-0002-001",
                            "CacheNodeId": "0001",
                            "PreferredAvailabilityZone": "us-east-1b"
                        },
                        {
                            "CacheClusterId": "test-autoscaling-0002-002",
                            "CacheNodeId": "0001",
                            "PreferredAvailabilityZone": "us-east-1a"
                        }
                    ]
                },
                {
                    "NodeGroupId": "0003",
                    "Status": "available",
                    "Slots": "1576-4305,8192-10922",
                    "NodeGroupMembers": [
                        {
                            "CacheClusterId": "test-autoscaling-0003-001",
                            "CacheNodeId": "0001",
                            "PreferredAvailabilityZone": "us-east-1a"
                        },
                        {
                            "CacheClusterId": "test-autoscaling-0003-002",
                            "CacheNodeId": "0001",
                            "PreferredAvailabilityZone": "us-east-1f"
                        }
                    ]
                }
            ],
            "AutomaticFailover": "enabled",
            "MultiAZ": "enabled",
            "ConfigurationEndpoint": {
                "Address": "test-autoscaling.rz4opq.clustercfg.use1.cache.amazonaws.com",
                "Port": 6379
            },
            "SnapshotRetentionLimit": 0,
            "SnapshotWindow": "07:30-08:30",
            "ClusterEnabled": true,
            "CacheNodeType": "cache.m6g.large",
            "AuthTokenEnabled": false,
            "TransitEncryptionEnabled": false,
            "AtRestEncryptionEnabled": false,
            "ARN": "arn:aws:elasticache:us-east-1:521539043457:replicationgroup:test-autoscaling",
            "LogDeliveryConfigurations": [],
            "ReplicationGroupCreateTime": "2021-09-07T10:54:39.885000+00:00"
        }
    ]
}

簡単ではありますが、シャードのスケールアウトの確認は以上です。

このタイミングで、作成したScheduled Policyは削除しておきます。

aws application-autoscaling delete-scheduled-action \
    --scheduled-action-name "test-scheduled-policy" \
    --service-namespace "elasticache" \
    --resource-id "replication-group/test-autoscaling" \
    --scalable-dimension "elasticache:replication-group:NodeGroups"

シャードのスケールイン

次に、スケールインを試します。

スケールインの動作確認ではTarget tracking policyを利用して、「メモリの利用率:50%」に収束するようなポリシーを定義してみます。

マネージメントコンソールの場合は以下のように設定します。

CLIでは以下のように設定します。 ポリシーが作成されると、CloudWatch Alarmが自動で作成されます。 このAlarmは触れないようにしましょう。

TARGET_TRACKING_SCALING_POLICY_FILE_NAME='TargetTrackingScalingPolicy.json'

cat << EOF > ${TARGET_TRACKING_SCALING_POLICY_FILE_NAME}
{
    "TargetValue": 50,
    "PredefinedMetricSpecification": {
        "PredefinedMetricType": "ElastiCacheDatabaseMemoryUsageCountedForEvictPercentage"
    },
    "ScaleOutCooldown": 600,
    "ScaleInCooldown": 300,
    "DisableScaleIn": false
}
EOF

aws application-autoscaling  put-scaling-policy \
    --policy-name "test-target-tracking-policy" \
    --service-namespace "elasticache" \
    --resource-id "replication-group/test-autoscaling" \
    --scalable-dimension "elasticache:replication-group:NodeGroups" \
    --policy-type "TargetTrackingScaling" \
    --target-tracking-scaling-policy-configuration file://${TARGET_TRACKING_SCALING_POLICY_FILE_NAME}
{
    "PolicyARN": "arn:aws:autoscaling:us-east-1:521539043457:scalingPolicy:b0a9f212-6668-455c-bb96-ad1b1f966bec:resource/elasticache/replication-group/test-autoscaling:policyName/test-target-tracking-policy",
    "Alarms": [
        {
            "AlarmName": "TargetTracking-replication-group/test-autoscaling-AlarmHigh-36df5b9b-1984-4d4f-a917-8c3d5ebefcb7",
            "AlarmARN": "arn:aws:cloudwatch:us-east-1:521539043457:alarm:TargetTracking-replication-group/test-autoscaling-AlarmHigh-36df5b9b-1984-4d4f-a917-8c3d5ebefcb7"
        },
        {
            "AlarmName": "TargetTracking-replication-group/test-autoscaling-AlarmLow-026619c1-fb0a-4a35-9b09-8b72d6bc845c",
            "AlarmARN": "arn:aws:cloudwatch:us-east-1:521539043457:alarm:TargetTracking-replication-group/test-autoscaling-AlarmLow-026619c1-fb0a-4a35-9b09-8b72d6bc845c"
        }
    ]
}

ちなみに、この流れで作業をしていた場合には先ほど設定したScheduled Policyによって最小シャード数および最大シャード数が共に3になっていてスケールインしないため、設定の上書きを行います。 ゼロから設定する場合は、こちらのコマンドを先に実行してください。

aws application-autoscaling register-scalable-target \
    --service-namespace "elasticache" \
    --scalable-dimension "elasticache:replication-group:NodeGroups" \
    --resource-id "replication-group/test-autoscaling" \
    --min-capacity 2 \
    --max-capacity 3

aws application-autoscaling describe-scalable-targets --service-namespace elasticache
{
    "ScalableTargets": [
        {
            "ServiceNamespace": "elasticache",
            "ResourceId": "replication-group/test-autoscaling",
            "ScalableDimension": "elasticache:replication-group:NodeGroups",
            "MinCapacity": 2,
            "MaxCapacity": 3,
            "RoleARN": "arn:aws:iam::521539043457:role/aws-service-role/elasticache.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ElastiCacheRG",
            "CreationTime": "2021-09-07T11:35:39.091000+00:00",
            "SuspendedState": {
                "DynamicScalingInSuspended": false,
                "DynamicScalingOutSuspended": false,
                "ScheduledScalingSuspended": false
            }
        }
    ]
}

今回の環境にはデータが入っていませんのですぐにスケールインを開始します。 スケールインが完了したら、アクティビティを確認します。 今回は23分ほどで完了しました

aws application-autoscaling describe-scaling-activities \
    --service-namespace elasticache
{
    "ScalingActivities": [
        {
            "ActivityId": "1de3d1cc-075f-460a-b0f8-d782eeaa9553",
            "ServiceNamespace": "elasticache",
            "ResourceId": "replication-group/test-autoscaling",
            "ScalableDimension": "elasticache:replication-group:NodeGroups",
            "Description": "Setting NodeGroups of ElastiCache cluster to 2.",
            "Cause": "monitor alarm TargetTracking-replication-group/test-autoscaling-AlarmLow-026619c1-fb0a-4a35-9b09-8b72d6bc845c in state ALARM triggered policy test-target-tracking-policy",
            "StartTime": "2021-09-07T12:50:38.424000+00:00",
            "EndTime": "2021-09-07T13:13:22.750000+00:00",
            "StatusCode": "Successful",
            "StatusMessage": "Successfully set NodeGroups of ElastiCache cluster to 2. Change successfully fulfilled by elasticache."
        }
    ]
}

レプリケーショングループの状態も確認しておきます。 スロットのリバランスも行われていました。

aws elasticache describe-replication-groups
{
    "ReplicationGroups": [
        {
            "ReplicationGroupId": "test-autoscaling",
            "Description": "test autoscaling",
            "GlobalReplicationGroupInfo": {},
            "Status": "available",
            "PendingModifiedValues": {},
            "MemberClusters": [
                "test-autoscaling-0001-001",
                "test-autoscaling-0001-002",
                "test-autoscaling-0002-001",
                "test-autoscaling-0002-002"
            ],
            "NodeGroups": [
                {
                    "NodeGroupId": "0001",
                    "Status": "available",
                    "Slots": "0-1575,2096-8711",
                    "NodeGroupMembers": [
                        {
                            "CacheClusterId": "test-autoscaling-0001-001",
                            "CacheNodeId": "0001",
                            "PreferredAvailabilityZone": "us-east-1c"
                        },
                        {
                            "CacheClusterId": "test-autoscaling-0001-002",
                            "CacheNodeId": "0001",
                            "PreferredAvailabilityZone": "us-east-1d"
                        }
                    ]
                },
                {
                    "NodeGroupId": "0002",
                    "Status": "available",
                    "Slots": "1576-2095,8712-16383",
                    "NodeGroupMembers": [
                        {
                            "CacheClusterId": "test-autoscaling-0002-001",
                            "CacheNodeId": "0001",
                            "PreferredAvailabilityZone": "us-east-1b"
                        },
                        {
                            "CacheClusterId": "test-autoscaling-0002-002",
                            "CacheNodeId": "0001",
                            "PreferredAvailabilityZone": "us-east-1a"
                        }
                    ]
                }
            ],
            "AutomaticFailover": "enabled",
            "MultiAZ": "enabled",
            "ConfigurationEndpoint": {
                "Address": "test-autoscaling.rz4opq.clustercfg.use1.cache.amazonaws.com",
                "Port": 6379
            },
            "SnapshotRetentionLimit": 0,
            "SnapshotWindow": "07:30-08:30",
            "ClusterEnabled": true,
            "CacheNodeType": "cache.m6g.large",
            "AuthTokenEnabled": false,
            "TransitEncryptionEnabled": false,
            "AtRestEncryptionEnabled": false,
            "ARN": "arn:aws:elasticache:us-east-1:521539043457:replicationgroup:test-autoscaling",
            "LogDeliveryConfigurations": [],
            "ReplicationGroupCreateTime": "2021-09-07T10:54:39.885000+00:00"
        }
    ]
}

スケールインの動作確認は以上です。

なお、レプリカのスケーリングは、各種 application-autoscaling コマンドで指定する scalable-dimensionelasticache:replication-group:Replicas とすることで設定できますので本記事では割愛します。

まとめ

Elasticache for RedisでシャードおよびレプリカのAutoScalingができるようになりました。 これにより、キャパシティの動的な追加やコスト効率の改善ができるようになるかと思います。

今回は何もデータを保存せずにスケールアウトを試しましたが、それでもスケールアウト・スケールインにそれなりの時間を要しました。 利用する際には適切な閾値・スケジュールを求めるために十分に評価を行ってください。

また、シャードのスケールインを行う際には残りのシャードにデータが収まるように計画する必要があるでしょう。

いずれにしても、本番環境で利用する際には本番環境に近い環境で動作確認を行いましょう。