Terraform 인증과 원격 state 준비
Cloud Shell의 배포 계정, 필요한 IAM 권한, state를 보관할 Cloud Storage backend
Cloud Shell은 브라우저로 로그인한 Google 계정을 사용한다. 터미널의 계정과 프로젝트가 서버를 만들 대상과 같아야 한다. Terraform state는 접근 권한을 제한한 Cloud Storage 버킷에 보관한다.
선수 조건
프로젝트 ID, 결제 연결과 예산 알림을 확인했고 Cloud Shell에서
terraform version이 실행돼야 한다.
지금 사용하는 계정과 프로젝트
Cloud Shell 오른쪽 위의 프로젝트 이름과 터미널의 설정이 다를 수 있다. 아래 명령은 현재 계정과 프로젝트 ID를 출력한다.
확인
gcloud auth list --filter=status:ACTIVE \
--format="value(account)"
gcloud config get-value project
첫 명령은 본인의 Google 계정 하나를, 둘째 명령은 02편에서 선택한 프로젝트 ID를
출력해야 한다. (unset)이나 다른 프로젝트가 나오면 다음 명령으로 고친다.
조건부 실행: 프로젝트가 다를 때
gcloud config set project "내-프로젝트-ID"
Updated property [core/project].가 정상 결과다. 이후 명령은 이 프로젝트에 리소스를
만든다. ID를 고치지 못했다면 여기서 멈춘다.
Cloud Shell과 내 컴퓨터의 인증은 다르다
Cloud Shell에는 브라우저에서 선택한 계정의 인증 정보가 이미 연결돼 있다.
gcloud auth application-default login을 다시 실행하지 않는다.
macOS나 WSL에서 같은 예제를 실행할 때는 로컬 터미널에서 아래 순서가 필요하다.
조건부 실행: Cloud Shell이 아닌 경우
gcloud init
gcloud auth login
gcloud auth application-default login
마지막 명령이 만드는 Application Default Credentials, 줄여서 ADC를 Google Provider가 사용한다. 인증 파일을 예제 디렉터리에 복사하거나 Git에 올리면 안 된다.
배포 계정에 필요한 권한
Terraform은 독자의 계정으로 API를 켜고 네트워크, VM, 서비스 계정과 버킷을 관리한다. IAM은 어떤 계정이 어떤 작업을 할 수 있는지 정하는 Google Cloud 권한 체계다. 혼자 소유한 실습 프로젝트라면 프로젝트 Owner 권한으로 진행할 수 있다. 회사나 공동 프로젝트에서는 관리자에게 다음 역할의 목적을 설명하고 필요한 범위만 요청한다.
| 역할 | 서버 구성에서 하는 일 |
|---|---|
roles/serviceusage.serviceUsageAdmin | 필요한 Google API 활성화 |
roles/compute.admin | VPC, 방화벽, IP, 디스크와 VM 관리 |
roles/storage.admin | state와 백업 버킷, 버킷 IAM 관리 |
roles/iam.serviceAccountAdmin | Minecraft VM 전용 서비스 계정 생성 |
roles/iam.serviceAccountUser | 만든 서비스 계정을 VM에 연결 |
roles/resourcemanager.projectIamAdmin | 05편에서 본인 계정에 OS Login 프로젝트 역할 연결 |
역할을 직접 추가할 수 없는 계정으로 계속하면 plan이나 apply 도중 403이 난다.
공유 프로젝트에서는 임의로 권한을 넓히지 말고 관리자에게 요청한다.
현재 결제 연결도 읽기 전용 명령으로 확인할 수 있다.
확인
export PROJECT_ID="$(gcloud config get-value project)"
gcloud billing projects describe "${PROJECT_ID}" \
--format="value(billingEnabled)"
export로 만든 값은 지금 열려 있는 터미널 세션에만 존재한다. Cloud Shell은 한동안
사용하지 않으면 세션이 끊기고, 새 탭이나 재접속에서는 이 값이 모두 사라진다. 이
연재의 명령이 갑자기 빈 값이나 (unset) 오류를 내면 가장 먼저 이 경우를
의심하고, 그 글에서 등장한 export 줄을 위에서부터 다시 실행한 뒤 이어 간다.
echo "${PROJECT_ID}"처럼 echo로 현재 값이 남아 있는지 언제든 확인할 수 있다.
True가 나와야 05편에서 VM을 만들 수 있다. 이 명령은 결제를 연결하거나 리소스를
만들지 않는다.
state 전용 버킷 만들기
Terraform state에는 실제 리소스 ID와 구성이 들어간다. Cloud Storage backend는 브라우저 탭을 닫은 뒤에도 state를 보관하고 state를 쓰는 동안 다른 실행의 쓰기를 잠근다.
새 프로젝트에서는 먼저 Cloud Storage API를 사용할 수 있게 한다.
실행
gcloud services enable storage.googleapis.com \
--project="${PROJECT_ID}"
Operation ... finished successfully.가 정상 결과다. API를 활성화한 뒤 생기는 Storage
사용량에는 비용이 붙는다. 로컬 검증에서는 API를 활성화하지 않았다.
버킷 이름은 전 세계 Cloud Storage에서 고유하다. 개인 이름, 이메일과 회사 내부
식별자는 넣지 않는다. 아래 예시는 프로젝트 ID 뒤에 -tfstate를 붙인다. 이미 사용
중이면 짧은 임의 문자열을 더한다.
비용 발생: Cloud Storage state 버킷 생성
export STATE_BUCKET="${PROJECT_ID}-tfstate"
gcloud storage buckets create "gs://${STATE_BUCKET}" \
--project="${PROJECT_ID}" \
--location="ASIA-NORTHEAST3" \
--uniform-bucket-level-access
gcloud storage buckets update "gs://${STATE_BUCKET}" \
--versioning
첫 명령은 Cloud Storage 리소스를 만든다. 저장량과 작업에 따라 소액의 과금 가능성이 있다. 예산 알림을 설정하지 않았거나 어떤 과금도 원하지 않는다면 실행하지 말고 여기서 중단한다. 로컬 검증에서는 버킷을 만들지 않았다.
성공하면 Creating gs://...와 버전 관리가 활성화됐다는 메시지가 나온다. 이름 충돌은
409로 표시된다. 그때 STATE_BUCKET 값을 바꿔 두 명령을 다시 실행한다.
버전 관리는 덮어쓰거나 삭제한 state 객체의 이전 세대를 남긴다. 이전 세대도 저장 용량을 사용한다. 서버 운영을 끝낼 때는 state와 남은 비용 정리에서 모든 세대를 확인하고 삭제한다. 장기간 운영하며 중간 세대를 줄이려면 별도 lifecycle 정책과 보존 기간을 정해야 한다.
본인만 사용하는 프로젝트에서는 현재 계정에 state 객체 관리 권한을 명시한다.
실행
export ADMIN_ACCOUNT="$(
gcloud auth list --filter=status:ACTIVE \
--format="value(account)"
)"
gcloud storage buckets add-iam-policy-binding \
"gs://${STATE_BUCKET}" \
--member="user:${ADMIN_ACCOUNT}" \
--role="roles/storage.objectAdmin"
정상 결과에는 roles/storage.objectAdmin과 현재 계정이 보인다. 다른 사람의 이메일이
들어갔다면 backend를 설정하지 말고 IAM binding을 바로잡는다.
예제 다운로드와 backend 설정
Cloud Shell 홈 디렉터리에 예제를 내려받는다.
실행
cd "${HOME}"
curl --fail --location \
"https://juntiger-assets.pages.dev/minecraft-one-root.zip" \
--output minecraft-one-root.zip
unzip -q minecraft-one-root.zip
cd minecraft-one-root
같은 이름의 디렉터리가 이미 있다면 덮어쓰지 않는다. 이전 작업을 계속할지, 새 디렉터리 이름으로 풀지 먼저 결정한다.
backend 샘플을 복사하고 nano 편집기로 연다. nano에서는 화살표 키로 이동해
값을 고친 뒤 Control+O, Enter로 저장하고 Control+X로 닫는다.
실행
cp backend.hcl.example backend.hcl
nano backend.hcl
파일에는 실제 state 버킷 이름과 이 서버만 사용할 경로를 넣는다.
bucket = "내-state-버킷-이름"
prefix = "minecraft/one-root"
backend.hcl은 Git에 올리지 않는다. 버킷 이름도 공개 저장소에 남길 필요가 없다.
원격 backend 초기화
실행
terraform init -backend-config=backend.hcl
처음 실행하면 Provider를 내려받고 .terraform.lock.hcl을 만든다. 마지막에 아래
문장이 나오면 성공이다.
Terraform has been successfully initialized!
Failed to get existing workspaces가 나오면 버킷 이름, 로그인 계정과
roles/storage.objectAdmin을 다시 확인한다. 처음 만든 디렉터리라면 옮길 로컬
state가 없어서 아무 질문 없이 끝나는 것이 정상이다. 만약 로컬 state를 원격으로
복사할지 묻는 프롬프트가 나온다면 이 디렉터리를 이전에 실행한 적이 있다는
뜻이다. 그 state가 무엇인지 설명할 수 있을 때만 yes를 입력하고, 기억에 없는
state라면 답하지 말고 Control+C로 중단한 뒤 원인을 확인한다.
완료 체크
확인
terraform providers
gcloud storage ls "gs://${STATE_BUCKET}"
Google Provider가 보이고 버킷 조회가 성공하면 준비가 끝났다. 버킷이 비어 있는 것은 정상이다. state 객체는 실제 계획이나 적용을 시작한 뒤 생길 수 있다.
초기화가 끝나면
Minecraft 서버 JAR와 Terraform 입력값 준비에서
같은 작업 디렉터리에 terraform.tfvars를 만든다.
참고
Comments
아직 댓글이 없습니다. 첫 댓글을 남겨주세요.
검토 대기 중