✅ 이 블로깅은 테라폼으로 시작하는 IaC 책을 기반으로 작성한다.


테라폼을 사용하는 조직에서 협업은 거의 필요다고 볼 수 있다.

그렇게 되는 경우 테라폼도 코드로 구성되어 있기 때문에 VCS (Version Control System)과 테라폼 State 파일을 관리할 수 있는 백엔드를 구성 방식도 고려해 봐야 한다

VCS로는 여러 코드저장소가 있는데 Github이 대표적인 저장소이다.

코드저장소에서 테라폼 코드를 관리하게 된다면 반드시 gitignore 파일을 통해 깃 관리 대상에서 제외해야 할 몇 가지 파일이 있다. .terraform 디렉터리, .tfstate 파일, tfvars 파일, Credentials 관련 파일, terraformrc 파일 등이 있다.

이번에 나도 테라폼 스터디를 진행하면서 스터디했던 내용은 깃헙에 올려둔 상태라 내 깃헙에 작성해 둔 gitignore 파일이 있다.

.terraform*
*.tfstate
*.tfstate.backup
aws*

최소한의 테스트 정도로는 이 정도만 작성해도 될 거 같다. 아래 링크는 gitignore 파일을 생성할 때 참조하면 좋은 사이트다!

참고 ) gitignore.io

State 백엔드

State 백엔드는 다수의 작업자가 동일한 State로 접근해 프로비저닝하기 위해 필요한 공유 스토리지이다.

State 백엔드를 사용할 때 민감한 데이터가 State 파일에 저장될 수 있는 점을 반드시 고려하여 암호화할 수 있는 방안도 고려해야 한다

테라폼 클라우드로 관리하게 되면 자동으로 vault로 암호화되기 때문에 관리에 유용하다고 한다. 게다가 무료!!

생각해 보니 테라폼을 처음 접했을 때 만들어둔 계정과 organization이 있었다 ㅎㅎ..

TFC State 실습

테라폼 클라우드 활용한 실습은 아래 레포를 fork하여 진행하였다.

https://github.com/terraform101/terraform-aws-collaboration

tom과 jerry 두 작업자가 진행한다고 가정하여 디렉토리를 두 공간으로 구분했다.

$ ls -al
	total 0
	drwxr-xr-x 1 gain gain 4096 Oct  8 02:29 .
	drwxrwxrwx 1 gain gain 4096 Oct  8 02:28 ..
	drwxr-xr-x 1 gain gain 4096 Oct  8 02:29 terraform-aws-collaboration-jerry
	drwxr-xr-x 1 gain gain 4096 Oct  8 02:28 terraform-aws-collaboration-tom

그리고 TFC를 사용하기 전에 두 작업자가 동일한 소스코드로 동일한 AWS 인프라를 프로비저닝한다는 상황이다.

tom 작업자가 먼저 init & apply를 진행하였고 terraform.tfstate, terraform.tfstate.backup 파일을 생성한 채 인프라 프로비저닝을 완료하였다.

그리고 jerry 작업자가 작업하게 되면.. state 파일을 공유하지 않기 때문에 jerry 작업자의 워크스페이스에서도 동일한 리소스를 만들게 된다

이제 TFC를 통해 State 파일을 공유할 것이다.

main.tf 파일에서 TFC 부분 설정을 추가해 준다.

cloud {
     organization = "6ain-study"         # 생성한 ORG 이름 지정
     hostname     = "app.terraform.io"      # default

     workspaces {
       name = "terraform-aws-collaboration"  # 없으면 생성됨
     }
   }

그리고 init 실행하면 아래와 같이 TFC로 state를 마이그레이션한다는 로그가 출력된다.

$ terraform init

	Initializing Terraform Cloud...
	Do you wish to proceed?
	  As part of migrating to Terraform Cloud, Terraform can optionally copy your
	  current workspace state to the configured Terraform Cloud workspace.
	  
	  Answer "yes" to copy the latest state snapshot to the configured
	  Terraform Cloud workspace.
	  
	  Answer "no" to ignore the existing state and just activate the configured
	  Terraform Cloud workspace with its existing state, if any.
	  
	  Should Terraform migrate your existing state?
	
	  Enter a value: yes

그럼 state 파일이 잘 이관되었는지 보려면 tfstate 파일 내용을 보자

$ ls terraform.tfstate*
	terraform.tfstate  terraform.tfstate.backup
$ cat terraform.tfstate

파일은 삭제는 안됐는데 cat 명령어로 내용 확인 시 아무것도 출력되지 않는다

Untitled

TFC의 States 메뉴에서 잘 업로드된 점을 확인할 수 있다.

어우 방금… 실수로 jerry에서 apply로 진행했을 때 이미 있는 프로비저닝되어 있는 리소스 중에서 pem 키를 재생성하느라고 오류가 났었다. 그러는 중에 jerry의 state 파일을 TFC에 적용되는 바람에 tfstate 파일이 tom이 생성한 리소스를 state에서 지워버린 모양이었다.

글서 수동으로 리소스를 다 지워주고 나서 state 파일을 맞춰주느라 진땀을 뺐다 ㅠ

암튼간에……. TFC에 state를 업데이트하고 나면 tom jerry 둘다 plan 시에 No changes. Your infrastructure matches the configuration. 메세지를 받을 수 있다!

그리고 terraform은 작업자가 apply를 수행하게 되면 state 파일을 잠가 버린다.

Untitled 1

이는 TFC에서도 동일하게 잠금된 것을 확인할 수 있다. 이는 다른 작업자가 작업 중에 접근하지 못하도록 마지막 상태에 무결성을 확보하는 일이다

실습 과제

  1. Terraform Cloud를 State 백엔드로 구성
    • Workspace 이름 : terraform-edu-part1-assessment
    • 실행 모드는 local
     cloud {
          organization = "6ain-study"         # 생성한 ORG 이름 지정
          hostname     = "app.terraform.io"      # default
        
          workspaces {
            name = "terraform-edu-part1-assessment"  # 없으면 생성됨
          }
        }
    

    위와 같이 수정하고 TFC에서 execution mode를 local로 수정해 주었다

    Untitled 2

  2. AWS 공통 Tag : Project = “workshop”

     tags = {
           Project = "workshop"
         }
    

    aws 프로바이더 블록 하위에 태그명을 변경해 주었다.

  3. aws_instance는 반복문을 사용해 3개 구성

     resource "aws_instance" "hashicat" {
       count = 3
     ...생략...
     }
        
     resource "null_resource" "configure-cat-app" {
     	count = 3
     ...생략...
     }
    

    aws_instance 블록과 null_resource 블록에서 count 문을 사용해서 복제했다

    count문을 사용했으면 저 리소스를 사용할 때 index 번호도 같이 수정해 주어야 한다.

    이는 [count.index]를 사용하면 된다.

    세 개의 인스턴스에 접속해야 하므로 host 정보를 수정해 주었다

     host        = aws_instance.hashicat[count.index].public_ip
    
  4. EIP를 제거하고 EC2에서 public ip를 자체 사용하도록 구성

    우선 EIP 관련 블록 aws_eipaws_eip_association을 주석 처리해 주었다.

     resource "aws_subnet" "hashicat" {
     	map_public_ip_on_launch = true
     ...생략...
     }
    

    위 설정은 public subnet 생성할 때 이 서브넷에서 시작하는 인스턴스들이 public ip를 가질지 아닐지를 설정해 주는 것이다.

     aws_instance.hashicat[count.index].public_ip
    

    그리고 기존에는 aws_eip.hashicat.public_ip으로 되어 있는 부분을 위와 같이 인스턴스 퍼블릭 아이피를 사용할 수 있게 수정해 주었다.

     output "catapp_url" {
       value = {
         for instance in aws_instance.hashicat:
           instance.id => "http://${instance.public_dns}"
       }
     }
        
     output "catapp_ip" {
       value = {
         for instance in aws_instance.hashicat:
           instance.id => "http://${instance.public_ip}"
       }
     }
    

    마지막으로 output에 원하는 형태로 반복적인 결과를 출력할 수 있게 for문을 사용하였다.

  5. placeholder 변수는 아래 3가지가 각각의 aws_instance에 적용되도록 구성

     placekitten.com
     placebear.com
     placedog.net
    
     variable "placeholder" {
       default     = [
         "placekitten.com",
         "placebear.com",
         "placedog.net"
       ]
       description = "Image-as-a-service URL. Some other fun ones to try are fillmurray.com, placecage.com, placebeard.it, loremflickr.com, baconmockup.com, placeimg.com, placebear.com, placeskull.com, stevensegallery.com, placedog.net"
     }
    

    variables.tf 파일에 위와 같이 변수를 추가해 주었다.

    그리고 variables에서 변수 세 개를 가져오므로 placeholder를 사용하는 곳에 ${var.placeholder[count.index]}로 변경해 주었다.

  6. 접속 테스트

    Untitled 3

    Untitled 4

결론

TFC 사용의 유용성을 알았다.

TFC를 사용하면 무료로 State 파일의 암호화 관리도 자동으로 해 주고, UI로 직관적으로 관리가 가능하며 State 파일을 별도 외부 스토리지말고 테라폼 클라우드로 관리가 가능하다.

지금 글 내용에는 안들어가 있지만 프로비저닝된 리소스 상태나 output이나 손쉽게 확인할 수 있다.

마지막으로 실습 과제를 진행하면서 테라폼 사용에 서툴러서 좀 헤맸지만 그래도 무슨 문법을 사용해야 하고 어디를 수정해야 할지는 바로 감이 왔다

테라폼 블록에서의 Argument와 Attribute에 능숙해 지면 금방 테라폼을 쓸 수 있을 거 같다!

Categories:

Updated:

Leave a comment