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
'Terraform > Terraform 101 Study' 카테고리의 다른 글
7주차 2편 테라폼으로 AWS EKS 배포 - EKS Workshop (0) | 2024.07.28 |
---|---|
7주차 1편 테라폼으로 AWS EKS 배포 - EKS Blueprints for Terraform (0) | 2024.07.28 |
5주차 2편 테라폼 Runner (1) | 2024.07.14 |
5주차 1편 테라폼 Module (1) | 2024.07.14 |