Terraform Basic(1)
개념 학습
태라폼 소개
- 구성 파일을 사용하여 버전 관리와 재사용 및 공유 기능을 제공해요. 클라우드 및 온프레미스 리소스를 모두 정의할 수 있는 코드형 인프라 관리 도구입니다.
- 테라폼으로 리소스를 프로비저닝하면 프로비저닝된 것을 ansible과 같은 것들로 관리를 해줄 수가 있어요.
프로비저닝 도구
프로비저닝 도구는 서버 자체를 생성합니다. 도구를 사용하면 서버 뿐만 아니라 모든 측면을 생성할 수 있어요.
아래는 테라폼의 예시 있다 웹 서버를 배표하는 코드에요. 해당 코드에서는 ami와 user_data에 집중하면 좋아요.
- ami는 서버에서 배포할 ami의 id를 지정해요.
- user_data는 웹 서버가 부팅될 때 실행되는 bash 스크립트에요.
resource "aws_instance" "app" {
instance_type = "t2.micro"
availability_zone = "us-east-2a"
ami = "ami-0fb653ca2d3203ac1"
user_data = <<-EOF
#!/bin/bash
sudo service apache 2 start
EOF
}
테라폼 동작 방법
테라폼은 기본적으로 Go 프로그래밍 언어로 작성된 오픈 소스 도구에요. 따라서 terraform이라는 컴파일된 바이너리를 실행하기만 하면 추가 인프라 실행 없이 인프라를 배포할 수 있어요.
테라폼 리소스 생성
테라폼에서 리소스 생성은 아래와 같이 템플릿을 활용해 작성할 수 있어요.
resource "<PROVIDER>_<TYPE>" "<NAME>" {
[ CONFIG ... ]
}
- PROVIDER는 aws와 같은 것이고
- TYPE은 해당 공급자에서 생성할 리소스 유형 (인스턴스와 같은 것들) 이에요.
- Name은 테라폼 코드에서 해당 리소스를 참조하는데 사용하는 식별자입니다.
- CONFIG는 해당 리소스와 관련된 하나 이상의 인수로 구성돼요.
코드 동기화
terraform으로 구축해놓은 것을 동기화하기 위해서는 작성한 .tf 파일들과 .terraform.lock.hcl 파일만 깃헙에 올리면 돼요.
.terraform
*.tfstate
*.tfstate.backup
실습
테라폼 초기 세팅 방법
- IAM 사용자를 만들어줍니다. 원래는 최소한의 권한만 주지만 실습을 진행하기 위해서 권한을
AdministratorAccess로 설정 후 만들어줍니다. - 만든 사용자로 들어가서 개발을 access key를 설정해줍니다. 이 때 access key와 secret access key를 잘 보관해둡니다. 이때 AWS CLI를 선택하여 키를 만들어줍니다.
테러폼 셋팅
현재 저는 아마존 리눅스 환경에서 진행을 하기 때문에 yum을 활용해 개발을 진행
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
sudo yum -y install terraform
AWS 인스턴스 생성
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "example" {
{/* ami id 값은 aws ec2 창의 ami에서 찾으면 나옵니다! */}
ami = "ami-.."
instance_type = "t2.micro"
}
이렇게 작업을 진행해준 다음에 아래 명령를 입력을 해줍니다.
terraform init
그려먼 .terraform이라는 파일이 하나 생성이 됩니다. 공급자의 코드는 여기에 다운로드가 됩니다. .terraform 디렉토리는 git에 따로 올리지 않아요. 만약 다른 사람이 사용하고 싶으면 .terraform.lock.hcl 공유를 받고 실행하면 멱등성으로 인해 안전하게 실행할 수 있습니다.
위 작업이 정상적으로 끝이 나면 Terraform has been successfully initialized!가 뜹니다. 그리고 아래 명령어를 입력줘요.
terraform plan
해당 명령을 실행하면 실제로 반영하기 전에 수행할 작업들을 확인할 수 있어요. + 는 모두 생성되고 -는 모두 삭제가 돼요.
정상적으로 확인이 되고 나면 아래 명령어를 실행줍니다.
- --auto-approve는 중간에 yes 과정을 없애고 바로 진행할 수 있어요.
terraform apply --auto-approve
만약 기본 VPC가 없다면 정상적으로 인스턴스가 생성이 안될거에요. 그럴 때는 AWS VPC로 들어가서 기본 VPC를 하나 만들어주면 됩니다.
정상적으로 완료가 되면 Apply complete!를 확인할 수 있어요.
해당 리소스를 지우기 위해서는 destroy를 활용해서 명령어를 지우실 수 있습니다.
terraform destroy --auto-approve
해당 명령어 역시 정상적으로 수행을 하고 나면 Destroy complete!를 확인할 수 있어요.
위 상태에서 실행을 하게 되면 인스턴스 이름이 없는 상태로 나와요. 이름을 지정하기 위해서는 tags에서 Name을 추가해주면 돼요.
resource "aws_instance" "example" {
{/* ami id 값은 aws ec2 창의 ami에서 찾으면 나옵니다! */}
ami = "ami-.."
instance_type = "t2.micro"
tags = {
Name = "terraform-exmaple"
}
}
그리고 다시 terraform apply --auto-approve를 하게 되면 기존의 인스턴스를 삭제하지 않고 change가 됩니다.
AWS httpd 서버 띄우기
resource "aws_instance" "example" {
{/* ami id 값은 aws ec2 창의 ami에서 찾으면 나옵니다! */}
ami = "ami-.."
instance_type = "t2.micro"
user_data = <<- EOF
#!/bin/bash
echo "hi" > index.html
nohub busybox httpd -f -p 8080 &
EOF
user_data_replace_on_chage
tags = {
Name = "terraform-exmaple"
}
}
- user_data를 활용해서 shell script를 전달해줄 수 있습니다. 이 때
<<-EOF ... EOF구문을 활용해서 여러 줄 문자열을 생성할 수 있어요. - user_data_replace_on_chage를 활용하면 원래 인스턴스를 종료하고 새로운 인스턴스를 새롭게 생성합니다.
하지만 이렇게만 해서는 퍼블릭 IP로 접속을 할 수 없어요. 왜냐하면 보안그룹을 설정하지 않았기 때문이에요. 따라서 테라폼을 활용해서 보안그룹을 생성하면 이 문제를 해결할 수 있어요.
resource "aws_security_group" "instance" {
name = "terraform-example-instance"
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = [ "0.0.0.0/0" ]
}
}
이렇게 만들었다고 해서 인스턴스와 보안그룹이 자동으로 연결이 되지 않아요. 따라서 Terraform 표현식을 통해서 연결을 해줄 수가 있습니다!
표현식의 기본적인 구조는 <PROVIDER>_<TYPE> . <NAME> . <ATTRIBUTE>에요. 여기서 ATTRIBUTE는
- 해당 리소소 인수
- 리소스에서 내보낸 속성
이거 2개 중 하나라고 알고 있으면 돼요.
보안 그룹은 id라는 속성을 내보내기 때문에 aws_security_group.instance.id 로 해줄 수 있어요. 해당 값을 인스턴스 코드에 넣어주시고 apply를 해주시면 연결이 됩니다.
resource "aws_instance" "example" {
...기존의 코드들
vpc_security_group_ids = [aws_security_group.id]
}
apply가 되면 최종적으로 public ip에 정상적으로 접속이 된 것을 확인할 수 있어요.
그리고 코드를 보게 되면 port를 확인하게 되면 동일하게 사용이 되는 것은 변수로 처리해 줄 수 있어요. 지정된 변수들은 var. 으로 접근하여서 사용해줄 수 있습니다.
variable "server_port" {
description = "The port the ..."
type = number
default = 8080
}
resource "aws_security_group" "instance" {
name = "terraform-example-instance"
ingress {
from_port = var.server_port
to_port = var.server_port
protocol = "tcp"
cidr_blocks = [ "0.0.0.0/0" ]
}
}
