TFC 워크스페이스 구성
TFC에 가입한다. 첫 조직(Organization)을 생성한다.
TFC를 백엔드로 사용하려는, 기존에 로컬에 있는 테라폼 프로젝트에서 로그인을 시도한다.
tf login
Shell
복사
yes 프롬프트가 뜨고 yes를 입력하면 로그인 할 수 있는 토큰 생성 페이지로 브라우저 리다이렉션한다.
경고문처럼 토큰은 다시 볼 수 없으니, 바로 복사해서 다시 터미널로 돌아가 붙여 넣자. 토큰 입력을 기다리는 프롬프트가 떠 있다.
그리고 다음 terraform.cloud 블록을 추가하고 프로젝트를 다시 초기화한다.
terraform {
cloud {
organization = "flavonoyeelleesam" # 조직명
workspaces {
name = "terraform-edu-part1-assessment" # 워크스페이스명
}
}
required_providers {
...
}
}
Ruby
복사
tf init
Shell
복사
TFC 웹 콘솔에서 워크스페이스가 생겼음을 확인한다. 프로젝트는 조직의 기본(default) 프로젝트가 된다.
Workspace Settings > General > Execution mode > Custom.Local 을 선택한다. 이렇게 하면 plan / apply 의 실행과 출력이, 기존 로컬 테라폼 프로젝트처럼, 실행한 터미널에서 이뤄진다. default는 Remote, TFC에서 원격으로 실행, 출력하지만, 실습 편의상 이렇게 구성한 것 같다.
문득 이런 생각이 들었다.
1.
IaC 하려고 테라폼의 클라우드 리소스를 콘솔로 만들고 있네. 이것도 IaC 가능한가?
2.
2번은 아직 해법이나 사례를 모르겠다. 하지만 1번은 가능하다. 테라폼 tfe 프로바이더를 써서.
resource "tfe_organization" "flavonoyeelleesam" { # 조직
name = "flavonoyeelleesam"
email = "flavono123@gmail.com"
}
resource "tfe_workspace" "terraform_edu_part1_assessment" { # 워크스페이스
name = "terraform-edu-part1-assessment"
organization = tfe_organization.flavonoyeelleesam.name
execution_mode = "local" # 실행 모드 설정
}
Ruby
복사
지금까지 콘솔로 한 작업은 위 구성으로 표현할 수 있다.
아무튼 이렇게 구성하면 state(.tfstate 파일)을 TFC에 생성, 관리된다. 워크스페이스 > States에서 확인할 수 있다.
우측 상단 버튼으로 Lock/Unlock도 가능하다. AWS 백엔드 사용 시 S3 버킷의 버저닝 활성화 그리고 DynamoDB를 통한 lock 기능이 TFC hosted로 구현돼 있다. 아마 뒤에선 AWS(같은 서비스?)를 쓰고 있지 않을까 예상해본다.
실습 →
목표 : 아래 깃허브 저장소를 복제해 아래 조건에 만족하는 코드를 작성
조건
1.
Terraform Cloud를 State 백엔드로 구성
•
Workspace 이름 : terraform-edu-part1-assessment
•
실행 모드는 local
2.
AWS 공통 Tag : Project = “workshop”
3.
aws_instance는 반복문을 사용해 3개 구성
4.
EIP를 제거하고 EC2에서 public ip를 자체 사용하도록 구성
5.
placeholder 변수는 아래 3가지가 각각의 aws_instance에 적용되도록 구성
placekitten.com
placebear.com
placedog.net
Bash
복사
•
풀이 예제는 ‘example’ 브랜치에 있다. 조건에 맞게 작성한 코드와 비교해보고 더 나은 방안을 찾아보자!
◦
반복문에 count와 for_each를 활용할 수 있다
◦
module을 활용하는 방안도 있다
문제로 내어준 조건은 위와 같다. 따라서 앞서 terraform.cloud 블록은 문제의 포크한 레포에서 구성했고, 1번에 대한 풀이를 한 것이다.
2번은 provider.aws.default_tags 에 값만 바꿈으로써 쉽게 풀 수 있다.
provider "aws" {
region = var.region
default_tags {
tags = {
Project = "workshop"
}
}
}
Ruby
복사
3~5번은 세개의 인스턴스를 각각 로 띄우기 위한 요구사항이다. 난 모듈로 만들기로 했다. 모듈이 되어야 하는 부분은 aws_instance 와 안에서 프로비저닝을 위한 null_resource 두개 뿐이지만, 이런거 모듈로 감싸지 않으면 코드가 엉망이 되더라… 그리고 연습이기도 하니깐 좀 굳이? 라는 선택을 했다.
위 리소스 두개만 모듈화하려면, 4번의 조건, EIP를 제거해야 한다. aws_eip.hashicat 과 aws_eip_association.hashicat 을 제거하고, aws_eip.hashicat.public_ip 참조를 aws_instance.hashicat.public_ip 로 바꾼다. aws_instance.hashicat 가 이미 퍼블릭 서브넷에 있다.
그 다음은 모듈을 만들자.
1.
$GIT_ROOT/modules/hashicat 디렉토리 밑에 다음 파일 생성
•
main.tf
•
variables.tf
•
outputs.tf
2.
main.tf에 모듈에 포함할 리소스를 옮기고
•
aws_instance.hashicat → aws_instance.this
•
null_resource.configure-cat-app
3.
variables.tf는 다음과 같이 구성한다:
•
루트 모듈 vars 중 모듈에서 참조가 필요한 것은 그대로 넘겨준다.
◦
prefix
◦
instance_type
◦
height
◦
width
◦
placeholder
•
그리고 루트 모듈의 리소스 중 모듈에서 참조가 필요한 vars를 새로 만든다. 크게 두 부분으로 나뉜다.
◦
네트워크
▪
subnet_id
▪
vpc_segurity_group_id
◦
(프로비저닝을 위한) SSH
▪
key_name
▪
private_key
4.
outputs.tf는 루트 모듈것을 그대로 옮긴다. 원래도 aws_instance.hashicat 의 attribute만 출력했기 때문
간단하게 설명했지만, 조금씩 옮기면서 validate , plan 심지어 apply 까지 돌려가며 검증했다. 운영 중인 서비스가 아니기 때문에. 복붙 후 크게 두 부분만 다르게 했다:
•
aws_instance.hashicat → aws_instance.this
•
리소스 attribute 직접 참조를 변수 참조로 변경
◦
e.g. aws_key_pair.hashicat.key_name → var.key_name
그리고 data.aws_ami.ubuntu 도 같이 모듈에 넣었는데, 이 부분은 루트 모듈에 선언하고 hashicat 모듈엔 .id 만 변수로 넘겨주어도 될 것 같다.
모듈을 만든 후 반복문을 써서 호출도 위 커밋에서 한꺼번에 했다.
•
모듈 이름은 hashicats 로 선언하고
•
루트 var.placeholder 를 var.placeholders 로 변경
◦
string → list
◦
기본 값을 5번 요구사항으로 변경
variable "placeholders" {
default = [
"placekitten.com",
"placebear.com",
"placedog.net"
]
...
}
Ruby
복사
•
module.hashicats 에 var.placeholders 길이만큼 반복문 선언 후 모듈 placeholder 에 인덱스 접근으로 하나씩 넣어 줌
module "hashicats" {
source = "./modules/hashicat"
count = length(var.placeholders)
...
placeholder = var.placeholders[count.index]
...
}
Ruby
복사
•
루트 모듈 outputs.tf 에서 module.hashicats 의 catapp_url/catapp_ip 를 순회하며 출력
output "catapp_url" {
value = [
for hashicat in module.hashicats :
hashicat.catapp_url
]
}
output "catapp_ip" {
value = [
for instance in module.hashicats :
instance.catapp_ip
]
}
Ruby
복사
apply 후 나온 url이나 ip로 각각 접속하면 을 볼 수 있다.