home..

테라폼 기본 3/3

HLC Hashicorp Infra Gasida Cloud@net IaC Terraform images/T101

프로비저너

테라폼의 프로비저너는 리소스 생성, 변경 또는 삭제 작업을 보완하기 위해 사용됩니다. 프로비저너는 특정 리소스를 초기 설정, 설정 변경, 시스템에 소프트웨어 설치 등의 작업을 수행합니다.

일반적인 사용 사례

  • 파일 업로드: 서버에 필요한 설정 파일을 업로드
  • 소프트웨어 설치: 패키지 매니저를 사용하여 필요한 소프트웨어를 설치
  • 스크립트 실행: 특정 작업을 수행하기 위해 쉘 스크립트 또는 Ansible 등을 실행

주요 프로비저너 유형

  • local-exec: 로컬 머신에서 명령을 실행
  • remote-exec: 원격 머신에서 명령을 실행
  • file: 로컬 머신에서 원격 머신으로 파일 또는 디렉터리를 복사

주의사항

프로비저너의 사용은 테라폼 코드의 선언적 특성에 어긋날 수 있습니다. 따라서 가능한 프로비저너를 적게 사용하고, 다른 방법으로 리소스를 설정하는 것이 권장됩니다.

사용 예시

AWS EC2 인스턴스에 파일을 업로드하고 명령을 실행하는 예입니다.

resource "aws_instance" "example" {
  ami           = "ami-0c9c942bd7bf113a2"
  instance_type = "t2.micro"

  provisioner "file" {
    source      = "local/file/path"
    destination = "/remote/file/path"
  }

  provisioner "remote-exec" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y nginx"
    ]
  }
}

유의점

  • 순서: 프로비저너는 리소스의 생명주기 중 특정 시점에 실행됩니다. 예를 들어, 리소스 생성 후에 실행되거나 리소스 삭제 전에 실행될 수 있습니다.
  • 가변성: 프로비저너는 상태를 명시적으로 관리하지 않습니다. 따라서, 프로비저닝 로직이 변경될 경우 이전 리소스에 적용되지 않을 수 있습니다.
  • 에러 핸들링: 프로비저너가 실패하면, 테라폼은 해당 리소스를 “타인트” 상태로 마킹합니다. 이 경우 사용자는 수동으로 상태를 복구해야 할 수 있습니다.

프로비저너는 유용하지만, 가능하면 리소스의 argument 또는 setting을 통해 필요한 설정을 하는 것이 더 좋습니다. 프로비저너는 꼭 필요한 경우에만 사용하는 것이 관리 측면에서 좋습니다.


테라폼(Terraform)에서 사용되는 주요 프로비저너(provisioners)와 각각의 특성은 다음과 같습니다.

1. local-exec 프로비저

  • 특성: 로컬 시스템에서 명령어를 실행합니다.
  • 사용 사례: 리소스 생성 후 로컬에서 특정 스크립트를 실행해야 할 때 유용합니다.

2. remote-exec 프로비저너

  • 특성: 원격 서버에서 명령어를 실행합니다.
  • 사용 사례: 서버 생성 후 원격으로 초기 설정이나 패키지 설치가 필요한 경우에 사용됩니다.
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",
    ]
  }
}

3. file 프로비저너

  • 특성: 로컬 파일을 원격 서버로 복사합니다.
  • 사용 사례: 설정 파일이나 스크립트를 원격 서버에 전달해야 할 때 사용됩니다.
resource "null_resource" "foo" {
  
  # myapp.conf 파일이 /etc/myapp.conf  업로드
  provisioner "file" {
    source      = "conf/myapp.conf"
    destination = "/etc/myapp.conf"
  }
  
  # content의 내용이 /tmp/file.log 파일로 생성
  provisioner "file" {
    content     = "ami used: ${self.ami}"
    destination = "/tmp/file.log"
  }

null resource와 terraform data

null_resource

특성

  • 아무런 작업도 수행하지 않는 리소스.
  • 별도의 프로바이더 구성이 필요합니다.
  • 주로 프로비저닝 로직이나 의존성 관리를 수행하기 위해 사용됩니다.

사용 시나리오

  1. 프로비저닝 수행: local-execremote-exec과 같은 프로비저너를 활용해 명령어를 실행합니다.
  2. 의존성 관리: 다른 리소스의 생성을 조건부로 관리합니다.
  3. 데이터 처리: 출력을 위한 데이터를 가공하거나, 로컬 변수와 함께 사용합니다.

terraform_data

특성

  • 자체적으로 아무런 작업도 수행하지 않습니다.
  • 별도의 프로바이더 구성이 필요 없이 테라폼 자체의 기본 수명주기 관리자가 제공됩니다.
  • trigger_replaceinput 인수, 그리고 output 속성이 제공됩니다.

사용 시나리오

  • 기본적으로 null_resource와 동일한 사용 시나리오가 적용됩니다.
  • 강제 재실행을 위한 trigger_replace 사용이 가능합니다.
  • 상태 저장을 위한 input 인수와 그에 따른 output 속성을 활용할 수 있습니다.

추가 기능

  1. triggers_replace: tuple 형태로 기존 map 형태보다 간단하게 값들을 정의할 수 있습니다.
  2. input: 상태 저장을 위해 사용됩니다.
  3. output: input에 저장된 값을 출력합니다.

예제


resource "terraform_data" "foo" {
  triggers_replace = [
    aws_instance.foo.id,
    aws_instance.bar.id
  ]

  input = "world"
}

output "terraform_data_output" {
  value = terraform_data.foo.output  # 출력 결과는 "world"
}

moved 블록

기본 개념

  • 테라폼에서 리소스의 주소나 이름이 변경되면 기본적으로 그 리소스는 삭제되고 새로운 리소스가 생성됩니다.
  • 테라폼 1.1 버전부터는 리소스 이름이나 주소를 변경하더라도, 기존 리소스 상태를 유지하면서 이를 반영할 수 있는 moved 블록이 도입되었습니다.

주요 사용 케이스

  1. 리소스 이름 변경: 코딩 규칙이나 명명 규칙의 변화로 리소스 이름을 변경해야 할 때.
  2. 반복문 변경: count을 사용하던 것을 for_each로 변경할 때.
  3. 모듈 이동: 리소스가 다른 모듈로 이동하여 참조 주소가 변경될 때.

기존 방식 vs Moved 블록

  • 기존 방식: 이전에는 terraform state mv 명령어를 사용해서 수동으로 테라폼 상태 파일을 수정해야 했습니다. 이는 State 파일에 직접 접근해야 하므로 권한이나 복잡성 문제가 발생할 수 있습니다.
  • Moved 블록: State 파일에 직접 접근할 필요가 없습니다. 이전 주소와 새 주소를 moved 블록 내에서 선언함으로써 리소스의 이동을 안전하고 간편하게 관리할 수 있습니다.

핵심 기능

  • 리소스가 “옮겨졌다(moved)”는 사실과 그에 따른 이전 주소와 새로운 주소를 테라폼 State에 알려주는 역할을 합니다.

이러한 특징을 고려하면, moved 블록은 리소스 구성이 변경되는 다양한 상황에서 유용하게 사용될 수 있습니다. 이를 통해 테라폼 코드의 유연성과 안정성이 향상될 수 있습니다.

다음 예시 코드를 실행해봅다.

cat <<'EOT' > main.tf
resource "local_file" "a" {
  content  = "foo!"
  filename = "${path.module}/foo.bar"
}

output "file_content" {
  value = local_file.a.content
}
EOT

Untitled

이제 다음 main.tf 파일을 변경합니다다.

아래의 local_file의 이름을 a→ b 로 변경합니다

cat <<'EOT' > main.tf
resource "local_file" "b" {
  content  = "foo!"
  filename = "${path.module}/foo.bar"
}

moved {
  from = local_file.a
  to   = local_file.b
}

output "file_content" {
  value = local_file.b.content
}
EOT

Untitled

위의 결과는 moved 블록을 사용하지않고 plan 했을경우 나오는 경과문이며, moved 블록을 이용해 plan 할경우 이상이 없음을 확인할 수 있습니다.

CLI를 위한 시스템 환경변수

테라폼은 환경변수를 이용해 실행방식, 출력내용에 대한 옵션을 조정이 가능합니다

일반적인 사용

  • 테라폼 CLI 환경 변수 설정을 통해 로컬 또는 다른 서버 환경에서 특정 옵션을 지정할 수 있습니다.
  • 이 설정은 시스템 환경 변수로, 일반적으로 영구적으로 로컬 환경에 적용됩니다.

설정 방법

Mac/리눅스/유닉스: export <환경 변수 이름>=<>
Windows CMD: set <환경 변수 이름>=<>
Windows PowerShell: $Env:<환경 변수 이름>='<>'

주요 환경 변수

  1. TF_LOG: 테라폼의 로깅 레벨을 설정합니다. (trace, debug, info, warn, error, off)
  2. TF_LOG_PATH: 로그를 저장할 파일의 위치를 지정합니다.
  3. TF_LOG_CORE: 테라폼 코어 자체의 로깅 레벨을 설정합니다.
  4. TF_LOG_PROVIDER: 테라폼의 프로바이더에 대한 로깅 레벨을 설정합니다.

사용 예시

  • TF_LOGinfo로 설정하고 terraform plan을 실행하면, 관련 로그가 표시됩니다.

      bashCopy code
      TF_LOG=info terraform plan
        
    

이를 통해 테라폼 작업을 보다 세밀하게 제어하고 디버깅할 수 있습니다.

프로바이더

테라폼의 프로바이더(Provider)는 특정 클라우드 또는 서비스의 리소스를 관리하기 위한 플러그인입니다. 각 프로바이더는 해당 서비스에 특화된 리소스 생성, 수정, 관리 및 삭제 동작을 정의합니다. 예를 들어, AWS 프로바이더를 사용하면 AWS의 EC2 인스턴스, S3 버킷, RDS 데이터베이스 등을 테라폼 코드로 관리할 수 있습니다.

프로바이더는 테라폼 코드에서 provider 블록을 통해 설정됩니다. 이 블록에서는 프로바이더의 버전, 인증 정보, 지역 등을 지정할 수 있습니다.

구성

Untitled

출처 : Cloudnet 스터디

Untitled

대표적인 프로바이더 종류입니다.

terraform {
  required_providers {
    architech-http = {
      source = "architect-team/http"
      version = "~> 3.0"
    }
    http = {
      source = "hashicorp/http"
    }
    aws-http = {
      source = "terraform-aws-modules/http"
    }
  }
}

data "http" "example" {
  provider = aws-http
  url = "https://checkpoint-api.hashicorp.com/v1/check/terraform"

  request_headers = {
    Accept = "application/json"
  }
}

다음과 같이 다수의 프로바이더를 선택이 가능합니다.

단일 프로바이더를 다중정의 할 경우

# region 1
provider "aws" {
  region = "ap-southeast-1"
}

# region 2
provider "aws" {
  alias = "seoul"
  region = "ap-northeast-2"
}

resource "aws_instance" "app_server1" {
  ami           = "ami-06b79cf2aee0d5c92"
  instance_type = "t2.micro"
}

resource "aws_instance" "app_server2" {
  provider      = aws.seoul
  ami           = "ami-0ea4d4b8dc1e46212"
  instance_type = "t2.micro"
}

다음과 같은 형식으로 region에 따라 aws provider를 aws_instance에 지정하는 방식입니다.

확인 / 삭제


terraform init && terraform plan
terraform apply -auto-approve
terraform state list

terraform destroy -auto-approve

프로바이더 경험해보기

Kubernetes

Kubernetes 실습

Kubernetes 프로바이더를 사용한 Nginx Deployment + Service 배포 - [참고: Docs]

  • 실습을 위해서 4.4 디렉터리를 신규 생성 후 열기
cd ../
mkdir 4.4 && cd 4.4
  • main.tf 파일 생성 : kubernetes 프로바이더 정의 및 KUBECONFIG 파일경로 정의
terraform {
  required_providers {
    kubernetes = {
      source = "hashicorp/kubernetes"
    }
  }
}

provider "kubernetes" {
  config_path    = "~/.kube/config"
}
  • kubernetes.tf 파일 생성 : Deployment, Service 리소스 정의 - [참고: K8s YAML to HCL]
resource "kubernetes_deployment" "nginx" {
  metadata {
    name = "nginx-example"
    labels = {
      App = "images/T101-nginx"
    }
  }
  spec {
    replicas = 2
    selector {
      match_labels = {
        App = "images/T101-nginx"
      }
    }
    template {
      metadata {
        labels = {
          App = "images/T101-nginx"
        }
      }
      spec {
        container {
          image = "nginx:1.7.8"
          name  = "example"

          port {
            container_port = 80
          }
        }
      }
    }
  }
}

resource "kubernetes_service" "nginx" {
  metadata {
    name = "nginx-example"
  }
  spec {
    selector = {
      App = kubernetes_deployment.nginx.spec.0.template.0.metadata[0].labels.App
    }
    port {
      node_port   = 30080
      port        = 80
      target_port = 80
    }

    type = "NodePort"
  }
}
  • 실행

# [터미널1] terraform init & plan & apply
**terraform init && terraform plan && terraform apply -auto-approve
terraform state list**

# [터미널1] terraform destroy
**terraform destroy -auto-approve**

watch 명령어로 생성을 같이 살펴봅니다


watch -n1 -d kubectl get pods,svc

기존에 올라가있는 리소스들을 제외하고, 4m 13s 로 생성된 nginx-example 리소스를 조회 할 수 있습니다.

Untitled

helm 실습

  • 실습을 위해서 4.5 디렉터리를 신규 생성 후 열기
# 4.4 디렉토리에서 작업을 진행했다면 상위 디렉토리로 이동
cd ../
mkdir 4.5 && cd 4.5
  • main.tf
terraform {
  required_providers {
    helm = {
      source  = "hashicorp/helm"
      version = "2.11.0"
    }
  }
}

provider "helm" {
  kubernetes {
    config_path = "~/.kube/config"
  }
}
  • helm.tf
resource "helm_release" "nginx" {
  name       = "nginx"
  repository = "https://charts.bitnami.com/bitnami"
  chart      = "nginx"

  values = [
    file("${path.module}/nginx-values.yaml")
  ]
}
  • nginx-values.yaml
replicaCount: 1
service:
  type: NodePort
  • 실행
# [터미널1] terraform init & plan & apply
**terraform init && terraform plan && terraform apply -auto-approve**

# [터미널2]helm 배포확인
helm list | grep nginx
# [터미널1] terraform destroy
**terraform destroy -auto-approve**

Untitled

정상적으로 helm 프로비저닝이 된것을 확인 할 수 있다.

© 2024 mont kim   •  Powered by Soopr   •  Theme  Moonwalk