Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

Study_note

[3주차] T013 테라폼 스터디 본문

카테고리 없음

[3주차] T013 테라폼 스터디

Study_note 2023. 9. 17. 02:23

조건문과 함수

  • 테라폼에서 조건문은 3항 연산자 형태를 갖는다
<조건 정의> ? <옳은 경우> : <틀린 경우>
var.a != "" ? var.a : "default-a"
아래와 같이 bool 값의 변수 값을 생성
variable "enable_autoscaling" {
  description = "If set to true, enable auto scaling"
  type        = bool
}

조건문 구문은 아래와 같다
  count = <condition> ? <true_val> : <false_val> # 컨디션의 bool 값의 변수 넣는다

다음 count 매개변수 조건문 추가
resource "aws_autoscaling_schedule" "scale_in_at_night" {
  count = var.enable_autoscaling ? 1 : 0
  
파일에서 bool 입력 변수 값이 true 즉 1 값이고 false는 0값으로 지정했기 때문에
입력 값에 따라 생성된다.

-----------------------------------

하지만 bool 값이 문자열 등의 더 복잡한 비교의 결과인 경우 아래와 같다.

아래에 bool 값이 아닌 문자열 입력 변수가 있을때
variable "instance_type" {
  description = "The type of EC2 Instances to run (e.g. t2.micro)"
  type        = string
}

아래와 같이 format 함수를 사용하여 var.instance_type에서 첫 번쨰 문자만 추출하여
해당 문자가 "t"일 경우 count를 1로 설정하고 "t"가 아닐 경우 count가 0이 되어 생성되지 않는다.

resource "aws_cloudwatch_metric_alarm" "low_cpu_credit_balance" {
  count = format("%.1s", var.instance_type) == "t" ? 1 : 0
  
-----------------------------------

조금 더 효율적으로 사용하면 if-else 문을 생성할수 있다.

아래와 같이 t계열이면 low_cpu_credit_balance가 생성되고 t가 아니라면 high_cpu_credit_balance 생성
resource "aws_cloudwatch_metric_alarm" "low_cpu_credit_balance" {
  count = format("%.1s", var.instance_type) == "t" ? 1 : 0
  [config....]
  
resource "aws_cloudwatch_metric_alarm" "high_cpu_credit_balance" {
  count = format("%.1s", var.instance_type) == "t" ? 0 : 1
  [config....]


      key => upper(value)
      if key != "Name"
    }

    content {
      key                 = tag.key
      value               = tag.value
      propagate_at_launch = true
    }
  }

 

Provisioner 

local-exec / remote-exec

local-exec  : 로컬에서 실행하는 프로비저너로 여기서 로컬은 terraform apply를 실행하는 현재 머신을 의미한다.

terraform이 실행되는 환경에서 수행할 커맨드를 정의하며 아래와 같이 local-exec 값이 실행 된다.

주로 로컬에 스크립트나 프로그램을 실행하거나 할때 사용한다.

resource "aws_instance" "web" {
  # ...

  provisioner "local-exec" {
    command = "echo ${self.private_ip} >> private_ips.txt"
  }
}
---
resource "null_resource" "example1" {
  
  provisioner "local-exec" {
    command = <<EOF
      echo Hello!! > file.txt
      echo $ENV >> file.txt
      EOF
    
    interpreter = [ "bash" , "-c" ]

    working_dir = "/tmp"

    environment = {
      ENV = "world!!"
    }

  }
}

 

remote-exec : 원격 리소스가 생성 된 스크립트를 호출합니다.

 

다음 인수가 지원됩니다.

  • inline- 이것은 명령 문자열의 목록입니다. 셸을 첫 번째 명령으로 지정하지 않는 한 제공자는 기본 셸을 사용합니다  #!/bin/bash. script또는 와 함께 제공할 수 없습니다 
  • script- 이것은 원격 리소스에 복사된 다음 실행될 로컬 스크립트에 대한 경로(상대 또는 절대)입니다. 
  • scripts - 이것은 원격 리소스에 복사된 다음 실행될 로컬 스크립트에 대한 경로(상대 또는 절대) 목록입니다. 
resource "aws_instance" "web" {
  # ...

  # Establishes connection to be used by all
  # generic remote provisioners (i.e. file/remote-exec)
  connection {
    type     = "ssh"
    user     = "root"
    password = var.root_password
    host     = self.public_ip
  }

  provisioner "remote-exec" {
    inline = [
      "puppet apply",
      "consul join ${aws_instance.web.private_ip}",
    ]
  }
}

---

resource "aws_instance" "web" {
  # ...

  # Establishes connection to be used by all
  # generic remote provisioners (i.e. file/remote-exec)
  connection {
    type     = "ssh"
    user     = "root"
    password = var.root_password
    host     = self.public_ip
  }

  provisioner "file" {
    source      = "script.sh"
    destination = "/tmp/script.sh"
  }

  provisioner "remote-exec" {
    inline = [
      "chmod +x /tmp/script.sh",
      "/tmp/script.sh args",
    ]
  }
}

위와 같이 원격에 접속해서 실행하려면 connection을 지정해야 한다. 

connection은 resource 아래 선언할 수 도있고, provisioner 아래 선언할 수도 있는데 resource 아래 선언하면 해당 리솟스의 모든 프로비저너가 선언한 커넥션을 사용하게 된다.

 

(이러한 프로비정닝 도구들은 최후싀 수단으로 사용하는것을 권장한다.)

 

Provider

테라폼이 대상과의 상호작용을 할 수 있도록 하는 것이 프로바이더이며 프로바이더가 제공하는 API를 호출해 상호작용을 한다

아래와 같이 aws 뿐만 아니라 kubernetes, helm, kubectl 등 사용할 수 있으면

실제로 현 회사에서는 많은 프로바이더를 사용하고 있다.

provider "kubernetes" {
  host                   = module.eks.cluster_endpoint
  cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)

  exec {
    api_version = "client.authentication.k8s.io/v1beta1"
    command     = "aws"
    # This requires the awscli to be installed locally where Terraform is executed
    args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
  }
}

provider "helm" {
  kubernetes {
    host                   = module.eks.cluster_endpoint
    cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)

    exec {
      api_version = "client.authentication.k8s.io/v1beta1"
      command     = "aws"
      # This requires the awscli to be installed locally where Terraform is executed
      args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
    }
  }
}

provider "kubectl" {
  apply_retry_count      = 5
  host                   = module.eks.cluster_endpoint
  cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
  load_config_file       = false

  exec {
    api_version = "client.authentication.k8s.io/v1beta1"
    command     = "aws"
    # This requires the awscli to be installed locally where Terraform is executed
    args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
  }
}

 

실제로 카펜터 모듈에 테라폼 코드를 보면 여러 프로바이더를 사용했다.

아래와 같이 helm, kubecrtl 

resource "helm_release" "karpenter" {
  namespace        = "karpenter"
  create_namespace = true

  name                = "karpenter"
  repository          = "oci://public.ecr.aws/karpenter"
  repository_username = data.aws_ecrpublic_authorization_token.token.user_name
  repository_password = data.aws_ecrpublic_authorization_token.token.password
  chart               = "karpenter"
  version             = "v0.21.1"

  set {
    name  = "settings.aws.clusterName"
    value = module.eks.cluster_name
  }

  set {
    name  = "settings.aws.clusterEndpoint"
    value = module.eks.cluster_endpoint
  }

  set {
    name  = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
    value = module.karpenter.irsa_arn
  }

  set {
    name  = "settings.aws.defaultInstanceProfile"
    value = module.karpenter.instance_profile_name
  }

  set {
    name  = "settings.aws.interruptionQueueName"
    value = module.karpenter.queue_name
  }
}
---
resource "kubectl_manifest" "karpenter_provisioner" {
  yaml_body = <<-YAML
    apiVersion: karpenter.sh/v1alpha5
    kind: Provisioner
    metadata:
      name: default
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot"]
      limits:
        resources:
          cpu: 1000
      providerRef:
        name: default
      ttlSecondsAfterEmpty: 30
  YAML
Comments