테라폼에서 반복문 사용은 count를 사용한다. count 함수를 사용해서 변수를 불러오면 list 형태로 불러온다. 아래는 간단한 예제이다.
variable "user_names" {
type = "list"
default = ["sin", "kim", "choi"]
}
resource "aws_iam_user" "example" {
count = length(var.user_names)
name = element(var.user_names, count.index )
}
count로 user_names
에 정의되어 있는 수 만큼 count를 채우고 (여기서는 2) 그 수만큼 iam_user를 생성한다. (0~2니까 3개를 생성시킴)
테라폼에서 조건문을 설정할 때는 두가지 속성을 사용한다
count
를 1로 설정하면 해당 리소스의 사본이 하나 생기고 count
를 0으로 설정하면 해당 리소스가 생성되지 않는다.variable "enable_autoscaling" {
description = "if set to true, enable auto scaling"
}
resource "aws_autoscaling_schedule" "scale_out_during_business_hours" {
count = "${var.enable_autoscaling}"
scheduled_action_name = "scale-out-during-business-hours"
min_size = 2
max_size = 10
desired_capacity = 10
recurrence = "0 9 * * *"
autoscaling_group_name = "${aws_autoscaling_group.example.name}"
}
resource "aws_autoscaling_schedule" "scale_in_at_night" {
count = "${var.enable_autoscaling}"
scheduled_action_name = "scale-in-at-night"
min_size = 2
max_size = 10
desired_capacity = 2
recurrence = "0 17 * * *"
autoscaling_group_name = "${aws_autoscaling_group.example.name}"
}
모듈의 main.tf에 이렇게 설정을 하고 var.enable_autoscaling
이 1이라면(참) 오토스케일링 스케줄이 작동이 될것이다.
이제 enable_autoscaling
을 true, false를 설정하여 오토스케일링을 트리거할 수 있다.
module "webserver_cluster" {
source = "../../../../modules/services/webserver-cluster"
cluster_name = "webservers-stage"
db_remote_state_bucket = "${var.db_remote_state_bucket}"
db_remote_state_key = "${var.db_remote_state_key}"
instance_type = "t2.micro"
min_size = 2
max_size = 2
enable_autoscaling = false #if value is true, set autoscaling
}
enable_autoscaling
의 값이 true면 autoscaling을 작동하고 false면 작동하지 않는다.
단순히 true, false 말고 더욱 비교를 해야 할 경우에는 조건에 의해 반환된 값으로 설정한다.
테라폼의 조건은 다른 프로그래밍 언어와 같은 삼항(ternary) 구문을 사용한다.
count = var.enable_autoscaling ? 1 : 0
CPU 크레딧이 적용되는 t 계열의 인스턴스만 감지하며, 다른 큰 인스턴스 계열은 CPU 크레딧의 제약사항이 없기 때문에 CPUCreditBalance
모니터링 항목을 수집하지 않는다.
resource "aws_cloudwatch_metric_alarm" "low_cpu_credit_balance" {
count = format("%.1s", var.instance_type) == "t" ? 1 : 0
alarm_name = "${var.cluster_name}-low-cpu-credit-balance"
namespace = "AWS/EC2"
metric_name = "CPUCreditBalance"
dimensions = {
AutoScalingGroupName = "${aws_autoscaling_group.example.name}"
}
comparison_operator = "LessThanThreshold"
evaluation_periods = 1
period = 300
statistic = "Minimum"
threshold = 10
unit = "Count"
}
var.instance_type
의 첫 번째 문자만 추출하여서 만일 문자열에 't' 가 있으면 count가 1로 치환되고 없으면 0으로 치환된다.
variable "enable_sin_user_data" {
description = "If set to true, use the sin's User Data script"
}
data "template_file" "kim_user_data" {
count = 1 - var.enable_new_user_data
template = file("${path.module}/kim-user-data.sh")
vars {
server_port = var.server_port
db_address = data.terraform_remote_state.db.address
db_port = data.terraform_remote_state.db.port
}
}
data "template_file" "sin_user_data_new" {
count = var.enable_sin_user_data
template = file("${path.module}/sin-user-data.sh")
vars {
server_port = var.server_port
}
}
var에 정의한 enable_sin_user_data
이 true이면 sin의 user_data, false이면 kim의 user_data를 불러온다.
data에서 template_file을 불러오고 count 함수를 넣는다.
resource "aws_launch_configuration" "example" {
image_id = "ami-40d28157"
instance_type = "${var.instance_type}"
security_groups = ["${aws_security_group.instance.id}"]
user_data = element(
concat(data.template_file.user_data.*.rendered,
data.template_file.user_data_new.*.rendered),
0)
lifecycle {
create_before_destroy = true
}
}
...
여기서 중요한 부분은 user_data 부분이다.
user_data = element(concat(data.template_file.user_data.*.rendered,data.template_file.user_data_new.*.rendered),0)
이 복잡한 user_data의 함수를 하나하나 살펴보자
concat(data.template_file.user_data.*.rendered,
data.template_file.user_data_new.*.rendered)
우선 concat
함수의 역할은 둘 이상의 목록을 하나의 목록으로 결합시켜 주는 역할을 한다.
data.template_file.user_data.*.rendered
에서 마지막의 rendered
의 역할은
"template_file 리소스가 실제로 실행되는 결과 값을 출력해주는 역할"이다.
그래서 이 두개의 리스트 중 하나는 길이가 1이 되는것이고 다른 하나의 길이는 0이 되는것이다.
*왜 길이가 1이고 0인가? : count
변수로 인해 하나는 실행이 될것이고 하나는 실행이 안될것이니까
이제 concat
함수를 사용하여 두 리스트를 길이가 1인 하나의 리스트로 결합을 하고
element
함수를 사용하여 내부에서 반한된 길이가 1인 리스트의 값이 추출된다.
user_data = element(concat(data.template_file.user_data.*.rendered,data.template_file.user_data_new.*.rendered),0)