Terraform/Study_과제

6주차 - 협업

in-cloud 2023. 8. 11. 17:59
<참고> 테라폼으로 시작하는 IaC - 김민수, 김재준, 이규석, 이유종 저 한빛미디어

 

모든 실습은 Mac OS 기준으로 작성되었습니다

 

7. 협업

- 인프라 규모가 커지고 관리 팀원이 늘어날 수록 구성 코드 관리가 필요하다.

- 공동 작업자는 작성된 코드를 점검하고 서로의 코드를 학습할 수 있는 협업 환경을 구성하게 된다.

- 협업 환경 구성 요소는 코드를 다수의 작업자가 유지 ㅂ수 할 수 있도록 돕는 VCS 와 테라폼 State를 중앙화하는 중앙 저장소가 대표적.

- 협업 과정에서 고려 요소(아래 그림 참조)

[그림 출처 https://kschoi728.tistory.com/139] 테라폼 협업을 위한 중앙 저장소 고려사항 단계

  • 유형 1 : VCS, 중앙 저장소 없음
    • 동일한 대상을 관리하는 여러 작업자는 동일한 프로비저닝을  위해 각자 자신이 작성한 코드를 수동으로 공유가 필요
    • 작업자의 수가 늘어날수록 코드 동기화는 어려워지고, 각 작업자가 작성한 코드를 병합하기도 어렵다
    • → VCS 도구 도입 고민 시점
  • 유형 2 : VCS(SVN, Git), 중앙 저장소 도입
    • 형성관리 도구를 통해 여러 작업자가 동일한 테라폼 코드를 공유해 구성 작업
      • 변경 이력 관리 및 이전 버전으로 롤백 가능
    • 공유파일은 테라폼 구성파일과 State ← 테라폼 프로비저닝의 결과물로 데이터 저장소와 같음
    • 작업자가 서로 다른 프로비저닝한 State 결과를 공유를 위해서 백엔드(공유 저장소) 설정을 제공
  • 유형 3 : VCS(Github), 중앙 저장소 도입
    • 테라폼 코드 형상관리를 위한 중앙 저장소 + State 백엔드 → 작업자는 개별적으로 프로비저닝을 테스트하고 완성된 코드를 공유
      • State 는 중앙 관리되어, 작업자가 프로비저닝을 수행하면 원격 State의 상태를 확인하고 프로비저닝 수행

7.1 형상관리 도구(VCS)

  •  VCS : Version Control System
    • SVN : 중앙 저장소에서 코드와 히스토리를 관리하는 방식
    • Git : 분산형 관리 시스템으로 작업 환경에서도 별도로 코드 히스토리를 관리하고 중앙 저장소와 동기화

7.1.1 Git

- Git을 사용하면 중앙 저장소와 코드를 동기화 하지 않아도 같은 파일을 여러 명이 작업할 수 있다.

- 따라서 개발과 배포 버전 관리를 별도로 진행할 수 있다.

  • Git은 코드 형상관리를 작업 환경인 Local Repository와 Remote Repository에 저장할 수 있다.
  • 작업자가 작업환경에서 코드 커밋을 수행하면 로컬 저장소에 적용된다.
  • 공동 작업을 위해 이 저장소의 내용을 다른 사람에게도 제공하려면 중앙 저장소가 필요하고 이를 리모트 저장소가 담당한다.
    • 로컬저장소 : 작업자 로컬 환경에 저장되는 개인 전용 저장소
    • 리모트저장소 : 코드 형상관리 이력과 코드가 원격지에서 관리도고 여러 사람이 공유하는 저장소
    • Git 용어 설명
    • 용어 표현 설명
      branch 브랜치 분기, “main” 또는 “master”의 주 브랜치에서 갈라져 나온 별도의 버전의 작업 공간
      checkout 체크아웃 지정한 브랜치로 전환하는 작업, 파일이 대상 브랜치의 색인과 파일로 업데이트됨
      clone 복제 리모트 저장소로부터 로컬 저장소로 복제
      fork 포크/분기 리모트 저장소로부터 로컬 저장소로 복제하지만 새로운 저장소로 구성
      fetch 페치 리모트 저장소에서 오브젝트를 로컬 저장소로 가져오는 동작
      HEAD 헤드 현재 체크아웃된 브랜치의 최종 변경을 가리키는 이름
      add 추가 작업 중인 공간에서 다음 커밋으로 변경을 기록하기 전까지 변경분을 추적
      commit 커밋 로컬 저장소에 변경 사항을 기록
      merge 머지/병합 깃으로 관리하는 오브젝트의 불일치한 내용을 병합
      pull 풀/가져오기 브랜치의 내용을 리모트 저장소로부터 fetch 한 후 병합
      push 푸시/저장하기 로컬의 수정 내용을 리모트 저장소에 저장
      pull request PR/풀 리퀘스트 분기된 브랜치 또는 저장소에서 지정한 저장소의 브랜치로의 병합 요청
  • 코드 추가와 변경 사항을 저장소에 기록하려면 커밋이라는 절차가 필요하다.
  • 커밋을 수행하면 이전 커밋 시점부터 현재까지의 변경 이력이 기록된다.
# Git 버전 확인
$ git --version
git version 2.41.0

7.1.2 리모트 저장소

  • 깃은 리모트저장소가 있어야 코드 수준에서 다른 작업자와 협업할 수 있다.
  • 리모트 저장소를 관리하면서 커밋된 데이터를 올리고, 받는 것이다.
  • 리모트 저장소는 인터넷이나 네트워크 상에 존재하는 곳일 수도 있지만 로컬 시스템일 수도 있다.
  • 대표적 리모트 저장소 : GitHub, GitLab, BitBucket등
♣ 실습을 위해 GitHub 계정 발급 및 인증 토큰을 미리 발급해두도록 하자

7.2 코드 관리

  •  깃허브 포크
    • 다른 리모트 저장소를 본인 소유의 저장소로 복사할 수 있다.
    • 포크한 저장소는 원본 저장소와 연결이 되어 있으므로 이후 변경 사항을 원본 저장소에 적용하는 요청(Pull Request) 가능
    • https://github.com/terraform101/terraform-aws-collaboration​ fork하여 새로운 GitHub 리포지토리 생성 [Create fork]
      > fork 가 정상적으로 확인되었다.

  • 공유 제외 대상
    • .gitignore 정의
      • .terraform 디렉터리 : init 실행 시 작성되므로 제외
      • .tfstate 파일 : 프로비저닝 결과 데이터 소스 정보, 민감 데이터가 포함, 다른 사용자가 같은 State 파일을 사용하는 경우 인프라 불합치 유발
      • tfvars 파일. 프로비저닝 시 적용할 변수 값을 보관하는 파일로, 작업자 마다 별도 변수 사용
      • 시크릿파일 : 인프라 구성에 필요한 시크릿 정보 파일
      • terraformrc 파일 : 작업자의 CLI 설정 파일
# .gitignore
# Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log
crash.*.log

# Exclude all .tfvars files, which are likely to contain sensitive data, such as
# password, private keys, and other secrets. These should not be part of version 
# control as they are data points which are potentially sensitive and subject 
# to change depending on the environment.
*.tfvars
*.tfvars.json

# no creds
*.pem

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Include override files you do wish to add to version control using negated pattern
# !example_override.tf

# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*

# Ignore CLI configuration files
.terraformrc
terraform.rc

로컬 저장소에 복제

- 로컬 작업 환경을 위해 리모트 저장소의 내용을 복제

# clone
MyGit=bringgree //내 GitHub 계정
git clone https://github.com/$MyGit/terraform-aws-collaboration
'terraform-aws-collaboration'에 복제합니다...
remote: Enumerating objects: 20, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 20 (delta 5), reused 3 (delta 3), pack-reused 12
오브젝트를 받는 중: 100% (20/20), 9.34 KiB | 9.34 MiB/s, 완료.
델타를 알아내는 중: 100% (5/5), 완료.

# 확인
$ tree terraform-aws-collaboration
terraform-aws-collaboration
├── LICENSE
├── README.md
├── files
│   └── deploy_app.sh
├── main.tf
├── outputs.tf
├── terraform.tfvars.example
└── variables.tf

$ cd terraform-aws-collaboration
$ git remote get-url origin
https://github.com/bringgreen/terraform-aws-collaboration

- Push Test : test.txt

#
echo "T101 Study" >> test.txt

#
$ git add test.txt
$ git commit -m "first commit"
$ git push

# Git 자격 증명 설정
$ git config --global user.name $MyGit
$ git config --global user.email bringgreen@gmail.com
$ cat ~/.gitconfig

# push 실행을 위해서 로그인 정보 입력
$ git push
오브젝트 나열하는 중: 4, 완료.
오브젝트 개수 세는 중: 100% (4/4), 완료.
Delta compression using up to 10 threads
오브젝트 압축하는 중: 100% (2/2), 완료.
오브젝트 쓰는 중: 100% (3/3), 292 bytes | 292.00 KiB/s, 완료.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/bringgreen/terraform-aws-collaboration
   191d776..d378576  main -> main

# 로그인 정보 입력 방안2
export GITHUB_USER=<깃허브 계정 정보>
export GITHUB_TOKEN=<토큰 정보>

>> 위에서 추가한 test.txt가 추가된 것을 확인할 수 있다.

  • 코드 협업을 위한 1인 2역을 준비 : 복제한 디렉터리 변경 및 추가 복사
    • terraform-aws-collaboration-tom : tom 작업 디렉터리
    • terraform-aws-collaboration-jerry : jerry 작업 디렉터리
$ cd ..
$ mv terraform-aws-collaboration terraform-aws-collaboration-tom
$ cp -r terraform-aws-collaboration-tom terraform-aws-collabotarion-jerry

Push & Pull

  • 커밋된 코드는 로컬 저장소에 기록되며, 푸시를 하기 전까지는 리모트 저장소에 공유되지 않음 -> 또한 작업 중 풀을 통해 리모트 저장소의 변경 사항을 로컬 저장소에 반영
  • tom 디렉터리의 main.tf 파일 코드 내용 수정
# main.tf
...
provider "aws" {
  region = var.region
  default_tags {
    tags = {
      Project = "T101-Study-6week"
    }
  }
}
...
  • 수정된 코드를 커밋하고 리모트 저장소에 푸시
#
$ cd terraform-aws-collaboration-tom
$ git remote get-url origin
$ git add main.tf
$ git commit -m "add default tags & project name"
$ git push
오브젝트 나열하는 중: 5, 완료.
오브젝트 개수 세는 중: 100% (5/5), 완료.
Delta compression using up to 10 threads
오브젝트 압축하는 중: 100% (3/3), 완료.
오브젝트 쓰는 중: 100% (3/3), 325 bytes | 325.00 KiB/s, 완료.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To https://github.com/bringgreen/terraform-aws-collaboration
   d378576..5deac1b  main -> main
  • 내 깃헙 사이트에 main.tf 파일 코드 내용이 수정되었다!!

  • jerry 디렉터리에서 작업
#
$ cd ..
$ cd terraform-aws-collaboration-jerry
$ git remote get-url origin
https://github.com/bringgreen/terraform-aws-collaboration

$ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 1 (delta 0), pack-reused 0
오브젝트 묶음 푸는 중: 100% (3/3), 305 bytes | 76.00 KiB/s, 완료.
https://github.com/bringgreen/terraform-aws-collaboration URL에서
   d378576..5deac1b  main       -> origin/main
업데이트 중 d378576..5deac1b
Fast-forward
 main.tf | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)


$ cat main.tf |grep Project
      Project = "T101-Study-6week"
  • 이번에는 tom과 jerry 양쪽에서 default_tags에 Owner 항목을 추가하고 저장 시도

  jerry 디렉터리 tom 디렉터리
main.tf 파일 코드 내용 수정 ...
provider "aws" {
    region = var.region
    default_tags {
        tags = {
            Project = "T101-Study-6week"
            Owner = "jerry"
         }
     }
}
...
...
provider "aws" {
    region = var.region
    default_tags {
        tags = {
            Project = "T101-Study-6week"
            Owner = "tom"
        }
    }
}
...
수정된 코드를 커밋하고 리모트 저장소에 푸시 cd terraform-aws-collaboration-jerry
git add main.tf
git commit -m "add default tags & Owner is jerry"
git push
cd ..
cd terraform-aws-collaboration-tom
git add main.tf
git commit -m "add default tags & Owner is tom"
# tom의 루트 모듈 변경 코드를 리모트 저장소에 보낼 때 실패
git push
push
실행결과
오브젝트 나열하는 중: 5, 완료.
오브젝트 개수 세는 중: 100% (5/5), 완료.
Delta compression using up to 10 threads
오브젝트 압축하는 중: 100% (3/3), 완료.
오브젝트 쓰는 중: 100% (3/3), 329 bytes | 329.00 KiB/s, 완료.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To https://github.com/bringgreen/terraform-aws-collaboration
   5deac1b..0f6dd8d  main -> main
 ! [rejected]        main -> main (fetch first)
error: 레퍼런스를 'https://github.com/bringgreen/terraform-aws-collaboration'에 푸시하는데 실패했습니다
힌트: 리모트에 로컬에 없는 사항이 들어 있으므로 업데이트가
힌트: 거부되었습니다. 이 상황은 보통 또 다른 저장소에서 같은
힌트: 저장소로 푸시할 때 발생합니다.  푸시하기 전에
힌트: ('git pull ...' 등 명령으로) 리모트 변경 사항을 먼저
힌트: 포함해야 합니다.
힌트: 자세한 정보는 'git push --help'의 "Note about fast-forwards' 부분을
힌트: 참고하십시오.

  • 푸시 전 풀을 먼저 수행해 리모트의 변경 사항을 로컬과 비교한 후 필요할 때 수정해 푸시하는 습관이 필요하다
  • 변경 사항에 충돌이 없는 경우 자동으로 커밋 지점이 병합된다
  • 풀 동작에 충돌이 있을 것으로 가정해 옵션을 붙여 수행 : git rebase
$ git pull --no-rebase
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 1 (delta 0), pack-reused 0
오브젝트 묶음 푸는 중: 100% (3/3), 309 bytes | 77.00 KiB/s, 완료.
https://github.com/bringgreen/terraform-aws-collaboration URL에서
   5deac1b..0f6dd8d  main       -> origin/main
자동 병합: main.tf
충돌 (내용): main.tf에 병합 충돌
자동 병합이 실패했습니다. 충돌을 바로잡고 결과물을 커밋하십시오.

  • 로컬 저장소와 리모트 저장소의 충돌 내용 표기
  • === 위는 로컬저장소, 아래는 리모트 저장ㅅ오 내용
  • '현재 변경사항 수락' 클릭!(회색 글씨)

 

 

 

 

 

#
$ terraform fmt
│ Error: Invalid expression
│ 
│   on main.tf line 23, in provider "aws":
│   23: <<<<<<< HEAD
│ 
│ Expected the start of an expression, but found an invalid expression token.

$ git add main.tf
$ git commit -m "change default tags Owner"
$ git push
오브젝트 나열하는 중: 8, 완료.
오브젝트 개수 세는 중: 100% (8/8), 완료.
Delta compression using up to 10 threads
오브젝트 압축하는 중: 100% (4/4), 완료.
오브젝트 쓰는 중: 100% (4/4), 440 bytes | 440.00 KiB/s, 완료.
Total 4 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3), completed with 2 local objects.
To https://github.com/bringgreen/terraform-aws-collaboration
   0f6dd8d..787fc05  main -> main


$ cat main.tf | grep Owner
      Owner = "tom"

풀 리퀘스트 Pull Request

  • 푸시와 풀로도 코드 협업이 가능하지만 다른 사람의 커밋을 확인하기가 쉽지 않고, 리모트 저장소에 푸시할 때가 되어야 충돌 상황을 확인하게 된다는 단점
  • 작업된 테라폼 코드에 대한 자연스러운 리뷰와 메인스트림 main branch의 병합을 관리하기 위해 풀 리퀘스트 방식을 사용한다
  • 깃으로 코드를 관리할 때 주로 사용되는 브랜치 branch를 이용하는 방안으로, 작업자가 코드 수정을 위해 메인과 별개의 브랜치를 생성하고 작업 후 본인의 브랜치를 푸시하고 코드 관리자에게 검토 후 병합을 요청하는 방식이다.

코드 작성자 1단계

  • 이번에도 코드 충돌을 유발하기 위해 앞 실습의 결과로 tom이 메인 브랜치에 푸시한 상황에서 jerry가 Owner 항목을 jerry & tom 으로 변경하고 싶어한다
  • 메인 브랜치에 바로 푸시하지 않고 작업을 위한 브랜치를 생성하고 작업을 수행한다
#
cd ..
cd terraform-aws-collaboration-jerry

# 최신 코드 pull 해두기
$ git pull
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 4 (delta 3), reused 4 (delta 3), pack-reused 0
오브젝트 묶음 푸는 중: 100% (4/4), 420 bytes | 70.00 KiB/s, 완료.
https://github.com/bringgreen/terraform-aws-collaboration URL에서
   0f6dd8d..787fc05  main       -> origin/main
업데이트 중 0f6dd8d..787fc05
Fast-forward
 main.tf | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
 
 
# 현재 브렌치 확인
git branch
* main

<q로 빠져나옴>

# 새로 만든 jerry-owner-task 브랜치로 전환
$ git checkout -b jerry-owner-task
새로 만든 'jerry-owner-task' 브랜치로 전환합니다
$ git branch
* jerry-owner-task
  main
  • jerry 디렉터리의 main.tf 파일 코드 내용 수정
...
provider "aws" {
  region = var.region
  default_tags {
    tags = {
      Project = "T101-Study-6week"
      Owner = "jerry & tom"
    }
  }
}
...
  • jerry에서 작업중인 브랜치로 코드를 푸시
#
$ git add main.tf
$ git commit -m "add default tags & Owner is jerrh & tom"
[jerry-owner-task 12202dc] add default tags & Owner is jerry & tom
 1 file changed, 1 insertion(+), 1 deletion(-)
 
$ git push origin jerry-owner-task
오브젝트 나열하는 중: 5, 완료.
오브젝트 개수 세는 중: 100% (5/5), 완료.
Delta compression using up to 10 threads
오브젝트 압축하는 중: 100% (3/3), 완료.
오브젝트 쓰는 중: 100% (3/3), 317 bytes | 317.00 KiB/s, 완료.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
remote: 
remote: Create a pull request for 'jerry-owner-task' on GitHub by visiting:
remote:      https://github.com/bringgreen/terraform-aws-collaboration/pull/new/jerry-owner-task
remote: 
To https://github.com/bringgreen/terraform-aws-collaboration
 * [new branch]      jerry-owner-task -> jerry-owner-task

  • Files changed 클릭 : 변경 내용 검토

  • 풀 리퀘스트는 코드를 머지 Merge 하는 관리자에게 자신이 수정한 내용을 메인 코드병합해달라는 요청을 하는 것이다.
  • 푸시로 코드를 머지하는 것과는 다르게 풀 리퀘스트는 코드 리뷰를 강제하기 때문에 코드 변경 사항을 검토할 수 있다

코드 관리자

  • 리모트 저장소의 쓰기 권한이 있는 관리자는 풀 리퀘스트가 발생하면 코드를 기존 코드에 머지할 권한을 갖는다.
  • 풀 리퀘스트에는 요청자의 변경 사항이 표기된다. 풀 리퀘스트 수행 방식은 세 가지를 지원하나 여기서는 기본 설정대로 진행한다
    1. Create a merge commit : 브랜치의 모든 커밋이 병헙을 통해 기본 브랜치에 추가
    2. Squash and Merge : 브랜치의 변경 이력을 모두 합쳐 새로운 커밋을 생성하고 메인에 추가
    3. Rebase and Merge : 브랜치 변경 이력이 각각 메인에 추가
      >> Pull requests > add default tags & Owner is jerry & tom 선택 >> Merge pull request의 Create a merge commit 선택 >> pull reuest test ok 입력 > Confirm merge 클릭

코드 작성자 2단계

  • 머지가 완료되면 작업자는 메인 브랜치로 이동 후 풀을 수행해 코드를 동기화하고 기존 브랜치를 삭제한다
# terraform-aws-collaboration-jerry 디렉터리에서 아래 작업 수행
$ git checkout main
'main' 브랜치로 전환합니다
브랜치가 'origin/main'에 맞게 업데이트된 상태입니다.

$ git pull
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
오브젝트 묶음 푸는 중: 100% (1/1), 654 bytes | 654.00 KiB/s, 완료.
https://github.com/bringgreen/terraform-aws-collaboration URL에서
   787fc05..5837397  main       -> origin/main
업데이트 중 787fc05..5837397
Fast-forward
 main.tf | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
 
$ git branch -d jerry-owner-task
jerry-owner-task 브랜치 삭제 (과거 12202dc).

$ git branch
* main

코드 협업자

  • 머지 이후 코드를 작업하는 작업자는 개별 로컬 저장소에 새로운 코드를 가져올 수 있다
# terraform-aws-collaboration-tom 디렉터리에서 아래 작업 수행
$ cd ..
$ cd terraform-aws-collaboration-tom
$ git checkout main
M       main.tf
이미 'main'에 있습니다
브랜치가 'origin/main'에 맞게 업데이트된 상태입니다.


$ git pull
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 2), reused 1 (delta 0), pack-reused 0
오브젝트 묶음 푸는 중: 100% (4/4), 939 bytes | 234.00 KiB/s, 완료.
https://github.com/bringgreen/terraform-aws-collaboration URL에서
   787fc05..5837397  main             -> origin/main
 * [새로운 브랜치]   jerry-owner-task -> origin/jerry-owner-task
업데이트 중 787fc05..5837397
error: 다음 파일의 로컬 변경 사항을 병합 때문에 덮어 쓰게 됩니다:
        main.tf
병합하기 전에 변경 사항을 커밋하거나 스태시하십시오.
중지함

# 위와 같이 정상 동작이 안되어서 그냥 강제로 덮어씌우기로 함.
$ git fetch --all
$ git reset --hard origin/main
HEAD의 현재 위치는 5837397입니다 Merge pull request #1 from bringgreen/jerry-owner-task

$ git pull origin main        
https://github.com/bringgreen/terraform-aws-collaboration URL에서
 * branch            main       -> FETCH_HEAD
이미 업데이트 상태입니다.

 

7.3 State 백엔드

  • 구성 목적
    • 관리 : 지속적인 State 백업을 위해서 local 이외의 저장소가 필요
    • 공유 : 다수의 작업자가 동일한 State로 접근해 프로비저닝하기 위한 공유 스토리지 필요
    • 격리 : 민감한 데이터가 State 파일에 저장될 가능성을 고려하여, 각각의 환경에 따라 접근 권한 제어 필요
  • 구성 가능한 백엔드와 설명
종류 설명
remote Terraform Cloud/Enterprise 의 워크스페이를 의미하며, 1.1.0부터 remote 백엔드에서 cloud로 명시화
local 기본 백엔드로 로컬 파일 시스템에 구성
azurerm Azure Blob Storage
consul 하시코프 Consul의 KV(Key-Value Store)를 사용
cos Tencent Cloud Storage
gcs Google Cloud Storage
http GET, POST, DELETE를 지원하는 REST 클라이언트 대상
kubernetes Kubernetes Secret
oss Alibaba Cloud Object Storage Service
pg Postgres Database
s3 Amazon S3 버킷을 사용하고, 추가로 DynamoDB 설정 시 State 잠금 및 일관성 검사 지원

7.3.1 Terraform Cloud (TFC) 백엔드

  • 하시코프에서 프로비저닝 대상과 별개로 State를 관리할 수 있도록 SaaS 환경인 TFC를 제공하며 State 관리 기능은 무상을 제공 - 링크
  • 제공 기능 : 기본 기능 무료, State 히스토리 관리, State lock 기본 제공, State 변경에 대한 비교 기능
  • Free Plan 업데이트 : 사용자 5명 → 리소스 500개, 보안 기능(SSO, Sentinel/OPA로 Policy 사용) - 링크
 

[アップデート]Terraform Cloudの料金プランが変わりました Freeプランでもセキュリティ系機能が利

Terraform Cloudの料金プランが変わりました。 Terraform Cloud updates plans with an enhanced Free tier and more flexibility 変更 …

dev.classmethod.jp

 

- TFC 계정 생성

  • https://app.terraform.io/ 링크 접속 후 하단에 free account 클릭 → 계정 생성 후 이메일 확인 → 암호 입력 후 로그인
  • TFC 초기 설정 화면 → 사용자의 고유 조직 이름 생성 : <nickname>-org >> kimjihee-org

  • CLI 환경에서 TFC 사용을 위한 자격 증명
# 
terraform login
yes 입력
  • 위에서 yes를 누르면 토큰 생성하는 화면이 뜬다. 토큰을 생성 후 아래 처럼 입력하고 토큰 확인!
Terraform will request an API token for app.terraform.io using your browser.

If login is successful, Terraform will store the token in plain text in
the following file for use by subsequent commands:
    /Users/mzc01-kimdoran/.terraform.d/credentials.tfrc.json

Do you want to proceed?
  Only 'yes' will be accepted to confirm.

  Enter a value: yes


---------------------------------------------------------------------------------

Terraform must now open a web browser to the tokens page for app.terraform.io.

If a browser does not open this automatically, open the following URL to proceed:
    https://app.terraform.io/app/settings/tokens?source=terraform-login


---------------------------------------------------------------------------------

Generate a token using your browser, and copy-paste it into this prompt.

Terraform will store the token in plain text in the following file
for use by subsequent commands:
    /Users/mzc01-kimdoran/.terraform.d/credentials.tfrc.json

Token for app.terraform.io:
  Enter a value: "토큰 정보 입력"


Retrieved token for user kimjihee


---------------------------------------------------------------------------------

                                          -                                
                                          -----                           -
                                          ---------                      --
                                          ---------  -                -----
                                           ---------  ------        -------
                                             -------  ---------  ----------
                                                ----  ---------- ----------
                                                  --  ---------- ----------
   Welcome to Terraform Cloud!                     -  ---------- -------
                                                      ---  ----- ---
   Documentation: terraform.io/docs/cloud             --------   -
                                                      ----------
                                                      ----------
                                                       ---------
                                                           -----
                                                               -


   New to TFC? Follow these steps to instantly apply an example configuration:

   $ git clone https://github.com/hashicorp/tfc-getting-started.git
   $ cd tfc-getting-started
   $ scripts/setup.sh


$ cat ~/.terraform.d/credentials.tfrc.json | jq
{
  "credentials": {
    "app.terraform.io": {
      "token": "토큰 정보가 여기에 표시됨"
    }
  }
}
  • 샘플테스트
# New to TFC? Follow these steps to instantly apply an example configuration:
$ git clone https://github.com/hashicorp/tfc-getting-started.git
$ cd tfc-getting-started
$ tree
.
├── LICENSE
├── README.md
├── backend.tf
├── main.tf
├── provider.tf
└── scripts
    └── setup.sh

2 directories, 6 files

$ scripts/setup.sh
--------------------------------------------------------------------------
Getting Started with Terraform Cloud
-------------------------------------------------------------------------

Terraform Cloud offers secure, easy-to-use remote state management and allows
you to run Terraform remotely in a controlled environment. Terraform Cloud runs
can be performed on demand or triggered automatically by various events.

This script will set up everything you need to get started. You'll be
applying some example infrastructure - for free - in less than a minute.

First, we'll do some setup and configure Terraform to use Terraform Cloud.

Press any key to continue (ctrl-c to quit):

Creating an organization and workspace...

Writing Terraform Cloud configuration to backend.tf...

========================================================================

Ready to go; the example configuration is set up to use Terraform Cloud!

An example workspace named 'getting-started' was created for you.
You can view this workspace in the Terraform Cloud UI here:
https://app.terraform.io/app/example-org-0b8c54/workspaces/getting-started

Next, we'll run 'terraform init' to initialize the backend and providers:

$ terraform init

Press any key to continue (ctrl-c to quit):


Initializing Terraform Cloud...

Initializing provider plugins...
- Finding latest version of hashicorp/fakewebservices...
- Installing hashicorp/fakewebservices v0.2.3...
- Installed hashicorp/fakewebservices v0.2.3 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform Cloud has been successfully initialized!

You may now begin working with Terraform Cloud. Try running "terraform plan" to
see any changes that are required for your infrastructure.

If you ever set or change modules or Terraform Settings, run "terraform init"
again to reinitialize your working directory.

...

========================================================================

Now it’s time for 'terraform plan', to see what changes Terraform will perform:

$ terraform plan

Press any key to continue (ctrl-c to quit):

Running plan in Terraform Cloud. Output will stream here. Pressing Ctrl-C
will stop streaming the logs, but will not stop the plan running remotely.

Preparing the remote plan...

To view this run in a browser, visit:
https://app.terraform.io/app/example-org-0b8c54/getting-started/runs/run-8CSyVoxEb4yxhRTY

Waiting for the plan to start...

Terraform v1.5.2
on linux_amd64
Initializing plugins and modules...

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # fakewebservices_database.prod_db will be created
  + resource "fakewebservices_database" "prod_db" {
      + id   = (known after apply)
      + name = "Production DB"
      + size = 256
    }

  # fakewebservices_load_balancer.primary_lb will be created
  + resource "fakewebservices_load_balancer" "primary_lb" {
      + id      = (known after apply)
      + name    = "Primary Load Balancer"
      + servers = [
          + "Server 1",
          + "Server 2",
        ]
    }

  # fakewebservices_server.servers[0] will be created
  + resource "fakewebservices_server" "servers" {
      + id   = (known after apply)
      + name = "Server 1"
      + type = "t2.micro"
      + vpc  = "Primary VPC"
    }

  # fakewebservices_server.servers[1] will be created
  + resource "fakewebservices_server" "servers" {
      + id   = (known after apply)
      + name = "Server 2"
      + type = "t2.micro"
      + vpc  = "Primary VPC"
    }

  # fakewebservices_vpc.primary_vpc will be created
  + resource "fakewebservices_vpc" "primary_vpc" {
      + cidr_block = "0.0.0.0/1"
      + id         = (known after apply)
      + name       = "Primary VPC"
    }

Plan: 5 to add, 0 to change, 0 to destroy.

...

========================================================================

The plan is complete!

This plan was initiated from your local machine, but executed within
Terraform Cloud!

Terraform Cloud runs Terraform on disposable virtual machines in
its own cloud infrastructure. This 'remote execution' helps provide consistency
and visibility for critical provisioning operations. It also enables notifications,
version control integration, and powerful features like Sentinel policy enforcement
and cost estimation (shown in the output above).

To actually make changes, we'll run 'terraform apply'. We'll also auto-approve
the result, since this is an example:

$ terraform apply -auto-approve

Press any key to continue (ctrl-c to quit):

Running apply in Terraform Cloud. Output will stream here. Pressing Ctrl-C
will cancel the remote apply if it's still pending. If the apply started it
will stop streaming the logs, but will not stop the apply running remotely.

Preparing the remote apply...

To view this run in a browser, visit:
https://app.terraform.io/app/example-org-0b8c54/getting-started/runs/run-jVyfbURP9gepuNXs

Waiting for the plan to start...

Terraform v1.5.2
on linux_amd64
Initializing plugins and modules...

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # fakewebservices_database.prod_db will be created
  + resource "fakewebservices_database" "prod_db" {
      + id   = (known after apply)
      + name = "Production DB"
      + size = 256
    }

  # fakewebservices_load_balancer.primary_lb will be created
  + resource "fakewebservices_load_balancer" "primary_lb" {
      + id      = (known after apply)
      + name    = "Primary Load Balancer"
      + servers = [
          + "Server 1",
          + "Server 2",
        ]
    }

  # fakewebservices_server.servers[0] will be created
  + resource "fakewebservices_server" "servers" {
      + id   = (known after apply)
      + name = "Server 1"
      + type = "t2.micro"
      + vpc  = "Primary VPC"
    }

  # fakewebservices_server.servers[1] will be created
  + resource "fakewebservices_server" "servers" {
      + id   = (known after apply)
      + name = "Server 2"
      + type = "t2.micro"
      + vpc  = "Primary VPC"
    }

  # fakewebservices_vpc.primary_vpc will be created
  + resource "fakewebservices_vpc" "primary_vpc" {
      + cidr_block = "0.0.0.0/1"
      + id         = (known after apply)
      + name       = "Primary VPC"
    }

Plan: 5 to add, 0 to change, 0 to destroy.

fakewebservices_vpc.primary_vpc: Creating...
fakewebservices_database.prod_db: Creating...
fakewebservices_vpc.primary_vpc: Creation complete after 0s [id=fakevpc-ApNSZK8uDhY6qXUF]
fakewebservices_server.servers[0]: Creating...
fakewebservices_server.servers[1]: Creating...
fakewebservices_database.prod_db: Creation complete after 0s [id=fakedb-ruzEHfTBt6b8qix4]
fakewebservices_server.servers[0]: Creation complete after 0s [id=fakeserver-z6Z5Ty5PJkeCQ4Lo]
fakewebservices_server.servers[1]: Creation complete after 0s [id=fakeserver-BRD74A94NrZPRMbb]
fakewebservices_load_balancer.primary_lb: Creating...
fakewebservices_load_balancer.primary_lb: Creation complete after 0s [id=fakelb-UQjxgpGR9o2fWrGm]

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.


...

========================================================================

You did it! You just provisioned infrastructure with Terraform Cloud!

The organization we created here has a 30-day free trial of the Team &
Governance tier features. After the trial ends, you'll be moved to the Free tier.

You now have:

  * Workspaces for organizing your infrastructure. Terraform Cloud manages
    infrastructure collections with workspaces instead of directories. You
    can view your workspace here:
    https://app.terraform.io/app/example-org-0b8c54/workspaces/getting-started
  * Remote state management, with the ability to share outputs across
    workspaces. We've set up state management for you in your current
    workspace, and you can reference state from other workspaces using
    the 'terraform_remote_state' data source.
  * Much more!

To see the mock infrastructure you just provisioned and continue exploring
Terraform Cloud, visit:
https://app.terraform.io/fake-web-services

7.3.2 백엔드 구성

  • TFC State 실습 : p238~243
    • tom 루트 모듈과 jerry 루트 모듈을 사용해 공통 백엔드 구성과 동작을 확인 → 두 작업자가 동일한 AWS 인프라를 프로비저닝하기를 원하는 상황
    • tom 루트 모듈에서 실행
#
$ cd ..
$ cd terraform-aws-collaboration-tom

#
$ terraform init
$ terraform plan -var=prefix=dev
$ terraform apply -auto-approve -var=prefix=dev
...
Apply complete! Resources: 12 added, 0 changed, 0 destroyed.

Outputs:

catapp_ip = "http://43.201.233.18"
catapp_url = "http://ec2-43-201-233-18.ap-northeast-2.compute.amazonaws.com"


# 확인
$ terraform workspace list
* default

$ terraform state list
data.aws_ami.ubuntu
aws_eip.hashicat
aws_eip_association.hashicat
aws_instance.hashicat
aws_internet_gateway.hashicat
aws_key_pair.hashicat
aws_route_table.hashicat
aws_route_table_association.hashicat
aws_security_group.hashicat
aws_subnet.hashicat
aws_vpc.hashicat
null_resource.configure-cat-app
tls_private_key.hashicat

$ ls terraform.tfstate*
terraform.tfstate

$ terraform output
catapp_ip = "http://43.201.233.18"
catapp_url = "http://ec2-43-201-233-18.ap-northeast-2.compute.amazonaws.com"
  • -
    • jerry 루트 모듈에서 실행 : plan 결과가 어떤가요?
#
$ cd ..
$ cd terraform-aws-collaboration-jerry

# plan 결과가 어떤가요?
$ terraform init && terraform plan -var=prefix=dev
...
Changes to Outputs:
  + catapp_ip  = (known after apply)
  + catapp_url = (known after apply)

──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

TFC를 통하여 작업 결과 공유 설정

  • TFC의 workspaces는 CLI에서의 workspace처럼 테라폼 구성과는 별개로 State를 관리하는 단위다
  • tom 루트 모듈에 main.tf 파일 수정
# main.tf
terraform {
  cloud {
    organization = "kimjihee"         # 생성한 ORG 이름 지정
    hostname     = "app.terraform.io"      # default

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

#
$ terraform init
: yes
Initializing provider plugins...
- Reusing previous version of hashicorp/null from the dependency lock file
- Reusing previous version of hashicorp/tls from the dependency lock file
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/null v3.2.1
- Using previously-installed hashicorp/tls v4.0.4
- Using previously-installed hashicorp/aws v4.67.0


# 파일 내용이 어떤가요?
$ ls terraform.tfstate*
terraform.tfstate               terraform.tfstate.backup

$ cat terraform.tfstate
  • TFC 전용 워크스페이스(State 백엔드 역할만 수행) 확인 → 선택 후 좌측에 Settings 클릭 → General
    • 실행 모드 변경 : Execution Mode 에서 Local 선택 → 하단의 Save settings 클릭하여 변경 적용
      • Remote : 테라폼 실행을 Terraform Cloud에서 수행
      • Local : 테라폼 실행은 작업자 환경 또는 연결된 외부 환경에서 실행해 State만을 동기화
      • Agent : 테라폼 실행을 사용자 지정 Agent(설치된 서버 환경)에서 수행 (Business 플랜에서 활성화)
    • 이후 [States] 탭에서 terraform init을 통해 마이그레이션된 State 업로드 정보 확인

  • 백엔드 저장소 동작 확인
# plan 결과가 어떤가요?
$ rm -rf terraform.tfstate*
$ terraform plan -var=prefix=dev
...
No changes. Your infrastructure matches the configuration.
...
  • push
$ git add main.tf
$ git commit -m "tfc state"
[main 4256c60] tfc state
 1 file changed, 7 insertions(+), 7 deletions(-)
 
$ git push
오브젝트 나열하는 중: 5, 완료.
오브젝트 개수 세는 중: 100% (5/5), 완료.
Delta compression using up to 10 threads
오브젝트 압축하는 중: 100% (3/3), 완료.
오브젝트 쓰는 중: 100% (3/3), 358 bytes | 358.00 KiB/s, 완료.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To https://github.com/bringgreen/terraform-aws-collaboration
   5837397..4256c60  main -> main
  • jerry 루트 모듈에서 확인
#
$ cd ..
$ cd terraform-aws-collaboration-jerry
$ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 2), reused 3 (delta 2), pack-reused 0
오브젝트 묶음 푸는 중: 100% (3/3), 338 bytes | 84.00 KiB/s, 완료.
https://github.com/bringgreen/terraform-aws-collaboration URL에서
   5837397..4256c60  main       -> origin/main
업데이트 중 5837397..4256c60
Fast-forward
 main.tf | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
 
 
# plan 결과 어떻게 되나요?
$ terraform init
$ terraform plan -var=prefix=dev
...
No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

7.3.3 백엔드 활용

- TFC State 잠금 기능 : 프로비저닝 수행 시 동일한 State 접근 못하게 잠금 → State 마지막 상태에 대한 무결성 확보

  • Jerry가 프로비저닝 실행 시 변경 사항이 발생하도록 코드를 수정한다고 가정하여, null_resource에 정의한 내용이 항상 수행되도록 trigger를 추가함
    • trigger에 timestamp() 함수를 지정하면 테라폼 프로비저닝 실행마다 다른 값이 저장되므로 항상 변경이 유발함
  • jerry 루트 모듈에서 main.tf 파일 코드 변경 및 실행
# main.tf
resource "null_resource" "configure-cat-app" {
  depends_on = [aws_eip_association.hashicat]

  triggers = {
    build_number = timestamp()
  }
  
  

# 
$ terraform apply -var=prefix=dev
...
Enter a value: <대기>
  • 신규 터미널에서 tom 루트 모듈에서 실행
$ cd terraform-aws-collaboration-tom
$ terraform apply -var=prefix=dev

╷
│ Error: Error acquiring the state lock
│ 
│ Error message: workspace already locked (lock ID: "kimjihee/collaboration")
│ Lock Info:
│   ID:        c395310c-996d-eee3-d614-f929de79d14a
│   Path:      
│   Operation: OperationTypeApply
│   Who:       mzc01-kimdoran@MZC01-KIMDORAN.local
│   Version:   1.5.2
│   Created:   2023-08-11 08:45:37.891372 +0000 UTC
│   Info:      
│ 
│ 
│ Terraform acquires a state lock to protect the state from being written
│ by multiple users at the same time. Please resolve the issue above and try
│ again. For most commands, you can disable locking with the "-lock=false"
│ flag, but this is not recommended.
╵
  • TFC Workspace 에 State 확인

  • jerry 루트 모듈에서 yes 실행
# 
terraform apply -var=prefix=dev
...
Enter a value: yes
  • TFC Workspace 에 State → [Changes in this version] 에서 변경 사항 확인

- 실습 완료 후 리소스 삭제

  1. AWS 리소스 삭제 : terraform destroy -auto-approve -var=prefix=dev
  2. TFC에 워크스페이스 삭제 : Setting → Destruction and Deletion 클릭 후 삭제
  3. Github Repo 삭제 : terraform-aws-collaboration → Setting → Delete this repository
  4. 로컬 디렉터리 삭제 : terraform-aws-collaboration-tom , terraform-aws-collaboration-jerry
 

Terraformのデプロイパイプラインに使用できるツールをまとめてみた | DevelopersIO

「Terraformデプロイパイプラインを作るなら、どのツールが自分の組織にあっているのだろう?」 Terraformのデプロイパイプラインの実装方法は、選択肢が多くて迷ってしまいます。 この記事

dev.classmethod.jp

 

7.4 실습

- 목표 : 아래 깃허브 저장소를 복제해 아래 조건에 만족하는 코드를 작성

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

 

GitHub - terraform101/terraform-aws-collaboration: [Chapter 7] Collaboration Code Example

[Chapter 7] Collaboration Code Example. Contribute to terraform101/terraform-aws-collaboration development by creating an account on GitHub.

github.com

 

조건 
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
  • 풀이 예제는 ‘example’ 브랜치에 있다. 조건에 맞게 작성한 코드와 비교해보고 더 나은 방안을 찾아보자!
    • 반복문에 count와 for_each를 활용할 수 있다
    • module을 활용하는 방안도 있다

'Terraform > Study_과제' 카테고리의 다른 글

7주차 - 워크플로  (0) 2023.08.20
4주차 - State & 모듈  (0) 2023.07.29
3주차 - Terraform 기본 사용 3/3  (0) 2023.07.23
2주차 - Terraform 기본 사용 2/3  (0) 2023.07.15
1주차 - Terraform 기본 사용 1/3  (0) 2023.07.09