Terraform 입문 - 반복문, if문, if-else문

empty·2020년 9월 30일
2

Terraform

목록 보기
4/4

반복문

테라폼에서 반복문 사용은 count를 사용한다. count 함수를 사용해서 변수를 불러오면 list 형태로 불러온다. 아래는 간단한 예제이다.

  • var.tf
variable "user_names" {
  type = "list"
  default = ["sin", "kim", "choi"]
}
  • iam.tf
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개를 생성시킴)

if문

테라폼에서 조건문을 설정할 때는 두가지 속성을 사용한다

  1. 테라폼에서 부울값을 true 설정으로 하면 1로 치환되고 false라면 0으로 치환된다.
  2. 리소스에 대해 count를 1로 설정하면 해당 리소스의 사본이 하나 생기고 count를 0으로 설정하면 해당 리소스가 생성되지 않는다.

간단한 if문

예제. Autoscaling 여부 트리거링

  • var.tf (트리거용 변수 선언)
variable "enable_autoscaling" {
  description = "if set to true, enable auto scaling"
}
  • autoscaling.tf
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를 설정하여 오토스케일링을 트리거할 수 있다.

  • main.tf
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면 작동하지 않는다.


복잡한 if문

단순히 true, false 말고 더욱 비교를 해야 할 경우에는 조건에 의해 반환된 값으로 설정한다.
테라폼의 조건은 다른 프로그래밍 언어와 같은 삼항(ternary) 구문을 사용한다.
count = var.enable_autoscaling ? 1 : 0

예제. Cloudwatch로 크레딧이 낮을 때 울리는 알람 추가

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으로 치환된다.

if-else 문

예제. 하나의 모듈에 두 개의 다른 사용자 데이터 스크립트를 제공하는법

  • var.tf
variable "enable_sin_user_data" {
  description = "If set to true, use the sin's User Data script"
}
  • data.tf

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 함수를 넣는다.

  • main.tf
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
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)

0개의 댓글