Terraform/Study_과제

1주차 - Terraform 기본 사용 1/3

in-cloud 2023. 7. 9. 01:03

<참고> 테라폼으로 시작하는 IaC - 김민수, 김재준, 이규석, 이유종 저 한빛미디어

 

모든 실습은 Mac OS 기준으로 작성되었습니다

 

2장 실행환경 구성

Terraform 설치 - 실습1

# tfenv - version 관리
brew install tfenv

# tfenv - 설치 가능한 버전 리스트
tfenv list-remote

# tfenv - 특정 버전( 1.5.2 )설치
tfenv install 1.5.2

# tfenv로 설치되어있는 버전 확인
tfenv list

# Terraform 명령어를 터미널에서 자동완성되도록 설정
terraform -install-autocomplete

# 위 스크립트 실행시
# Error executing CLI: Did not find any shells to install 라고 나오는 경우
# 쉘 설정파일 먼저 만든 후 다시 스크립트 실행
touch ~/.zshrc

# 실습에 사용될 Tool 설치
brew install tree jq watch

IDE 설치 및 구성 - Visual Studio Code 사용

- 다운로드 및 설치 - 링크

- 확장도구 (Extention) 추가

AWS CLI 설치 및 자격증명 설정

# aws cli 설치 및 버전 확인
brew install awscli
aws --verion

# 자격증명 설정
aws configure

AWS Access Key ID [********************]:
AWS Secret Access Key [********************]:
Default region name [ap-northeast-2]:
Default output format [None]:

Default VPC에 EC2 1대 배포 - 실습2

ami-06b79cf2aee0d5c92 를 기준으로 생성

# 작업 경로 만들고 이동하기
mkdir ec2-test
cd ec2-test

# ami가 자주 바뀌기때문에 id를 찾아주어야 함
# aws ec2 describe-images --owners self amazon
aws ec2 describe-images --owners self amazon --query 'Images[*].[ImageId]' --output text

aws ssm get-parameters-by-path --path /aws/service/ami-amazon-linux-latest
aws ssm get-parameters-by-path --path /aws/service/ami-amazon-linux-latest --query "Parameters[].Name"
aws ssm get-parameters-by-path --path /aws/service/ami-amazon-linux-latest --query "Parameters[].Value"

# EC2 생성 모니터링
export AWS_PAGER=""
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

# 배포 코드 파일 작성
cat <<EOT > main.tf
provider "aws" {
  region = "ap-northeast-2"
}

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

# 배포 - 초기화
terraform init
ls -al
tree .terraform

# plan 확인
terraform plan

# apply 실행
terraform apply
 Enter a value: yes 입력

# ec2 생성 확인 : aws 웹 관리 콘솔에서도 확인
export AWS_PAGER=""
aws ec2 describe-instances --output table

# 리소스 삭제
terraform destroy -auto-approve

terraform init

 

3장 기본 사용법

주요 커맨드

# 실습 디렉터리 생성 후 이동
mkdir workspaces
cd workspaces

# 테라폼 실행
terraform
Usage: terraform [-version] [-help] <command> [args]
...

# VS Code 폴더 생성 (03.start) → 새파일 생성 (main.tf)
resource "local_file" "abc" {
content  = "abc!"
filename = "${path.module}/abc.txt"
}

# Help
terraform console -help
terraform init -help

# 초기화
terraform init
ls -al
tree .terraform

tree .terraform 실행 결과

# plan - 테라폼으로 적용할 인프라의 변경 사항에 관한 실행 계획을 생성
terraform plan

# -detailed-exitcode : **plan 추가 옵션**으로, 파이프라인 설계에서 활용 가능, exitcode가 환경 변수로 구성됨
# -auto-approve 자동 승인 기능 부여 옵션

# plan 결과를 시스템 코드로 출력
terraform plan -detailed-exitcode

# 코드 확인 : 0(변경 사항이 없는 성공), 1(오류가 있음), 2(변경 사항이 있는 성공)
echo $?
2

# (참고) apply 결과에 적용 시도
terraform apply -auto-approve -detailed-exitcode

# apply - 실행
terraform apply

# plan 결과를 지정된 파일(바이너리 형태) 이름으로 생성
terraform plan -out=tfplan
cat tfplan
file tfplan

# apply 실행 : 실행계획이 있으므로 즉시 적용됨
terraform apply tfplan
ls -al abc.txt

# 코드파일 수정
resource "local_file" "abc" {
content = "abc!"
filename = "${path.module}/abc.txt"
}

resource "local_file" "dev" {
  content  = "def!"
  filename = "${path.module}/def.txt"
}

# apply 실행 : 변경(신규 추가) 부분만 반영 확인
terraform apply
...
# local_file.dev will be created
  + resource "local_file" "dev" {
...
Enter a value: yes

# 확인
terraform state list
tree
ls *.txt

# 변경 이전의 실행 계획 적용 시도 > 어떻게 될까요?
terraform apply tfplan
...

# 다시 추가 코드 내용을 삭제
resource "local_file" "abc" {
content = "abc!"
filename = "${path.module}/abc.txt"
}

# 실행 > 어떻게 되나요?
terraform apply
...
Enter a value: yes
...

# 확인
terraform state list
tree
ls *.txt

실행 결과

# 현재 배포된 리소스 확인
terraform state list
local_file.abc

# 다시 생성 : 파일 생성 시간 확인
ls -l abc.txt
terraform apply -replace=local_file.abc -auto-approve
ls -l abc.txt
terraform apply -replace=local_file.abc -auto-approve
ls -l abc.txt

 

# 제거
terraform destroy
...
Enter a value: yes
...

# 확인
terraform state list
ls *.txt

# 적용 후 코드 파일 내용 확인
terraform fmt

default VPC에 웹 서버 배포 - 실습3

EC2 1대를 배포하면서 userdata 에 웹 서버 설정 → 간단한 애플리케이션 설정 자동화

 

EC2 1대를 배포하면서&nbsp;userdata&nbsp;에 웹 서버 설정 &rarr; 간단한&nbsp;애플리케이션 설정 자동화

# 파일 작성
cat <<EOT > main.tf
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  ami                    = "ami-0e9bfdb247cc8de84"
  instance_type          = "t2.micro"
  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 8080 &
              EOF

  tags = {
    Name = "Single-WebSrv"
  }
}

resource "aws_security_group" "instance" {
  name = var.security_group_name

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

variable "security_group_name" {
  description = "The name of the security group"
  type        = string
  default     = "terraform-example-instance"
}

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

# 배포
# plan
terraform plan
+ user_data                            = "d91ca31904077f0b641b5dd5a783401396ffbf3f"

# apply 실행
# plan/apply
terraform plan
terraform apply -auto-approve
#terraform graph

# 웹서버 접속 - 새 터미널에서 실행
# [터미널3] 변수 지정
PIP=<각자 자신의 EC2 IP>
PIP=xxx.xxx.xxx.xxx
while true; do curl --connect-timeout 1  http://$PIP:8080/ ; echo "------------------------------"; date; sleep 1; done

# 리소스 삭제
terraform destroy -auto-approve

 

 

HCL

// 한줄 주석 방법1
# 한줄 주석 방법2

/*
라인
주석
*/

locals {
  key1     = "value1"     # = 를 기준으로 키와 값이 구분되며
  myStr    = "TF ♡ UTF-8" # UTF-8 문자를 지원한다.
  multiStr = <<EOF
  Multi
  Line
  String
  with anytext
EOF

  boolean1    = true   # boolean true
  boolean2    = false  # boolean false를 지원한다.
  deciaml     = 123    # 기본적으로 숫자는 10진수,
  octal       = 0123   # 0으로 시작하는 숫자는 8진수,
  hexadecimal = "0xD5" # 0x 값을 포함하는 스트링은 16진수,
  scientific  = 1e10   # 과학표기 법도 지원한다.

  # funtion 호출 예
  myprojectname = format("%s is myproject name", var.project)

  # 3항 연산자 조건문을 지원한다.
  credentials = var.credentials == "" ? file(var.credentials_file) : var.credentials
}

>> VS Code test

3.3 테라폼 블록

terraform {
  required_version = "~> 1.3.0" # 테라폼 버전

  required_providers { # 프로바이더 버전을 나열
    random = {
      version = ">= 3.0.0, < 3.1.0"
    }
    aws = {
      version = "4.2.0"
    }
  }

  cloud { # Cloud/Enterprise 같은 원격 실행을 위한 정보
    organization = "<MY_ORG_NAME>"
    workspaces {
      name = "my-first-workspace"
    }
  }

  backend "local" { # state를 보관하는 위치를 지정
    path = "relative/path/to/terraform.tfstate"
  }
}

# version = Major.Minor.Patch
version = 1.3.4

테라폼 버전 required_version

cd ..
cd 03.start

# 현재 버전 정보 확인
terraform version
Terraform v1.5.1

# main.tf 파일 수정
terraform {
  required_version = "< 1.0.0"
}

resource "local_file" "abc" {
  content  = "abc!"
  filename = "${path.module}/abc.txt"
}

#init
# 실행 결과는?
terraform init
...

버전 변경하는 코드블록을 추가 후 init을 실행한 결과

# 코드파일 수정 
terraform {
  required_version = ">= 1.0.0"
}

resource "local_file" "abc" {
  content  = "abc!"
  filename = "${path.module}/abc.txt"
}

# 실행 결과는?
terraform init
...

프로바이더 버전

terraform {
  required_version = ">= 1.0.0"
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = ">=10000.0.0"
    }
  }
}

resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

# 실행 결과는?
terraform init -upgrade

# local 프로바이더 버전을 >= 2.0.0으로 수정
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = ">= 2.0.0"
    }
  }
}

resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

# 실행 결과는?
terraform init -upgrade

3.4 리소스

# 03.end 디렉터리를 신규 생성 후 열기 → main.tf 파일 생성
cd ..
rm -rf 03.start
mkdir 03.end
cd 03.end

# 파일
resource "local_file" "abc" {
  content  = "123"
  filename = "${path.module}/abc.txt"
}

resource "aws_instance" "web" {
  ami = "ami-a1b2c3d4"
  instance_type = "t2.micro"  
}

# init
terraform init
tree .terraform

 

종속성 - VS Code 확장 graphviz 설치

resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

resource "local_file" "def" {
  content  = "456!"
  filename = "${path.module}/def.txt"
}

# apply
terraform apply -auto-approve

# 리소스 확인
ls *.txt
terraform state list

# graph 확인 > graph-1.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph
terraform graph > graph-1.dot

# 모든 리소스 제거
terraform destroy -auto-approve
ls *.txt
terraform state list

리소스 참조값을 설정해 두 개의 리소스 간 암시적 종속성 부여

# main.tf
resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

resource "local_file" "def" {
  content  = local_file.abc.content
  filename = "${path.module}/def.txt"
}

# apply 커맨드 생성에 순서가 발생한 종속성 있는 두 개의 리소스
terraform apply -auto-approve

ls *.txt
terraform state list
cat abc.txt
cat def.txt
diff abc.txt def.txt

# graph 확인 > graph-2.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph
terraform graph > graph-2.dot

리소스의 속성을 주입하지 않아도 두 리소스 간에 종속성이 필요한 경우에, depends_on 선언으로 적용 가능

resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

resource "local_file" "def" {
  depends_on = [
    local_file.abc
  ]

  content  = "456!"
  filename = "${path.module}/def.txt"
}

#apply
terraform destroy -auto-approve
terraform apply -auto-approve
...

# graph 확인 > graph-3.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph
terraform graph > graph-3.dot

'Terraform > Study_과제' 카테고리의 다른 글

7주차 - 워크플로  (0) 2023.08.20
6주차 - 협업  (0) 2023.08.11
4주차 - State & 모듈  (0) 2023.07.29
3주차 - Terraform 기본 사용 3/3  (0) 2023.07.23
2주차 - Terraform 기본 사용 2/3  (0) 2023.07.15