Backend

  1. 해당 문서를 통해서 Terraform Backend 설정 확인

  2. S3 버킷 생성

    {
      export S3_BUCKET=terraform-state-$(tr -dc a-z0-9 </dev/urandom | head -c 8)
      aws s3api create-bucket --bucket $S3_BUCKET --region ap-northeast-2 \
      --create-bucket-configuration LocationConstraint=ap-northeast-2 \
      --no-cli-pager
    }
  3. S3 버킷에 Versioning 활성화

    aws s3api put-bucket-versioning --bucket $S3_BUCKET \
    --versioning-configuration Status=Enabled
  4. Versioning이 활성화 되었는지 확인

    aws s3api get-bucket-versioning --bucket $S3_BUCKET
  5. DynamoDB 테이블 생성

    {
      export DYNAMODB_TABLE=terraform-lock-$(tr -dc a-z0-9 </dev/urandom | head -c 4)
      aws dynamodb create-table \
      --table-name $DYNAMODB_TABLE \
      --attribute-definitions AttributeName=LockID,AttributeType=S \
      --key-schema AttributeName=LockID,KeyType=HASH \
      --billing-mode PAY_PER_REQUEST \
      --no-cli-pager
    }
  6. Terraform 코드를 저장할 디렉토리 생성

    cd ~/environment && mkdir terraform && cd terraform
  7. Terraform Backend 설정을 포함하는 파일 생성

    cat <<EOF | tee backend.tf
    terraform {
      backend "s3" {
        bucket         = "$S3_BUCKET"
        key            = "terraform.tfstate"
        region         = "ap-northeast-2"
        dynamodb_table = "$DYNAMODB_TABLE"
        encrypt        = true
      }
    }
    EOF
  8. Terraform Provider 설정을 포함하는 파일 생성

    cat <<EOF | tee provider.tf
    terraform {
      required_providers {
        aws = {
          source  = "hashicorp/aws"
          version = ">= 5.45.0"
        }
      }
    }
    EOF
  9. VPC를 생성하는 코드를 포함하는 파일 생성

    cat <<EOF | tee vpc.tf
    resource "aws_vpc" "this" {
      cidr_block = "10.10.0.0/16"
    }
    EOF
  10. Terraform 환경 구성

    terraform init
  11. 인프라 변경 사항 확인

    terraform plan
  12. 인프라 변경 사항 반영

    terraform apply --auto-approve
  13. tfstate 파일이 생성되었는지 확인

    ll
  14. S3 버킷에 tfstate 파일이 생성되었는지 확인

    aws s3 ls $S3_BUCKET
  15. S3 버킷에 저장된 tfstate 파일 다운로드

    aws s3 cp s3://$S3_BUCKET/terraform.tfstate s3.terraform.tfstate
  16. tfstate 파일 내용 확인

    cat s3.terraform.tfstate | jq
  17. Terraform을 통해서 tfstate를 확인하고 파일 형식으로 저장

    terraform state pull | tee pull.terraform.tfstate
  18. 위의 2개의 파일을 비교

    diff s3.terraform.tfstate pull.terraform.tfstate -y
  19. 의도적으로 딜레이를 발생시키는 리소스를 포함하는 파일 생성

    cat <<EOF | tee delay.tf
    resource "time_sleep" "wait_3_mins" {
      create_duration = "3m"
    }
    EOF
  20. 인프라 변경 사항 확인

    terraform plan
  21. Terraform 플러그인 설치

    terraform init
  22. 인프라 변경 사항 확인

    terraform plan
  23. DynamoDB 테이블 이름을 파일 형식으로 저장

    echo $DYNAMODB_TABLE > dynamodb.txt
  24. Dynamo에 저장된 레코드 확인

    aws dynamodb scan --table-name $(cat dynamodb.txt) --no-cli-pager
  25. 인프라 변경 사항 반영

    terraform apply --auto-approve
  26. 새로운 터미널을 열고 동일한 Terraform 코드 실행

    cd ~/environment/terraform && terraform apply --auto-approve
  27. Dynamo에 저장된 레코드 확인

    aws dynamodb scan --table-name $(cat dynamodb.txt) --no-cli-pager
  28. Terraform 로그 레벨을 올리고 다시 Terraform 코드 실행

    TF_LOG=DEBUG terraform apply --auto-approve
  29. 기존 터미널로 돌아와서 배포가 완료될때까지 대기

  30. EC2 및 RDS 인스턴스를 생성하는 코드 블록을 추가

    cat <<EOF | tee rds.tf
    resource "aws_instance" "this" {
      ami = "ami-0c031a79ffb01a803"
      instance_type = "t3.micro"
      
      tags = {
        Name = "terraform-ec2-test"
      }
    }
    
    resource "aws_db_instance" "this" {
      identifier          = "terraform-rds-test"
      instance_class      = "db.t3.micro"
      allocated_storage   = 20
      engine              = "mysql"
      engine_version      = "8.0"
      username            = "admin"
      password            = "asdf!234"
      skip_final_snapshot = true
    }
    EOF
  31. 인프라 변경 사항 확인

    terraform plan
  32. AWS 임시 토큰을 발급하고 해당 임시 토큰을 사용해서 인프라 변경 사항 반영

    {
      response=$(aws sts get-session-token --duration-seconds 900)
      
      AWS_ACCESS_KEY_ID=$(echo "${response}" | jq --raw-output ".Credentials[\"AccessKeyId\"]")
      AWS_SECRET_ACCESS_KEY=$(echo "${response}" | jq --raw-output ".Credentials[\"SecretAccessKey\"]")
      AWS_SESSION_TOKEN=$(echo "${response}" | jq --raw-output ".Credentials[\"SessionToken\"]")
    
      export AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID}"
      export AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY}"
      export AWS_SESSION_TOKEN="${AWS_SESSION_TOKEN}"
      export AWS_DEFAULT_REGION=ap-northeast-2
    
      for i in {80..1};do echo $(($i*10)) && sleep 10; done
    
      terraform apply --auto-approve
    }
  33. 인프라 변경 사항 확인

    terraform plan
  34. 환경변수로 지정한 AWS 임시 자격증명 제거

    {
      unset AWS_ACCESS_KEY_ID
      unset AWS_SECRET_ACCESS_KEY
      unset AWS_SESSION_TOKEN
    }
  35. 인프라 변경 사항 확인

    terraform plan
  36. LockID 확인

    {
      export LOCK_ID=$(aws dynamodb get-item --table-name $DYNAMODB_TABLE \
      --key '{"LockID": {"S":"'$S3_BUCKET'/terraform.tfstate"}}' \
      --query 'Item.Info.S' | jq -r 'fromjson | .ID')
      echo $LOCK_ID
    }
  37. Lock 해제

    terraform force-unlock $LOCK_ID
  38. 인프라 변경 사항 확인

    terraform plan
  39. 로컬에 저장된 errored.tfstate 파일 확인

    cat errored.tfstate | jq
  40. EC2 인스턴스가 실제로 생성되었는지 확인

    aws ec2 describe-instances \
    --filters "Name=tag:Name,Values=terraform-ec2-test" \
    --no-cli-pager
  41. S3 백엔드에 errored.tfstate 파일 적용

    terraform state push errored.tfstate
  42. 인프라 변경 사항 확인

    terraform plan
  43. 인프라 변경 사항 반영

    terraform apply --auto-approve
  44. RDS 인스턴스 목록 확인

    aws rds describe-db-instances \
    --db-instance-identifier terraform-rds-test \
    --no-cli-pager
  45. 해당 문서를 통해서 Terraform에서 이미 생성된 DB 인스턴스를 불러오는 방법 확인

  46. 이미 생성된 DB 인스턴스 불러오기

    terraform import aws_db_instance.this terraform-rds-test
  47. 인프라 변경 사항 확인

    terraform plan
  48. 변경이 감지될 경우 실제 생성된 DB 인스턴스 속성에 맞게 Terraform 코드 수정

  49. 인프라 변경 사항 확인

    terraform plan
  50. 인프라 변경 사항 반영

    terraform apply --auto-approve
  51. 인프라 변경 사항 확인

    terraform plan
  52. 리소스 삭제

    {
      terraform destroy --auto-approve
      aws s3api put-bucket-versioning --bucket $S3_BUCKET \
      --versioning-configuration Status=Suspended \
      --no-cli-pager
      sleep 10
      aws s3api delete-objects \
      --bucket $S3_BUCKET \
      --delete "$(aws s3api list-object-versions \
      --bucket $S3_BUCKET \
      --output=json \
      --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}')" \
      --no-cli-pager
      aws s3api delete-objects \
      --bucket $S3_BUCKET \
      --delete "$(aws s3api list-object-versions \
      --bucket $S3_BUCKET \
      --output=json \
      --query='{Objects: DeleteMarkers[].{Key:Key,VersionId:VersionId}}')" \
      --no-cli-pager
      aws s3api delete-bucket --bucket $S3_BUCKET \
      --no-cli-pager
      aws dynamodb delete-table --table-name $DYNAMODB_TABLE \
      --no-cli-pager
      cd ~/environment && rm -rf terraform
    }

Last updated