★★cloudNet@ 팀의 가시다 님이 진행하는 Terraform 101 Study 4기 내용과
한빛미디어 테라폼으로 시작하는 IaC 책을 참고하여 정리하였습니다.
for Expressions

: 복합 형식 값의 형태를 변환하는 데 사용 (for_each와 다름)

  • 예를 들어 list 값의 포맷을 변경하거나 특정 접두사 prefix를 추가할 수도 있고, output에 원하는 형태로 반복적인 결과를 표현할 수도 있다.
    - list 타입의 경우 또는 인덱스와 값을 반환
    - map 타입의 경우 또는 키와 값에 대해 반환
    - set 타입의 경우 키 값에 대해 반환

main.tf 수정
terraform apply
terraform console
main.tf 수정
terraform console

  • for 구문을 사용하는 규칙
    - list 유형의 경우 반환 받는 값이 하나로 되어 있으면 값을, 두 개의 경우 앞의 인수가 인덱스를 반환하고 뒤의 인수가 값을 반환
    : 관용적으로 인덱스는 i, 값은 v로 표현
    - map 유형의 경우 반환 받는 값이 하나로 되어 있으면 키를, 두 개의 경우 앞의 인수가 키를 반환하고 뒤의 인수가 값을 반환
    : 관용적으로 키는 k, 값은 v로 표현
    - 결과 값은 for문을 묶는 기호가 [] 인 경우 tuple로 반환되고 {} 인 경우 object 형태로 반환

    - object 형태의 경우 키와 값에 대한쌍은 ==> 기호로 구분
    - {} 형식을 사용해 object 형태로 결과를 반환하는 경우 키 값은 고유해야 하므로 값 뒤에 그룹화 모드 심볼(...)를 붙여서 키의 중복을 방지(SQL의 group by문 또는 java의 MultiValueMap과 같은 개념)
    - if 구문을 추가해 조건 부여 가능

 

  • list 유형에 대한 for 구문 처리의 TEST

main.tf
terraform output
terraform console

 

  • map 유형에 대한 for 구문 처리 TEST
    : resource 블록이 없으므로 terraform state list 확인 시 결과 값이 없음

main.tf
terraform console

 

  • [악분님] for expression 실습 - map 유형에 대한 for 구문 처리 예

main.tf
terraform console
terraform console - for

 

 

▶ dynamic : 리소스 내부 속성 블록을 동적인 블록으로 생성

  • count나 for_each 구문을 사용한 리소스 전체를 여러 개 생성하는 것 이외도 리소스 내에 선언되는 구성 블록을 다중으로 작성해야 하는 경우가 있다
  • 예를 들면 AWS Security Group 리소스 구성에 ingress, egress 요소가 리소스 선언 내부에서 블록 형태로 여러 번 정의되는 경우 (resource 내부에 있는 속성을 반복=>dynamic / resource 반복 => count, for_each)
resource "aws_security_group" "example" {
  name        = "example-security-group"
  description = "Example security group"
  vpc_id.     = aws_vpc.main.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    ipv6_cidr_blocks = ["::/0"]
  }
}
  • 리소스 내의 블록 속성(Attributes as Blocks)은 리소스 자체의 반복 선언이 아닌 내부 속성 요소 중 블록으로 표현되는 부분에 대해서만 반복 구문을 사용해야 하므로, 이때 dynamic 블록을 사용해 동적인 블록 생성 가능
  • dynamic 블록을 작성하려면, 기존 블록의 속성 이름을 dynamic 블록의 이름으로 선언하고 기존 블록 속성에 정의되는 내용을 content 블록에 작성
  • 반복 선언에 사용되는 반복문 구문은 for_each를 사용
    기존 for_each 적용 시 each 속성에 key, value가 적용되었다면 dynamic에서는 dynamic에 지정한 이름에 대해 속성 부여
  • dynamic 블록 활용 예
일반적인 블록 속성 반복 적용 시 dynamic 블록 적용 시
resource "provider_resource" "name" {
 name = "some_resource"

 some_setting {
   key = a_value
 }

 some_setting {
   key = b_value
 }
 
 some_setting {
   key = c_value
 }
 
 some_setting {
   key = d_value
 }
}
resource "provider_resource" "name" {
 name = "some_resource"

 dynamic "some_setting" {
   for_each = {
      a_key = a_value
      b_key = b_value
      c_key = c_value
      d_key = d_value
   }

   content {
     key = some_setting.value
   }
 }
}

 

  • archive 프로바이더의 archive_file에 source 블록 선언을 반복

main.tf 배포 후 생성된 압축 파일 확인
dynamic을 사용하여 main.tf 수정 -> 결과는 동일

조건문

 

▶[ Conditional Expressions] 테라폼에서의 조건식은 3항 연산자 형태를 갖는다
조건은 true 또는 false로 확인되는 모든 표현식 사용

  • 일반적으로 비교, 논리 연산자를 사용해 조건 확인
  • 조건식은 ? 기호를 기준으로 왼쪽은 조건, 오른쪽은 : 기호를 기준으로 왼쪽이 조건에 대해 true가 반환되는 경우이고 오른쪽이 false가 반환
# <조건 정의> ? <옳은 경우> : <틀린 경우>
var.a != "" ? var.a : "default-a"
  • 명시적인 형태 작성을 권장
# 조건식 형태 권장 사항 
var.example ? 12 : "hello"            # 비권장
var.example ? "12" : "hello"          # 권장
var.example ? tostring(12) : "hello"  # 권장
  • 조건식은 단순히 특정 속성에 대한 정의, 로컬 변수에 대한 재정의, 출력 값에 대한 조건 정의 뿐만 아니라 리소스 생성 여부에 응용 가능
    count에 조건식을 결합한 경우 다음과 같이 특정 조건에 따라 리소스 생성 여부 선택 가능
  • main.tf 파일 내용
    : 환경 변수로 TF_VAR_enable_file 값을 false로 등록해둔 상태
    : 배포 시 파일이 생성 안됨
    : 아래 코드와 같을 경우 파일이 생성되지만 환경변수 false 값으로 인해 count가 0이 되어 파일 생성되지 않음

main.tf
환경변수 삭제 후 배포 시 정상적으로 파일 생성 확인

함수

▶ 테라폼은 프로그래밍 언어적인 특성을 가지고 있어서, 값의 유형을 변경하거나 조합할 수 있는 내장함수 사용 가능

  • 단, 내장된 함수 외에 사용자가 구현하는 별도의 사용자 정의 함수를 지원하지 않음
  • 함수 종류에는 숫자, 문자열, 컬렉션, 인코딩, 파일 시스템, 날짜/시간, 해시/암호화, IP 네트워크, 유형 변환
  • 테라폼 코드에 함수를 적용하면 변수, 리소스 속성, 데이터 소스 속성, 출력 값 표현 시 작업을 동적이고 효과적으로 수행할 수 있다

main.tf
배포 후 출력 값 확인

 

[ 추천실습] count + 함수 cidrhost로 EC2의 ENI에 10개의 ip를 장착

 

 

프로비저너

▶ 프로비저너는 프로바이더와 비슷하게 '제공자'로 해석되나, 프로바이더로 실행되지 않는 커맨드와 파일 복사 같은 역할을 수행

Provisioners are a Last Resort (다른 방안이 안되면, 최후의 수단으로 사용하라!!)

  • 예를 들어 AWS EC2 생성 후 특정 패키지를 설치해야 하거나 파일을 생성해야 하는 경우, 이것들은 테라폼의 구성과 별개로 동작해야 한다
  • 프로비저너로 실행된 결과는 테라폼의 상태 파일과 동기화되지 않으므로 프로비저닝에 대한 결과가 항상 같다고 보장할 수 없음 => 선언적 보장 안됨
  • 따라서 프로비저너 사용을 최소화
프로비저너의 종류에는 파일 복사와 명령어 실행을 위한 file, local-exec, remote-exec가 있음 인프라 배포 후 애플리케이션 설정 할 수 있는 다양한 방법이 있고 장단점이 있습니다. 좀 더 견고하고 안정적이며 신뢰할 수 있는 방법이 무엇일까요? - 참고링크 링크 
- 테라폼 코드 
userdata 사용, cloud-init 사용, Packer 활용, Provisiner Connections 활용, 별도의 설정 관리 툴 사용(Chef, Habitat, Puppet 등)
⇒ 이전에는 
local-exec provisioners를 통해서 ansible과 연동하여 인프라 배포 후 구성관리를 많이하였으나, 최근에 이러한 부분을 개선하기 위해 terraform-provider-ansible이 제공된다고 합니다
- 
https://registry.terraform.io/providers/ansible/ansible/latest/docs
 - https://github.com/ansible/terraform-provider-ansible/tree/main

 

  • 프로비저너의 경우 리소스 프로비저닝 이후 동작하도록 구성할 수 있다
    예를 들어 AWS EC2 생성 후 CLI를 통해 별도 작업 수행 상황을 가정
  • main.tf 파일 생성(실습)

main.tf
terraform apply

: error가 발생하였지만 선언적 보장을 할 수가 없으며 error 관련된 로그가 확인 불가

terraform destroy
main.tf 수정

 

배포 후 결과값

 

▶ local-exec 프로비저너 : 테라폼이 실행되는 환경에서 수행할 커맨드를 정의

  • 리눅스나 윈도우 등 테라폼을 실행하는 환경에 맞게 커맨드를 정의, 아래 사용하는 인수 값
    - command(필수) : 실행할 명령줄을 입력하며 << 연산자를 통해 여러 줄의 커맨드 입력 가능
    - working_dir(선택) : command의 명령을 실행할 디렉터리를 지정해야 하고 상대/절대 경로로 설정
    - interpreter(선택) : 명령을 실행하는 데 필요한 인터프리터를 지정하며, 첫 번째 인수로 인터프리터 이름이고 두번째부터는 인터프리터 인수 값
    - environment(선택) : 실행 시 환경 변수는 실행 환경의 값을 상속받으면, 추가 또는 재할당하려는 경우 해당 인수에 key = value 형태로 설정
  • 예시 코드

  • command의 << 연산자를 통해 다중 라인의 명령을 수행하여 각 환경에 맞는 인터프리터를 지정해 해당 명령을 수행
  • Apply 수행 시 이 명령의 실행 위치를 working_dir를 사용해 지정하고 command에서 사용하는 환경변수에 대해 environment에서 지정
  • main.tf 수정

main.tf
배포 후 결과 값

 

▶ 원격지 연결 (remote_exec 프로비저너를 사용하려면 원격지 연결이 필요)

  • remote-exec와 file 프로비저너를 사용하기 위해 원격지에 연결할 SSH, WinRM 연결 정의가 필요하다
  • connection 블록 리소스 선언 시, 해당 리소스 내에 구성된 프로비저너에 대해 공통으로 선언되고, 
    프로비저너 내에 선언되는 경우, 해당 프로비저너에서만 적용된다

# connection 블록으로 원격지 연결 정의
resource "null_resource" "example1" {
  
  connection {
    type     = "ssh"
    user     = "root"
    password = var.root_password
    host     = var.host
  }

  provisioner "file" {
    source      = "conf/myapp.conf"
    destination = "/etc/myapp.conf"
  }

  provisioner "file" {
    source      = "conf/myapp.conf"
    destination = "C:/App/myapp.conf"

    connection {
        type     = "winrm"
        user     = "Administrator"
        password = var.admin_password
        host     = var.host
    }
  }
}

 

  • connection 적용 인수와 설명

 

  • 원격 연결이 요구되는 프로비저너의 경우 스크립트 파일을 원격 시스템에 업로드해 해당 시스템의 기본 쉘에서 실행하도록 하므로 script_path의 경우 적절한 위치를 지정하도록 한다. 경로는 난수인 %RAND% 경로가 포함되어 생성된다.
Unix/Linux/macOS : /tmp/terraform_%RAND%.sh
Windows(cmd) : C:/windows/temp/terraform_%RAND%.cmd
Windows(PowerShell) : C:/windows/temp/terraform_%RAND%.ps1

 

  • 베스천 호스트를 통해 연결하는 경우 관련 인수를 지원

인수 설명 기본값
bastion_host 설정하게 되면 베스천 호스트 연결이 활성화되며, 
연결 대상 호스트를 지정
 
bastion_host_key 호스트 연결을 위한 공개키  
bastion_port 베스천 호스트에 연결할 포트 port 인수 값
bastion_user 베스천 호스트에 연결할 사용자 user 인수 값
bastion_password 베스천 호스트 연결에 사용할 비밀번호 password 인수 값
bastion_private_key 베스천 호스트 연결에 사용할 SSH 키파일 private_key 인수 값
bastion_certificate 서명된 CA 인증서 내용으로 bastion_private_key와 함께 사용  

 

▶ file 프로비저너 : 테라폼을 실행하는 시스템에서 연결 대상으로 파일 또는 디렉터리를 복사하는 데 사용

  • 테라폼을 실행하는 시스템에서 연결 대상으로 파일 또는 디렉터리를 복사
  • 사용되는 인수
    - source : 소스 파일 또는 디렉터리로, 현재 작업 중인 디렉터리에 대한 상태 경로 또는 절대 경로 지정 가능(content와 함께 사용할 수 없음)
    - content : 연결 대상에 복사할 내용을 정의, 대상이 디렉터리인 경우 tf-file-content 파일이 생성되고, 파일인 경우 해당 파일에 내용이 기록. source와 함께 사용 불가능
    - destination : 필수 항목으로 항상 절대 경로로 지정되어야 하며, 파일 또는 디렉터리
  • destination 지정 시 주의해야 할 점은 ssh 연결의 경우 대상 디렉터리가 존재해야 하며, winrm 연결은 디렉터리가 없는 경우 자동으로 생성
  • 디렉터리를 대상으로 하는 경우에는 source 경로 형태에 따라 동작에 차이 발생
  • destination이 /tmp인 경우 source가 디렉터리로 /foo 처럼 마지막에 /가 없는 경우 대상 디렉터리에 지정한 디렉터리가 업로드되어 연결된 시스템에 /tmp/foo 디렉터리가 업로드 된다.
  • source가 디렉터리로 /foo/처럼 마지막에 /가 포함되는 경우 source 디렉터리 내의 파이란 /tmp 디렉터리에 업로드
  • file 프로비저너 구성 예

main.tf

▶ remote-exec 프로비저너 : 원격지 환경에서 실행할 커맨드와 스크립트를 정의

  • AWS의 EC2 인스턴스를 생성하고 해당 VM에서 명령을 실행하고 패키지를 설치하는 등의 동작을 의미
  • 사용하는 인수는 다음과 같고 각 인수는 서로 배타적
    - inline : 명령에 대한 목록으로 [] 블록 내에 "" 로 묶인 다수의 명령을 , 로 구분해 구성
    - script : 로컬의 스크립트 경로를 넣고 원격에 복사해 실행
    - scripts : 로컬의 스크립트 경로의 목록으로 [] 블록 내에 " "로 묶인 다수의 스크립트 경로를, 로 구분해 구성
  • script 또는 scripts의 대상 스크립트 실행에 필요한 인수는 관련 구성에서 선언할 수 없으므로 필요할 때 file 프로바이더로 해당 스크립트를 업로드하고 inline 인수를 활용해 스크립트에 인수를 추가
  • 구성 예 - 만들고 나서 ec2 인스턴스에 연결하고 나서 프로비저너 동작 (file 복사 > script 파일을 실행 순서)

null_resource와 terraform_data

: 테라폼 1.4버전이 릴리즈되면서 기존 null_resource 리소스를 대체하는 terraform_data 리소스가 추가

 

▶ null_resource : 아무 작업도 수행하지 않는 리소스를 구현

  • 이런 리소스가 필요한 이유는??
    테라폼 프로비저닝 동작을 설계하면서 사용자가 의도적으로 프로비저닝하는 동작을 조율해야 하는 상황이 발생하여, 프로바이더가 제공하는 리소스 수명주기 관리만으로는 이를 해겨하기 어렵기 때문
  • 주로 사용되는 시나리오
    - 프로비저닝 수행 과정에서 명령어 실행
    - 프로비저너와 함께 사용
    - 모듈, 반복문, 데이터 소스, 로컬 변수와 함께 사용
    - 출력을 위한 데이터 가공
  • 예를 들어 다음의 상황을 가정
    - AWS EC2 인스턴스를 프로비저닝하면서 웹서비스를 실행시키고 싶다
    - 웹서비스 설정에는 노출되어야 하는 고정된 외부 IP가 포함된 구성이 필요. 따라서 aws_eip 리소스 생성이 필요
  • AWS EC2 인스턴스를 프로비저닝하기 위해 aws_instance 리소스 구성 시 앞서 확인한 프로비저너를 활용하여 웹서비스를 실행
  • 실습

terraform plan 시 에러 발생

  • main.tf 파일 내용 수정 : 둘 중 하나의 실행 시점을 한 단계 뒤로 미뤄야 함
    - 이런 경우 실행에 간격을 추가하여 실제 리소스와는 무관한 동작을 수행하기 위해 null_resource 활용
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_security_group" "instance" {
  name = "t101sg"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

}

resource "aws_instance" "example" {
  ami                    = "ami-0c9c942bd7bf113a2"
  instance_type          = "t2.micro"
  subnet_id              = "subnet-dbc571b0"
  private_ip             = "172.31.0.100"
  key_name               = "kp-gasida" # 각자 자신의 EC2 SSH Keypair 이름 지정
  vpc_security_group_ids = [aws_security_group.instance.id]

  user_data = <<-EOF
              #!/bin/bash
              echo "Hello, T101 Study" > index.html
              nohup busybox httpd -f -p 80 &
              EOF

  tags = {
    Name = "Single-WebSrv"
  }

}

resource "aws_eip" "myeip" {
  #vpc = true
  instance = aws_instance.example.id
  associate_with_private_ip = "172.31.0.100"
}

resource "null_resource" "echomyeip" {
  provisioner "remote-exec" {
    connection {
      host = aws_eip.myeip.public_ip
      type = "ssh"
      user = "ubuntu"
      private_key =  file("/Users/gasida/.ssh/kp-gasida.pem") # 각자 자신의 EC2 SSH Keypair 파일 위치 지정
      #password = "qwe123"
    }
    inline = [
      "echo ${aws_eip.myeip.public_ip}"
      ]
  }
}

output "public_ip" {
  value       = aws_instance.example.public_ip
  description = "The public IP of the Instance"
}

output "eip" {
  value       = aws_eip.myeip.public_ip
  description = "The EIP of the Instance"
}

 

  • null_resource는 정의된 속성이 'id'가 전부이므로, 선언된 내부의 구성이 변경되더라도 새로운 Plan 과정에서 실행 계획에 포함되지 못함
  • 따라서 사용자가 null_resource에 정의된 내용을 강제로 다시 실행하기 위한 인수로 trigger가 제공
  • trigger는 임의의 string 형태의 map 데이터를 정의하는데, 정의된 값이 변경되면 null_resource 내부에 정의된 행위를 다시 실행
  • trigger 정의와 동작 에제
resource "null_resource" "foo" {
  triggers = {
    ec2_id = aws_instance.bar.id # instance의 id가 변경되는 경우 재실행
  }
  ...생략...
}

resource "null_resource" "bar" {
  triggers = {
    ec2_id = time() # 테라폼으로 실행 계획을 생성할 떄마다 재실행
  }
  ...생략...
}

 

▶ terraform_data

  • 자체적으로 아무것도 수행하지 않지만 null_resource는 별도의 프로바이더 구성이 필요하다는 점과 비교하여 추가 프로바이더 없이 테라폼 자체에 포함된 기본 수명주기 관리자가 제공된다는 것이 장점
  • 사용 시나리오는 null_resource와 동일하며 강제 재실행을 위한 trigger_replace와 상태 저장을 위한 input 인수와 input에 저장된 값을 출력하는 output 속성이 제공
  • triggers_replace에 정의되는 값이 기존 map 형태에서 tuple로 변경되어 쓰임이 더 간단
  • terraform_data 리소스의 trigger_replace 정의와 동작 예제
resource "aws_instance" "web" {
  # ...
}

resource "aws_instance" "database" {
  # ...
}

# A use-case for terraform_data is as a do-nothing container
# for arbitrary actions taken by a provisioner.
resource "terraform_data" "bootstrap" {
  triggers_replace = [
    aws_instance.web.id,
    aws_instance.database.id
  ]

  provisioner "local-exec" {
    command = "bootstrap-hosts.sh"
  }
}
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 블록을 사용
  • 'moved' 라는 단어가 의미하는 것처럼 테라폼 State에서 옮겨진 대상의 이전 주소와 새 주소를 알리는 역할을 수행
  • 실습

main.tf

 

배포 후 결과값

  • main.tf 파일 내용 변경 : local_file의 프로비저닝 결과를 유지한 채 이름을 변경하기 위해 moved 블록 활용

main.tf
배포 후 terraform.tfstate 값 확인

 

  • main.tf 파일 내용 변경 : moved 블록을 삭제해서 리팩터링 완료
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
}

 

CLI를 위한 시스템 환경 변수

 

▶ 테라폼은 환경 변수를 통해 실행 방식과 출력 내용에 대한 옵션 조절 가능

  • 시스템 환경 변수를 설정하면, 영구적으로 로컬 환경에 적용되는 옵션이나 별도 서버 환경에서 실행하기 위한 옵션 부여
  • 이를 통해 로컬 작업 환경과 다른 환경 구성에서만 사용될 특정 옵션 적용
Mac/리눅스/유닉스: export <환경 변수 이름>=<값>
Windows CMD: set <환경 변수 이름>=<값>
Windows PowerShell: $Env:<환경 변수 이름>='<값>'

 

  • trace, debug, info, warn, error, off를 설정할 수 있고 관련 환경 변수가 없는 경우 off와 동일
  • 디버깅을 위한 로그 관련 환경 변수 설명
    - TF_LOG : 로깅 레벨 지정 또는 해제
    - TF_LOG_PATH : 로그 출력 파일 위치 지정
    - TF_LOG_CORE : TF_LOG와 별도로 테라폼 자체 코어에 대한 로깅 레벨 지정 또는 해제
    - TF_LOG_PROVIDER : TF_LOG와 별도로 테라폼에서 사용하는 프로바이더에 대한 로깅 레벨 지정 또는 해제
  • TF_VAR_name : TF_VAR_<변수 이름>을 사용하면 입력 시 또는 default로 선언된 변수 값을 대체
  • TF_DATA_DIR : State 저장 백엔드 설정과 같은 작업 디렉터리별 데이터를 보관하는 위치를 지정
    - 이 데이터는 .terraform 디렉터리 위치에 기록되지만 TF_DATA_DIR에 경로가 정의되면 기본 경로를 대체
    - 실행 시마다 일관되게 적용될 수 있도록 설정 필요
    - 이미 terraform init이 수행된 상태에서 TF_DATA_DIR로 경로를 재지정하고 실행하는 경우 플러그인 설치가 필요하다는 메시지 출력 확인 가능
TF_DATA_DIR=./.terraform_tmp terraform plan
Error: Required plugins anr not installed

* 참고 링크

https://developer.hashicorp.com/terraform/language/functions

 

Functions - Configuration Language | Terraform | HashiCorp Developer

An introduction to the built-in functions that you can use to transform and combine values in expressions.

developer.hashicorp.com

https://developer.hashicorp.com/terraform/language/resources/provisioners/syntax

 

Provisioners | Terraform | HashiCorp Developer

Provisioners run scripts on a local or remote machine during resource creation or destruction. Learn how to declare provisioners in a configuration.

developer.hashicorp.com

 

https://developer.hashicorp.com/terraform/language/resources/provisioners/local-exec

 

Provisioner: local-exec | Terraform | HashiCorp Developer

The `local-exec` provisioner invokes a local executable after a resource is created. This invokes a process on the machine running Terraform, not on the resource. See the `remote-exec` provisioner to run commands on the resource.

developer.hashicorp.com

https://developer.hashicorp.com/terraform/language/resources/provisioners/remote-exec

 

Provisioner: remote-exec | Terraform | HashiCorp Developer

The `remote-exec` provisioner invokes a script on a remote resource after it is created. This can be used to run a configuration management tool, bootstrap into a cluster, etc. To invoke a local process, see the `local-exec` provisioner instead. The `remot

developer.hashicorp.com

https://developer.hashicorp.com/terraform/language/resources/provisioners/connection

 

Provisioner Connection Settings | Terraform | HashiCorp Developer

The connection block allows you to manage provisioner connection defaults for SSH and WinRM.

developer.hashicorp.com

https://developer.hashicorp.com/terraform/language/resources/provisioners/connection#connecting-through-a-bastion-host-with-ssh

 

Provisioner Connection Settings | Terraform | HashiCorp Developer

The connection block allows you to manage provisioner connection defaults for SSH and WinRM.

developer.hashicorp.com

https://developer.hashicorp.com/terraform/language/resources/provisioners/file

 

Provisioner: file | Terraform | HashiCorp Developer

The `file` provisioner is used to copy files or directories from the machine executing Terraform to the newly created resource. The `file` provisioner supports both `ssh` and `winrm` type connections.

developer.hashicorp.com

https://developer.hashicorp.com/terraform/language/resources/provisioners/remote-exec

 

Provisioner: remote-exec | Terraform | HashiCorp Developer

The `remote-exec` provisioner invokes a script on a remote resource after it is created. This can be used to run a configuration management tool, bootstrap into a cluster, etc. To invoke a local process, see the `local-exec` provisioner instead. The `remot

developer.hashicorp.com

https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource

 

Terraform Registry

 

registry.terraform.io

https://developer.hashicorp.com/terraform/language/modules/develop/refactoring#moved-block-syntax

 

Refactoring | Terraform | HashiCorp Developer

How to make backward-compatible changes to modules already in use.

developer.hashicorp.com