본문 바로가기

study/T101 4기

T101 4기 1주차 두번째

[스터디 전용/실습3] EC2 1대 배포 & 웹 서버 설정

 

??? 테라폼이뮤터블 immutable 한가요?

뮤터블 mutable 한가요? → p37 이뮤터블 : 인프라스트럭처의 상태를 변경할 때, 기존의 인프라스트럭처를 수정하거나 업데이트하는 것이 아니라 새로운 인프라스트럭처를 생성하여 이전 상태의 인프라스트럭처를 교체하는 방식을 위미한다.

 

 

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

 

Ubuntu 22.04 LTS 사용

# 각자 편한 디렉터리를 생성해주시면 됩니다
cd ..
mkdir t101-1week-web
cd t101-1week-web

# Ubuntu 22.04 최신 AMI ID 확인
aws ec2 describe-images --owners 099720109477 \
    --filters "Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*" "Name=state,Values=available" \
    --query 'Images|sort_by(@, &CreationDate)[-1].[ImageId, Name]' --output text

# 변수 지정
UBUNTUID=ami-0572f73f0a5650b33

 

코드 파일 작성 : user_data 에 실행 명령어 작성

cat <<EOT > main.tf
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  ami                    = "$UBUNTUID"
  instance_type          = "t2.micro"

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

  tags = {
    Name = "terraform-Study-101"
  }
}
EOT

 

배포 실행 : -auto-approve 자동 승인 기능 부여 옵션

# init
terraform init

# plan
terraform plan
+ user_data                            = "d91ca31904077f0b641b5dd5a783401396ffbf3f"

# apply 실행
terraform apply -auto-approve

 

웹 서버 접속 시도 : 터미널3에서 실행

# [터미널3] 변수 지정
PIP=<각자 자신의 EC2 Public IP>
PIP=54.180.29.38
while true; do curl --connect-timeout 1  http://$PIP:8080/ ; echo "------------------------------"; date; sleep 1; done

 

 

curl을 날리면 응답 하지 않는다..

왜 안될까?

 

 

코드 파일 수정 : 보안 그룹 생성 후 연동

cat <<EOT > main.tf
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  ami                    = "$UBUNTUID"
  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/apply
terraform plan
terraform apply -auto-approve

# 모니터링 : EC2 정보와 curl 접속 확인
PIP=3.39.22.130
혹은
PIP=$(terraform output -raw public_ip)

while true; do curl --connect-timeout 1  http://$PIP:8080/ ; echo "------------------------------"; date; sleep 1; done

# (옵션) 리소스 생성 그래프 확인
terraform graph

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

 

확인

 

 

 

 

---

  • 참조 reference 는 코드의 다른 부분에서 값에 액세스 할 수 있게 해주는 표현식
    • PROVIDER : ‘aws’ 같은 공급자의 이름
    • TYPE : ‘security_group’ 같은 리소스의 유형
    • NAME : 보안 그룹 이름인 ‘instance’ 같은 리소스의 이름
    • ATTRIBUTE : ‘name’ 과 같은 리소스의 인수 중 하나이거나 리소스가 내보낸 속성 중 하나
  • <PROVIDER>_<TYPE>.<NAME>.<ATTRIBUTE>
  • 보안 그룹은 id라는 주석을 내보내므로 이를 참조하는 표현식은 아래와 같음
    • 하나의 리소스에서 다른 리소스로 참조를 추가하면 내재된 종속성이 작성됨
    • 테라폼은 종속성 구문을 분석하여 종속성 그래프를 작성하고, 이를 사용하여 리소스를 생성하는 순서를 자동으로 결정함
  • aws_security_group.instance.id

---

 

 

웹 서비스 포트 변경 : 8080 포트가 아닌 다른 포트로 변경하려면 어떻게 해야 될까?

 

# 모니터링
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

# plan
terraform plan
# aws_instance.example must be replaced
-/+ resource "aws_instance" "example" {
...
      ~ user_data                            = "d91ca31904077f0b641b5dd5a783401396ffbf3f" -> "f1a1c16060740d7be18475c067c120a0eed366da"
        # forces replacement
...
Changes to Outputs:
  ~ public_ip = "43.201.8.225" -> (known after apply)

# apply
terraform apply -auto-approve

# 웹 서버 접속 시도 : 터미널3에서 실행
# process 올라오는데 시간이 1~2분 정도 소요되어서, ec2 생성되면 1~2분 정도 후에 curl 접속이 가능하다
# EC2 Public IP가 어떻게 되나요? 유지? 변경?
PIP=<각자 자신의 EC2 IP>
PIP=54.180.123.229
혹은
PIP=$(terraform output -raw public_ip)

while true; do curl --connect-timeout 1  http://$PIP:9090/ ; echo "------------------------------"; date; sleep 1; done
terraform output
terraform output public_ip
terraform output -raw public_ip
PIP=$(terraform output -raw public_ip)
echo $PIP
curl $PIP:9090

 

아래 보면 userdata부분이 바뀌면 삭제 됐다가 다시 생성됩니다.

 

그래서 재생성되면서 ip도 변경됩니다.

 

 

- HCL

 

HCL HashiCorp configuration language은 하시코프사에서 IaC와 구성 정보를 명시하기 위해 개발된 오픈 소스 도구이다 - 링크 Link

  • IaC는 수동 프로세스가 아닌 코드를 통해 인프라를 관리하고 프로비저닝 하는 것을 말함
  • 테라폼에서 HCL이 코드의 영역을 담당한다. HCL은 쉽게 읽을 수 있고 빠르게 배울 수 있는 언어의 특징을 가진다.
  • 인프라가 코드로 표현되고, 이 코드는 곧 인프라이기 때문에 선언적 특성을 갖게 되고 튜링 완전한 Turing-complete 언어적 특성을 갖는다.
  • 즉, 일반적인 프로그래밍 언어의 조건문 처리 같은 동작이 가능하다. 자동화와 더불어, 쉽게 버저닝해 히스토리를 관리하고 함께 작업 할 수 있는 기반을 제공.

HCL을 사용하면 동일한 내용을 JSON으로 표현하는 것보다 더 간결하고 읽기 쉽게 작성할 수 있다

 

표현식

// 한줄 주석 방법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
}

 

 

- 테라폼 블록

  • 테라폼 블록 : 테라폼 구성을 명시하는 데 사용
    • 테라폼 버전이나 프로바이더 버전과 같은 값들은 자동으로 설정되지만, 함께 작업할 때는 버전을 명시적으로 선언하고 필요한 조건을 입력하여 실행 오류를 최소화 할 것을 권장한다. [Docs] [Docs 예제]
    • 오늘 실행하던, 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"
  }
}

 

 

  • 테라폼 내에서 버전이 명시되는 terraform, module에서 사용 가능하며 버전에 대한 제약을 둠으로써 테라폼, 프로바이더, 모듈이 항상 의도한 정의대로 실행되는 것을 목적으로 한다.
  • 버전 체계는 시맨틱 버전 관리 Semantic Versioning 방식을 따른다
# version = Major.Minor.Patch
version = 1.3.4

 

 

  • 시맨틱 버전 관리 방식
    • Major 버전 : 내부 동작의 API가 변경 또는 삭제되거나 하위 호환이 되지 않는 버전
    • Minor 버전 : 신규 기능이 추가되거나 개선되고 하위 호환이 가능한 버전
    • Patch 버전 : 버그 및 일부 기능이 개선된 하위 호환이 가능한 버전
  • 버전 제약 구문은 다른 프로그램 언어에서의 종속성 관리 시스템과 흡사하다.
    • = 또는 연산자 없음 : 지정된 버전만을 허용하고 다른 조건과 병기할 수 없다.
    • != : 지정된 버전을 제외한다.
    • >, >=, <, <= : 지정된 버전과 비교해 조건(부등호)에 맞는 경우 허용한다.
      • ~> : 지정된 버전에서 가장 자리수가 낮은 구성요소만 증가하는 것을 허용한다.
        • ~> x.y 인 경우 y 버전에 대해서만, ~> x.y.z인 경우 z 버전에 대해서만 보다 큰 버전을 허용한다

테라폼 버전 required_version

cd ..
cd 03.start

 

버전 확인 후 수정

terraform {
  required_version = "< 1.0.0"
}

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

 

결과는?!

 

 

 

다시 수정 후 init

terraform {
  required_version = ">= 1.0.0"
}

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

 

확인

 

 

버전을 높여서 해보자

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 {
  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"
}

 

잘 작동된됩니다.

'study > T101 4기' 카테고리의 다른 글

T101 4기 3주차 첫번째  (0) 2024.06.29
T101 4기 2주차 두번째  (0) 2024.06.22
T101 4기 2주차 첫번째  (0) 2024.06.22
T101 4기 1주차 세번째  (0) 2024.06.15
T101 4기 1주차 첫번째  (0) 2024.06.15