본문 바로가기
Terraform/Terraform 101 Study

8주차 1편 테라폼 OpenTofu

by 개발자 영만 2024. 8. 4.

OpenTofu 소개

OpenTofu: Terraform의 오픈 소스 포크

  • 오픈 소스 인프라 관리 도구 OpenTofu는 HashiCorp의 Terraform에서 파생된 커뮤니티 주도 프로젝트입니다.
  • 2023년 8월, HashiCorp는 Terraform의 라이선스를 Mozilla Public License(MPL)에서 비오픈 소스 라이선스인 Business Source License(BUSL)로 변경했습니다 .
  • 이로 인해 Terraform의 오픈 소스 포크 프로젝트인 OpenTF가 탄생했으며, 이는 곧 OpenTofu로 이름을 변경했습니다 .

OpenTofu의 목표와 기능

  • OpenTofu는 클라우드 및 온프레미스 리소스를 사람이 읽을 수 있는 구성 파일에 정의하고, 이를 통해 인프라의 프로비저닝 및 관리를 일관된 워크플로로 수행할 수 있도록 돕습니다 . 주요 기능은 다음과 같습니다:
    • 쓰기(Write): 여러 클라우드 공급자와 서비스에 걸쳐 리소스를 정의합니다.
    • 계획(Plan): OpenTofu는 실행 계획을 생성하여 어떤 인프라가 생성, 업데이트 또는 삭제될지를 설명합니다.
    • 적용(Apply): 제안된 작업을 올바른 순서로 수행하여 인프라를 구성합니다 .

OpenTofu의 작동 원리

  • OpenTofu는 API를 통해 클라우드 플랫폼 및 기타 서비스에서 리소스를 생성하고 관리합니다.
  • OpenTofu 커뮤니티는 이미 수천 개의 공급자를 작성하여 다양한 유형의 리소스와 서비스를 관리할 수 있게 했습니다.

OpenTofu와 Terraform의 차이점

  • OpenTofu는 기술적으로 Terraform과 매우 유사하지만, 오픈 소스로서 단일 회사가 아닌 협력적인 방식으로 프로젝트가 진행된다는 점에서 차별화됩니다.
  • 현재 OpenTofu 1.6.x는 Terraform 1.6.x와 기능적으로 매우 유사하며, 앞으로는 기능 세트가 달라질 예정입니다 .

마이그레이션과 호환성

  • OpenTofu는 Terraform 버전 1.5.x 및 대부분의 1.6.x와 호환되며, 기존 상태 파일도 지원합니다.
  • 현재 Terraform 공급자와 함께 작동하지만 별도의 레지스트리를 사용합니다.

 

OpenTofu 설치

Tenv 소개

  • Tenv는 OpenTofu, Terraform, Terragrunt, Atmos의 버전 관리를 위한 도구입니다. 다양한 버전 간 전환을 쉽게 할 수 있으며, 사용자가 필요로 하는 버전을 손쉽게 관리할 수 있도록 도와줍니다.
  • Tenv 주요 기능
    • 다양한 버전 관리: OpenTofu, Terraform, Terragrunt, Atmos의 다양한 버전을 쉽게 전환할 수 있습니다.
    • Semver 2.0.0 호환성: go-version을 사용하여 Semver 2.0.0 호환 버전 관리를 지원하며, HCL 파서를 사용하여 필요한 버전 제약 조건을 추출합니다.
    • 서명 검증: cosign과 gopenpgp를 사용하여 서명을 검증할 수 있습니다.
    • 직관적인 설치: Homebrew 및 수동 설치 옵션을 통해 쉽게 설치할 수 있습니다.
  • 도구 및 명령어 목록
tool (alias) env vars description
tofu (opentofu) TOFUENV_ OpenTofu
tf (terraform) TFENV_ Terraform
tg (terragrunt) TG_ Terragrunt
at (atmos) ATMOS_ Atmos

Tenv 설치 확인

# Tenv 버전 확인
tenv -v

# Tenv 도움말 확인
tenv -h

# Tofu 관련 명령어 확인
tenv tofu -h

# Tenv 경로 확인
which tenv

OpenTofu 설치 및 확인

# Tofu 관련 명령어 확인
tenv tofu -h

# 사용할 수 있는 Tofu 버전 목록 확인
tenv tofu list
tenv tofu list-remote

# 특정 버전 설치 (예: 1.7.3 버전)
tenv tofu install 1.7.3

# 설치된 버전 목록 확인
tenv tofu list

# 특정 버전 사용 설정
tenv tofu use 1.7.3

# 현재 사용 중인 버전 감지
tenv tofu detect

# 설치된 Tofu 확인
tofu -h
tofu version

 

OpenTofu 1.7.0

[실습] Provider-defined functions

  • main.tf 파일 작성
terraform {
  required_providers {
    corefunc = {
      source = "northwood-labs/corefunc"
      version = "1.4.0"
    }
  }
}

provider "corefunc" {
}

output "test" {
  value = provider::corefunc::str_snake("Hello world!")
  # Prints: hello_world
}
  • 실행 후 확인
# 초기화
tofu init

# 프로바이더 정보 확인
tree .terraform

# Plan
tofu plan

# Apply
tofu apply

# Output
tofu output

# tfstate 파일 확인
cat terraform.tfstate | jq

  • main.tf 파일 수정 - main.tf 파일을 수정하여 문자열을 camelCase 형식으로 변환하도록 합니다.
terraform {
  required_providers {
    corefunc = {
      source = "northwood-labs/corefunc"
      version = "1.4.0"
    }
  }
}

provider "corefunc" {
}

output "test" {
  value = provider::corefunc::str_camel("Hello world!")
  # Prints: hello_world
}
  • 실행 후 확인
# Output
tofu output

# Apply
tofu apply -auto-approve

# tfstate 파일 확인
ls -l terraform.tfstate*

[실습] Loopable import blocks

Import 블록

  • import 블록을 사용하여 기존 인프라 리소스를 OpenTofu로 가져와서 OpenTofu에서 관리할 수 있습니다.
  • import 블록은 모든 OpenTofu 구성 파일에 추가할 수 있습니다. 일반적인 패턴은 imports.tf 파일을 생성하거나 resource 블록 옆에 import 블록을 배치하는 것입니다.
import {
  to = aws_instance.example
  id = "i-abcd1234"
}

resource "aws_instance" "example" {
  name = "hashi"
  # (other resource arguments...)
}
  • import 블록의 인수:
    • to: 상태 파일에서 이 리소스의 인스턴스 주소
    • id: 리소스의 import ID
    • provider (선택 사항): 사용자 정의 리소스 공급자
    • for_each (선택 사항): 맵 또는 세트를 반복하여 여러 리소스를 가져오기

Importing multiple resources

  • for_each 표현식을 사용하여 하나의 import 블록으로 여러 리소스를 가져올 수 있습니다.
  • 이 표현식은 세트, 튜플 또는 맵을 허용하며, 개별 요소에 접근하기 위해 each.key 및 each.value 변수를 제공합니다.

실습 따라하기

  • main.tf 파일 작성
data "aws_ami" "ubuntu" {
    most_recent = true

    filter {
        name   = "name"
        values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
    }

    filter {
        name   = "virtualization-type"
        values = ["hvm"]
    }

    owners = ["099720109477"] # Canonical
}

variable "instance_tags" {
  type = list(string)
  default = ["web", "app"]
}

resource "aws_instance" "this" {
  count = length(var.instance_tags)
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = "t3.micro"

  tags = {
    Name = var.instance_tags[count.index]
  }
}
  • 실행 후 확인
# 초기화
tofu init

# 프로바이더 정보 확인
tree .terraform
                
# Apply
tofu apply -auto-approve

# EC2 확인
while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text ; echo "------------------------------" ; sleep 1; done

# 확인
tofu state list
tofu state ls
echo "data.aws_ami.ubuntu" | tofu console
tofu show

# tfstate 파일 확인
cat terraform.tfstate | jq

  • 문제 상황 재연 : tfstate 파일 삭제
# tfstate 파일 삭제
rm -rf .terraform* terraform.tfstate*
tree

# EC2 확인: ID 메모
aws ec2 describe-instances --query 'Reservations[*].Instances[*].{InstanceID:InstanceId,PublicIP:PublicIpAddress,Name:Tags[?Key==`Name`]|[0].Value}' --output json | jq -r '.[][] | "\(.InstanceID)\t\(.PublicIP)\t\(.Name)"'

  • main.tf 파일 수정 - ami-id 에 바로 위 ‘EC2 확인’ 에서 출력된 ID 를 입력
data "aws_ami" "ubuntu" {
    most_recent = true

    filter {
        name   = "name"
        values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
    }

    filter {
        name   = "virtualization-type"
        values = ["hvm"]
    }

    owners = ["099720109477"] # Canonical
}

variable "instance_ids" {
  type = list(string)
  default = ["변경", "변경"]
}

variable "instance_tags" {
  type = list(string)
  default = ["web", "app"]
}

resource "aws_instance" "this" {
  count = length(var.instance_tags)
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = "t3.micro"

  tags = {
    Name = var.instance_tags[count.index]
  }
}

import {
  for_each = { for idx, item in var.instance_ids : idx => item }
  to = aws_instance.this[tonumber(each.key)]
  id = each.value
}
  • 실행 후 확인
# 초기화
tofu init -json
tree .terraform

# Apply
tofu apply -auto-approve

# 확인
tofu state ls
tofu show

# tfstate 파일 확인
cat terraform.tfstate | jq

[실습] State file encryption - Local

  • OpenTofu는 로컬 스토리지와 백엔드를 사용할 때 모두 상태 파일과 계획 파일을 암호화하는 것을 지원합니다. 또한 terraform_remote_state 데이터 소스와 함께 암호화를 사용할 수도 있습니다.
  • 기본 코드 예시
terraform {
  encryption {
    key_provider "some_key_provider" "some_name" {
      # Key provider options here
    }

    method "some_method" "some_method_name" {
      # Method options here
      keys = key_provider.some_key_provider.some_name
    }

    state {
      # Encryption/decryption for state data
      method = method.some_method.some_method_name
    }

    plan {
      # Encryption/decryption for plan data
      method = method.some_method.some_method_name
    }

    remote_state_data_sources {
      # See below
    }
  }
}
  • key and method rollover : 신규 암호화 설정 변경 시 문제 발생 시 자동으로 이전 암호화 설정으로 전환 적용 (fallback)
terraform {
  encryption {
    # Methods and key providers here.

    state {
      method = method.some_method.new_method
      fallback {
        method = method.some_method.old_method
      }
    }

    plan {
      method = method.some_method.new_method
      fallback {
        method = method.some_method.old_method
      }
    }
  }
}
  • 신규 프로젝트 초기 설정
    • 신규 프로젝트에서 상태 파일이 없는 경우, 다음 예시를 사용하여 암호화를 설정할 수 있습니다.
terraform {
  encryption {
    ## Step 1: Add the desired key provider:
    key_provider "pbkdf2" "mykey" {
      # Change this to be at least 16 characters long:
      passphrase = "changeme!"
    }
    ## Step 2: Set up your encryption method:
    method "aes_gcm" "new_method" {
      keys = key_provider.pbkdf2.mykey
    }

    state {
      ## Step 3: Link the desired encryption method:
      method = method.aes_gcm.new_method

      ## Step 4: Run "tofu apply".

      ## Step 5: Consider adding the "enforced" option:
      # enforced = true
    }

    ## Step 6: Repeat steps 3-5 for plan{} if needed.
  }
}
  • 기존 프로젝트 초기 설정
    • 기존 프로젝트에서 암호화를 처음 구성할 때 상태 및 계획 파일은 암호화되지 않습니다. OpenTofu는 기본적으로 이를 읽는 것을 거부합니다. 암호화되지 않은 데이터 읽기를 활성화하려면 다음 unencrypted 방법을 지정해야 합니다.
terraform {
  encryption {
    ## Step 1: Add the unencrypted method:
    method "unencrypted" "migrate" {}

    ## Step 2: Add the desired key provider:
    key_provider "pbkdf2" "mykey" {
      # Change this to be at least 16 characters long:
      passphrase = "changeme!"
    }

    ## Step 3: Add the desired encryption method:
    method "aes_gcm" "new_method" {
      keys = key_provider.pbkdf2.mykey
    }

    state {
      ## Step 4: Link the desired encryption method:
      method = method.aes_gcm.new_method

      ## Step 5: Add the "fallback" block referencing the
      ## "unencrypted" method.
      fallback {
        method = method.unencrypted.migrate
      }

      ## Step 6: Run "tofu apply".

      ## Step 7: Remove the "fallback" block above and
      ## consider adding the "enforced" option:
      # enforced = true
    }

    ## Step 8: Repeat steps 4-8 for plan{} if needed.
  }
}
  • Rolling back encryption : 암호화에서 평문으로 마이그레이션
    • unencrypted를 사용하여 암호화되지 않은 상태 및 계획 파일로 마이그레이션할 수 있습니다.
terraform {
  encryption {
    ## Step 1: Leave the original encryption method unchanged:
    method "some_method" "old_method" {
      ## Parameters for the old method here.
    }

    # Step 2: Add the unencrypted method here:
    method "unencrypted" "migrate" {}

    state {
      ## Step 3: Disable or remove the "enforced" option:
      enforced = false

      ## Step 4: Move the original encryption method into the "fallback" block:
      fallback {
        method = method.some_method.old_method
      }

      ## Step 5: Reference the unencrypted method as your primary "encryption" method.
      method = method.unencrypted.migrate
    }

    ## Step 6: Run "tofu apply".

    ## Step 7: Remove the "state" block once the migration is complete.

    ## Step 8: Repeat steps 3-7 for plan{} if needed.
  }
}
  • Key providers
    • PBKDF2 키 제공자는 AES-GCM과 같은 암호화 방법에 대한 키를 생성하기 위해 긴 패스프레이즈를 사용할 수 있습니다.
terraform {
  encryption {
    key_provider "pbkdf2" "foo" {
      # Specify a long / complex passphrase (min. 16 characters)
      passphrase = "correct-horse-battery-staple"

      # Adjust the key length to the encryption method (default: 32)
      key_length = 32

      # Specify the number of iterations (min. 200,000, default: 600,000)
      iterations = 600000

      # Specify the salt length in bytes (default: 32)
      salt_length = 32

      # Specify the hash function (sha256 or sha512, default: sha512)
      hash_function = "sha512"
    }
  }
}
  • AWS
    • AWS 키 제공자는 AWS KMS로 키를 생성할 수 있습니다.
terraform {
  encryption {
    key_provider "aws_kms" "basic" {
      kms_key_id = "a4f791e1-0d46-4c8e-b489-917e0bec05ef"
      region = "us-east-1"
      key_spec = "AES_256"
    }
  }
}

실습 따라하기 

  • backend.tf 파일 작성
terraform {
  encryption {
    key_provider "pbkdf2" "my_passphrase" {
      ## Enter a passphrase here:
      passphrase = "ChangeIt_123abcd"
    }

    method "aes_gcm" "my_method" {
      keys = key_provider.pbkdf2.my_passphrase
    }

    ## Remove this after the migration:
    method "unencrypted" "migration" {
    }

    state {
      method = method.aes_gcm.my_method

      ## Remove the fallback block after migration:
      fallback{
        method = method.unencrypted.migration
      }
      ## Enable this after migration:
      #enforced = true
    }
  }
}
  • 실행 후 tfstate 파일 암호화 확인
# 초기화
tofu init -json | jq
tree .terraform

# import 실행
tofu apply -auto-approve
tofu state list
tofu show

# tfstate 파일 확인
cat terraform.tfstate | jq

  • 강력한 보안 정책 적용. 암호화되지 않은 데이터 저장 방지
    • 환경 변수가 저장되는 것을 방지하려면 다음 구성을 추가합니다.
terraform {
    encryption {
        state {
            enforced = true
        }
        plan {
            enforced = true
        }
    }
}
  • backend.tf 파일 수정: 주석 제거
terraform {
  encryption {
    key_provider "pbkdf2" "my_passphrase" {
      ## Enter a passphrase here:
      passphrase = "ChangeIt_123abcd"
    }

    method "aes_gcm" "my_method" {
      keys = key_provider.pbkdf2.my_passphrase
    }

    ## Remove this after the migration:
    method "unencrypted" "migration" {
    }

    state {
      method = method.aes_gcm.my_method

      ## Remove the fallback block after migration:
      fallback{
        method = method.unencrypted.migration
      }
      # Enable this after migration:
      enforced = true
    }
  }
}
  • 실행 후 확인
# Apply
tofu apply -auto-approve

# tfstate 파일 확인
cat terraform.tfstate | jq

  • Rolling back encryption : 암호화에서 평문으로 마이그레이션
  • backend.tf 파일 수정
terraform {
  encryption {
    key_provider "pbkdf2" "my_passphrase" {
      ## Enter a passphrase here:
      passphrase = "ChangeIt_123abcd"
    }

    method "aes_gcm" "my_method" {
      keys = key_provider.pbkdf2.my_passphrase
    }

    ## Remove this after the migration:
    method "unencrypted" "migration" {
    }

    state {
      method = method.unencrypted.migration

      ## Remove the fallback block after migration:
      fallback{
        method = method.aes_gcm.my_method
      }
      # Enable this after migration:
      enforced = false
    }
  }
}
  • 실행 후 확인
# Apply
tofu apply -auto-approve

# tfstate 파일 확인
cat terraform.tfstate | jq

[실습] State file encryption - AWS KMS

  • [사전 준비] AWS S3 버킷 생성 : Backend State 저장용도
aws s3 mb s3://<각자 유일한 S3 버킷명 이름> --region ap-northeast-2
aws s3 mb s3://ihwoo-t101 --region ap-northeast-2

# 확인
aws s3 ls
  • AWS KMS 소개
    • 암호화는 키를 사용해 평문을 암호문으로 변환하는 프로세스입니다.
    • 동일한 키를 사용해 암호문을 평문으로 변환할 수 있는데, 이를 복호화라고 합니다.
    • AWS 키 관리 서비스(KMS)는 공유 하드웨어 보안 모듈(HSM)을 사용하여 암호화 키를 생성하고 관리할 수 있게 도와줍니다.
    • CloudHSM은 AWS 내에서 암호화 키를 관리할 수 있지만 보안 강화를 위해 전용 HSM을 사용할 수 있는 서비스입니다.
    • 용어 변경 참고: 기존 Customer Master Key (CMK) → AWS KMS key 혹은 KMS key로 변경되었습니다.
  • [사전 준비] AWS KMS 생성 및 설정  : 대칭 키 생성 후 평문 파일을 암호화 및 복호화
# 키 생성
CREATE_KEY_JSON=$(aws kms create-key --description "my text encrypt descript demo")
echo $CREATE_KEY_JSON | jq

# 키 ID확인
KEY_ID=$(echo $CREATE_KEY_JSON | jq -r ".KeyMetadata.KeyId")
echo $KEY_ID

# 키 alias 생성
export ALIAS_SUFFIX=<각자 닉네임>
export ALIAS_SUFFIX=ihwoo
aws kms create-alias --alias-name alias/$ALIAS_SUFFIX --target-key-id $KEY_ID

# 생성한 별칭 확인
aws kms list-aliases
aws kms list-aliases --query "Aliases[?AliasName=='alias/<각자 닉네임>'].TargetKeyId" --output text
aws kms list-aliases --query "Aliases[?AliasName=='alias/ihwoo'].TargetKeyId" --output text

  • CMK로 평문을 암호화 및 복호화
# 평문 파일 생성
echo "Hello 123123" > secrect.txt

# 암호화
aws kms encrypt --key-id alias/$ALIAS_SUFFIX --cli-binary-format raw-in-base64-out --plaintext file://secrect.txt --output text --query CiphertextBlob | base64 --decode > secrect.txt.encrypted

# 암호문 확인
cat secrect.txt.encrypted

# 복호화
aws kms decrypt --ciphertext-blob fileb://secrect.txt.encrypted --output text --query Plaintext | base64 --decode
# Hello 123123
  • backend.tf 파일 수정
terraform {
  backend "s3" {
    bucket = "ihwoo-t101" # 각자 자신의 S3 버킷명
    key = "terraform.tfstate"
    region = "ap-northeast-2"
    encrypt = true
  }

  encryption {
    key_provider "aws_kms" "kms" {
      kms_key_id = "xxxxxxxxxx-xxxxxxxxxxxx-xxxx-xxxxxxxxxxxx" # 각자 자신의 KMS ID
      region = "ap-northeast-2"
      key_spec = "AES_256"
    }

    method "aes_gcm" "my_method" {
      keys = key_provider.aws_kms.kms
    }

    ## Remove this after the migration:
    method "unencrypted" "migration" {}

    state {
      method = method.aes_gcm.my_method

      ## Remove the fallback block after migration:
      fallback {
        method = method.unencrypted.migration
      }
      # Enable this after migration:
      # enforced = false
    }
  }
}
  • 실행 및 확인
# 로컬 tfstate 파일 제거
rm -rf .terraform* terraform.tfstate*
tree

# 초기화
tofu init
tree .terraform
cat .terraform/terraform.tfstate | jq

# import 실행
tofu apply -auto-approve
tofu state list
tofu show
ls -l terraform.tfstate*

# 원격 백엔드에 저장된 tfstate 파일 확인 및 로컬에 다운로드
aws s3 ls s3://<각자 자신의 S3 버킷명> --recursive
aws s3 cp s3://<각자 자신의 S3 버킷명>/terraform.tfstate .

aws s3 ls s3://ihwoo-t101 --recursive
aws s3 cp s3://ihwoo-t101/terraform.tfstate .

# 다운받은 tfstate 파일 확인
cat terraform.tfstate | jq

[실습] Removed Block

  • Removed 블록은 인프라에서 리소스를 유지하면서 상태 파일에서 리소스를 제거할 수 있게 합니다.
  • 먼저 리소스를 생성한 후, removed 블록을 사용하여 상태 파일에서 해당 리소스를 제거합니다.

실습 따라하기

  • main.tf 파일 작성
data "aws_ami" "ubuntu" {
    most_recent = true

    filter {
        name   = "name"
        values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
    }

    filter {
        name   = "virtualization-type"
        values = ["hvm"]
    }

    owners = ["099720109477"] # Canonical
}

variable "instance_ids" {
  type = list(string)
  default = ["i-0e2d4475790337a81", "i-00a4daebb71942280"] # 각자 자신의 EC2 ID를 기입 할 것
}

variable "instance_tags" {
  type = list(string)
  default = ["web", "app"]
}

resource "aws_instance" "this" {
  count = length(var.instance_tags)
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = "t3.micro"

  tags = {
    Name = var.instance_tags[count.index]
  }
}

import {
  for_each = { for idx, item in var.instance_ids : idx => item }
  to = aws_instance.this[tonumber(each.key)]
  id = each.value
}

resource "aws_ssm_parameter" "this" {
  count = length(var.instance_tags)
  name  = var.instance_tags[count.index]
  type  = "String"
  value = aws_instance.this[count.index].id
}
  • 실행 및 확인
# 초기화
tofu init
tree .terraform

# 2개 리소스는 import , 2개 리소스는 생성
tofu apply -auto-approve

# 상태 확인
tofu state ls
tofu show
tofu state show 'aws_ssm_parameter.this[0]'
tofu state show 'aws_ssm_parameter.this[1]'

# tfstate 파일 확인
cat terraform.tfstate | jq

# AWS SSM Parameter 정보 확인
aws ssm describe-parameters | jq
aws ssm get-parameter --name "web"
aws ssm get-parameter --name "web" --query "Parameter.Value" --output text
aws ssm get-parameter --name "app"
aws ssm get-parameter --name "app" --query "Parameter.Value" --output text

  • 이번 실습 목적 : 파라미터 스토어 리소스만 tfstate 에서 제거하고, AWS 상에는 유지 하게 설정
  • main.tf 파일 수정하여 리소스 제거
data "aws_ami" "ubuntu" {
    most_recent = true

    filter {
        name   = "name"
        values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
    }

    filter {
        name   = "virtualization-type"
        values = ["hvm"]
    }

    owners = ["099720109477"] # Canonical
}

variable "instance_ids" {
  type = list(string)
  default = ["i-0e2d4475790337a81", "i-00a4daebb71942280"]
}

variable "instance_tags" {
  type = list(string)
  default = ["web", "app"]
}

resource "aws_instance" "this" {
  count = length(var.instance_tags)
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = "t3.micro"

  tags = {
    Name = var.instance_tags[count.index]
  }
}

import {
  for_each = { for idx, item in var.instance_ids : idx => item }
  to = aws_instance.this[tonumber(each.key)]
  id = each.value
}

# resource "aws_ssm_parameter" "this" {
#   count = length(var.instance_tags)
#   name  = var.instance_tags[count.index]
#   type  = "String"
#   value = aws_instance.this[count.index].id
# }

removed {
  from = aws_ssm_parameter.this
}
  • 실행 및 확인
# Apply
tofu apply -auto-approve

# AWS SSM Parameter 정보 확인
aws ssm describe-parameters | jq

# 상태 확인
tofu state ls

# tfstate 파일 확인
cat terraform.tfstate | jq