概要
Terraformを使ってAutoScaling環境を構築します。
以下の状態をゴールとします
- デフォルト1台
- CPUが30%超えたら1台増やす
- CPUが5%以下なら1台減らす
環境
- Terraform 0.6.9
Terraform設定
セキュリティグループなどはTerraformでAWSのセキュアな構成を構築をベースにしています。
最終的なソースは以下です。
LaunchConfig
主にセキュリティグループやどんなインスタンスを使うか、などを設定します。
resource "aws_launch_configuration" "dev_api" { name = "dev-api" image_id = "${var.amis.api}" instance_type = "t2.micro" key_name = "${var.key_name}" vpc_security_group_ids = ["${aws_security_group.internal.id}"] associate_public_ip_address = 0 lifecycle { create_before_destroy = true } }
主な項目の説明は以下です。
項目 | 意味 | 値 |
---|---|---|
image_id | 使用するAMIのID | ${var.amis.api} |
key_name | 登録するSSHキー | ${var.key_name} |
associate_public_ip_address | PublicIPを付与するか | 0(しない) |
create_before_destroy | 削除する前に新規作成する | true |
AutoScalingGroup
何台まで増やすか、どのELBに紐付けるか、などを設定します。
resource "aws_autoscaling_group" "dev_api" { availability_zones = ["ap-northeast-1a"] name = "dev-api" max_size = 4 min_size = 1 desired_capacity = 1 health_check_grace_period = 300 health_check_type = "ELB" force_delete = true launch_configuration = "${aws_launch_configuration.dev_api.id}" vpc_zone_identifier = ["${aws_subnet.private_1a.id}"] load_balancers = ["${aws_elb.dev_elb.name}"] tag = { key = "Name" value = "dev-api-asg" propagate_at_launch = true } tag = { key = "Environment" value = "Development" propagate_at_launch = true } tag = { key = "Type" value = "API" propagate_at_launch = true } lifecycle { create_before_destroy = true } }
主な項目の説明は以下です。
項目 | 意味 | 値 |
---|---|---|
max_size | 最大スケール幅 | 4 |
min_size | 最小スケール幅 | 1 |
desired_capacity | デフォルトの台数 | 1 |
launch_configuration | LauchConfigの指定 | ${aws_launch_configuration.dev_api.id} |
vpc_zone_identifier | サブネット | ${aws_subnet.private_1a.id} |
load_balancers | インスタンスを登録するELB | ${aws_elb.dev_elb.name} |
propagate_at_launch | 生成されたインスタンスにこのタグを付けるか | true |
create_before_destroy | 削除する前に新規作成する | true |
Policy
どのようにスケールアウト・スケールインさせるかの設定です。
resource "aws_autoscaling_policy" "dev_api_scale_out" { name = "Instance-ScaleOut-CPU-High" scaling_adjustment = 1 adjustment_type = "ChangeInCapacity" cooldown = 300 autoscaling_group_name = "${aws_autoscaling_group.dev_api.name}" } resource "aws_autoscaling_policy" "dev_api_scale_in" { name = "Instance-ScaleIn-CPU-Low" scaling_adjustment = -1 adjustment_type = "ChangeInCapacity" cooldown = 300 autoscaling_group_name = "${aws_autoscaling_group.dev_api.name}" }
主な項目の説明は以下です。
項目 | 意味 | 値 |
---|---|---|
scaling_adjustment | 増減させる台数 | 1 or -1 |
adjustment_type | 台数の増やし方。下記詳細参照 | ChangeInCapacity |
cooldown | この期間はイベント発火はしません。秒間。 | 300 |
autoscaling_group_name | どのASGへ設定するか | ${aws_autoscaling_group.dev_api.name} |
adjustment_type
は以下の設定ができます。
項目 | 意味 |
---|---|
ChangeInCapacity | 指定した値だけ既存の値から増減させる |
ExactCapacity | 既存の値に関係なく指定した値にする |
PercentChangeInCapacity | 指定した値を百分率とした割合で増減させる |
Alarm
どういう状況になったらスケールアウト、スケールインするか、の設定です。
resource "aws_cloudwatch_metric_alarm" "dev_api_high" { alarm_name = "dev-api-CPU-Utilization-High-30" comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "1" metric_name = "CPUUtilization" namespace = "AWS/EC2" period = "300" statistic = "Average" threshold = "30" dimensions { AutoScalingGroupName = "${aws_autoscaling_group.dev_api.name}" } alarm_actions = ["${aws_autoscaling_policy.dev_api_scale_out.arn}"] } resource "aws_cloudwatch_metric_alarm" "dev_api_low" { alarm_name = "dev-api-CPU-Utilization-Low-5" comparison_operator = "LessThanThreshold" evaluation_periods = "1" metric_name = "CPUUtilization" namespace = "AWS/EC2" period = "300" statistic = "Average" threshold = "5" dimensions { AutoScalingGroupName = "${aws_autoscaling_group.dev_api.name}" } alarm_actions = ["${aws_autoscaling_policy.dev_api_scale_in.arn}"] }
主な項目の説明は以下です。
項目 | 意味 | 値 |
---|---|---|
alarm_name | アラーム名。変更不可。区別しやすい名称がいい | dev-api-CPU-Utilization-Low-5 |
comparison_operator | 条件式 | LessThanThreshold |
evaluation_periods | 何回period が起きたら発火するか |
1 |
metric_name | 監視する項目 | CPUUtilization |
period | statistic の上限期間。この秒数を超えたら発火 |
300 |
statistic | データのどの値を使うか。Sum、Minimumなど | Average |
threshold | 値の上限・下限値 | 5 |
dimensions | 監視するグラフ | ${aws_autoscaling_group.dev_api.name} |
alarm_actions | どのPolicyを発火させるか | ${aws_autoscaling_policy.dev_api_scale_in.arn} |
ELB
resource "aws_elb" "dev_elb" { name = "dev-elb" subnets = [ "${aws_subnet.public_1a.id}", ] security_groups = [ "${aws_security_group.internal.id}", "${aws_security_group.http.id}", ] listener { instance_port = 80 instance_protocol = "http" lb_port = 80 lb_protocol = "http" } health_check { healthy_threshold = 2 unhealthy_threshold = 2 timeout = 5 target = "HTTP:80/" interval = 30 } cross_zone_load_balancing = true idle_timeout = 400 connection_draining = true connection_draining_timeout = 400 tags { Environment = "Development" Name = "dev-elb" Role = "ELB" } }
ポイントとしてinstances
を付けないことです。
つけると再実行した際にASGのインスタンスが外れてしまいます。