인생은 여행

Terraform 101 Day1 본문

T101

Terraform 101 Day1

산떠 버하둘 2024. 6. 16. 05:43
이 글은 도서 "테라폼으로 시작하는 IaC"를 교재로 하여 진행하는 가시다님의 Terraform 101 스터디 4기에 참여하여 기록으로 남긴 것입니다.

IaC

"IaC는 컴퓨터에서 읽을 수 있는 정의 파일을 사용해 인프라나 서비스를 관리하고 프로비저닝하는 프로세스"

긍정적인 측면

- 속도와 효율성

- 버전 관리

- 협업

- 재사용성

- 기술의 자산화

우려되는 측면

- 코드 문법 학습

- 파이프라인 통합

- 대상 인프라에 대한 이해 필요

 

테라폼의 세 가지 중요한 철학

- 워크플로에 집중

- 코드형 인프라(IaC)

- 실용주의

 

테라폼 제공 유형

- On-Premise

- Hosted SaaS

- Private Install

 

실습 1: 테라폼 설치

사용하는 컴퓨터 환경이 mac이므로 brew 명령을 이용하여 설치할 수도 있지만 다루는 테라폼 소스마다 요구하는 테라폼 버전이 다를 수 있으므로 스터디에서는 tfenv라는 프로그램을 먼저 설치하고 tfenv를 통하여 테라폼을 설치하는 방식으로 진행하였다.

기존에 이미 brew를 이용하여 테라폼이 설치되어 있었지만 tfenv가 테라폼 바이너리를 관리할 수 있도록 제거하고 tfenv를 이용하여 다시 설치하였다.

# tfenv 설치
brew install tfenv

# terraform 설치 및 기본 버전 선택
tfenv list-remote
tfenv install 1.3.2
tfenv use 1.3.2
tfenv list
terraform version

# 자동완성 - 현재 계정의 시작 스크립트에 테라폼 자동완성 기능 기동 명령 추가
terraform -install-autocomplete

 

실습 2: default VPC에 EC2 1대 배포

꿀팁 - 다음은 메모해두고 업무에 활용해 볼만할 

 

특정 AMI 검색하기

# SSM Parameter에서 Amazon Linux 최신 버전 이름 조회
aws ssm get-parameters-by-path \
  --path /aws/service/ami-amazon-linux-latest \
  --query "Parameters[].Name"

# SSM Parameter에서 이미지 이름으로 최신 AMI 버전 찾기
aws ssm get-parameters-by-path \
  --path /aws/service/ami-amazon-linux-latest \
  --query "Parameters[?contains(Name, 'amzn2-ami-kernel-5.10-hvm-x86_64-gp2')]"

# AMI 중에서 조회 및 정렬
aws ec2 describe-images --owners self amazon \
  --query "sort_by(Images[?contains(Name, 'amzn2-ami-kernel-5.10-hvm-')], \
  &CreationDate)[*].[ImageId, Name]" \
  --output text

참고

- https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html

[토막 상식] 아미존 리눅스 2는 커널버전 4.14와 5.10을 지원한다. 이미지 이름에 커널 버전이 없으면 4.14이다.

- https://docs.aws.amazon.com/linux/al2/ug/aml2-kernel.html

 

현재(2024.06.16) 최신 버전

- ami-0d7acf3d584720d31 amzn2-ami-kernel-5.10-hvm-2.0.20240610.1-arm64-gp2
- ami-06f220419a1559609 amzn2-ami-kernel-5.10-hvm-2.0.20240610.1-x86_64-ebs
- ami-034a31ed1d34ef024 amzn2-ami-kernel-5.10-hvm-2.0.20240610.1-x86_64-gp2

 

EC2 생성 모니터링 준비(주기적으로 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

 

 

아래와 같은 내용으로 main.tf 파일을 작성한다.

provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  ami           = "ami-0c76973fbe0ee100c"
  instance_type = "t2.micro"
}

 

아래와 같은 명령으로 인스턴스를 생성한다.

# 초기화
terraform init
# 계획
terraform plan
# 실행
terraform apply

 

생성된 인스턴의 정보를 수정한다. 여기에서는 태그를 하나 추가하였다.

provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  ami           = "ami-0c76973fbe0ee100c"
  instance_type = "t2.micro"

  tags = {
    Name = "t101-study"
  }
}

plan 후 apply 한다.

 

다음은 최신 AMI를 코드로 가져오는 예제이다.

provider "aws" {
  region = "ap-northeast-2"
}

# plan에서 ami id가 보이지 않는다. 파라미터 조횟값이라 민감정보로 판단하는 듯 하다. "(sensitive value)"로 표시
data "aws_ssm_parameter" "amzn2_latest" {
  name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-kernel-5.10-hvm-x86_64-gp2"
}

# plan 시 ami id가 보인다.
data "aws_ami" "linux" {
  owners      = ["amazon"]
  most_recent = true

  filter {
    name   = "name"
    values = ["amzn2-ami-kernel-5.10-hvm*"]
  }
}

resource "aws_instance" "example" {
  #ami           = data.aws_ssm_parameter.amzn2_latest.value
  ami           = data.aws_ami.linux.id
  instance_type = "t2.micro"

  tags = {
    Name = "Sample EC2"
  }
}

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

Ubuntu 22.04 LTS 사용 (ami-0e9bfdb247cc8de84)

EC2의 userdata를 이용하여 인스턴스 기동시에 웹서버를 띄운다. 

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

 

- 웹서버 접속 확인

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

접속 실패, 웹 서버 접속이 왜 되지 않을까요?

-> AWS에서는 외부에서의 접속을 기본적으로 차단한다. 보안그룹 설정을 통해 서비스하는 포트를 외부로 개방해 주어야 한다.

코드에 보안그룹 설정을 추가한다.

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

 

 

위에서 vpc_security_group_ids = [aws_security_group.instance.id] 부분은 보안그룹의 ID를 인스턴스에서 참조하는 모양새이다.

테라폼은 종속성 구문을 분석하여 종속성 그래프를 작성하고, 이를 사용하여 리소스를 생성하는 순서를 자동으로 결정한다.

포트를 8080 -> 9090으로 변경하기 위해서는 코드 내의 8080을 모두 9090으로 바꿔줘야한다. 만약 빈번하게 서버의 포트가 변경되면 어떻게 해야 될까요? 이런 불편함을 해결하려면 어떻게 해야 될까요?

-> 포트 번호를 변수 처리하여 코드 한 곳에서만 변경하거나 외부에서 주입할 수도 있을 것이다.

만약 user_data_replace_on_change = false 설정 상태에서 userdata 를 변경 후 apply 하면 어떻게 될까요?

-> 어찌된 일인지 EC2가 재기동하였지만 접속불가 상태가 됨. 더 확인 필요

 

인프라 배포 후 애플리케이션 설정 할 수 있는 다양한 방법이 있고 장단점이 있습니다. 좀 더 견고하고 안정적이며 신뢰할 수 있는 방법이 무엇일까요? - 참고링크 링크 - 테라폼 코드 userdata 사용, cloud-init 사용, Packer 활용, Provisiner Connections 활용, 별도의 설정 관리 툴 사용(Chef, Habitat, Puppet 등)

 

심화옵션: 코드와 실제 배포된 형상이 일치하지 않을 경우

테라폼 apply를 하면 적용된 인프라의 상태가 terraform.tfstate 파일에 기록된다. 이 상태 파일이 없으면 테라폼 코드를 정상적으로 수행할 수 없다. 상태는 아주 중요하므로 유실되지 않도록 유의해야 한다.

IaC 도입 시에는 최대한 코드를 통한 상태가 실제 배포된 프로바이더의 상태가 되도록 맞추는 것이 중요.

상태를 로컬 파일이 아닌 다른 곳에 저장할 수 있다. S3도 좋은 대안이 될 수 있다.

[이론] Variable 변수

입력 변수

변수의 4가지 입력 방안

variable "server_port" {
  description = "The port the server will use for HTTP requests"
  type        = number
}

- 대화형으로 변수값 입력

    default 값이 없고, 아무런 옵션이 주어지지 않았다면 실행시에 물어본다.

- -var 옵션

 

- 환경 변수

# 환경변수에 지정
export TF_VAR_server_port=8080
terraform plan

# 환경변수 확인
export | grep TF_VAR_

# 환경변수 지정 삭제
unset TF_VAR_server_port

- 디폴트 값을 미리 지정

variable "server_port" {
  description = "The port the server will use for HTTP requests"
  type        = number
  default     = 8080
}

출력 변수

출력 변수 용도

- 유용한 정보 출력

- 모듈의 리턴 값

 

 

Comments