Gitlab 으로 terraform 상태(state) 관리하기
Terraform 을 여러명이 사용할때에 필요한 것이 Terraform 의 상태를 변경하지 못하도록 하는 것이다. terraform 을 실행할때마다 상태(state) 파일이 갱신되는데, 여러사람이 같이 일을 할때에는 이 파일을 공유해서 사용해야 한다.
대부분이 terraform state 파일을 AWS S3 저장소와 Dynamo DB 를 이용해 lock 을 거는 방식이 많이 거론된다. 이 방법은 AWS 클라우드를 사용해야 한다는 강제가 필요한데, 물론 Terraform 이 클라우드를 빠르게 코드로 만들도록 도와주기 때문에 어짜피 AWS 클라우드 인프라를 구성할 거면 S3 를 사용하는 것이 문제가 되지 않는다.
또, 인터넷상에 보면 Gitlab 을 이용한 상태관리 관련한 문서, 심지여 Gitlab 의 공식문서조차도 잘못된 내용이 있어 이 글을 작성한다.
하지만 꼭 AWS S3와 DynamoDB 를 이용해야만 가능하냐 하는 질문에는 그렇지 않다는 답이 존재한다. 이 문서는 AWS 클라우드 서비스를 이용하지 않고 Gitlab 을 이용해 Terraform 의 상태(state) 파일을 관리하는 방법에 대해서 알아 본다.
GitLab
매우 훌륭한 시스템이다. 소스코드 저장소는 물론이고 Container Registry, Terraform state 저장소, CI/CD, Wiki, Ticket 시스템등 거의 모든 IT 업무를 한곳에서 수행할 수 있게 해준다.
Terraform state 파일 저장소를 네이티브 기능으로 사용할 수 있도록 만들어져 있어서 이걸 이용하면 클라우드 저장소의 도움 없이도 Terraform 의 상태 파일을 관리 할 수 있다.
저장소 생성하기
Terraform 상태 파일 저장을 위한 저장소를 만들어 준다.
Gitlab 에서 저장소 생성은 단순한 절차임으로 큰 어려움 없이 생성이 된다.
Terraform 파일 작성
간단하게 Terraform 파일을 작성해 보자. provider 와 backend, 그리고 AWS Resource 중에 Security Group 하나를 만들어 보자. 파일은 main.tf 와 backend.tf 두개로 작성 됐다.
main.tf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
provider "aws" { access_key = "" secret_key = "" alias = "seoul" region = "ap-northeast-2" } resource "aws_security_group" "terraform-example-sg" { provider = aws.seoul name = "terraform-example-sg" ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } |
backend.tf
1 2 3 4 5 6 7 8 9 10 11 |
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } backend "http" {} } |
위 코드를 보면 변수 3개가 보인다. $PROJECT_ID 는 Gitlab 에 프로젝트 Settings -> General 을 보면 번호가 부여된 Project ID 를 알 수 있다.
API 통신을 위해서 인증 토큰이 필요하다. 공식문서에는 사용자 계정 토큰을 발행하라고 되어 있다. 사용자 계정 토큰은 사용자 Profile -> Access Tokens 에서 생성이 가능하다.
하지만, 여기서 한가지 주의해야 할게 있다. 인터넷을 검색해보면 개인 토큰으로는 인증 실패가 발생한다고 하는데, API 통신을 위해서는 Maintainer 권한을 필요로 한다. 그러니까 계정의 권한이 Maintainer 를 가지고 있지 않는다면 토큰을 발행이 되어도 인증에 실패하게 된다.
Gitlab 에서 API 통신을 위해서는 적절한 권한을 필요로하게 되는데, Maintainer 권한이 필요하게 된다. 이 말은 Access Tokens 은 Maintainer 권한만 있다면 사용자 구분 없이 사용이 가능하게 된다.
그러면, 프로젝트 Access Tokens 을 이용할 수 있지 않을까? 당연히 가능 하다. 앞서 생성한 프로젝트 -> Settings -> Access tokens 에서 토큰 발생이 가능하다. 프로젝트 토큰 발생은 사용자도 함게 생성되는데, 그 사용자는 bot 이다.
한가지 주의해야 할 것은 프로젝트 access token 을 생성할때에 권한(role) 을 Maintainer 권한으로 해야 한다. 그리고 이렇게 생성을 하게 되면 bot 계정이 생성이 되는데, 이 계정이 access token 소유자가 된다.
이 계정의 Id 는 @ 로 시작하는 문자열이다.
어떤 Access Tokens 을 사용해도 상관은 없다. 핵심은 권한(Role) 이다. 반드시 Maintainer 권한이 있어야 한다.
Terraform init
이제 Terraform 을 초기화 한. 초기화는 다음과 같은 명령어를 사용 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
export TF_USERNAME=project_21_bot_213a2c1faa436d68d8984837afaa3460 export TF_PASSWORD=glpat-92txtMPCAK-gnbWvrC7C export TF_STATE_NAME=default export PROJECT_ID="21" export TF_ADDRESS="https://gitlab.systemv.local:8001/api/v4/projects/${PROJECT_ID}/terraform/state/${TF_STATE_NAME}" terraform init \ -backend-config="address=${TF_ADDRESS}" \ -backend-config="lock_address=${TF_ADDRESS}/lock" \ -backend-config="unlock_address=${TF_ADDRESS}/lock" \ -backend-config="username=$TF_USERNAME" \ -backend-config="password=$TF_PASSWORD" \ -backend-config="lock_method=POST" \ -backend-config="unlock_method=DELETE" \ -backend-config="retry_wait_min=5" |
TF_USERNAME 은 Project Access Token 소유자인 bot 이고 TF_PASSWORD 는 Project Access Token 이다.
terraform plan
이 명령어를 실행하면 드디어 Gitlab 저장소에 Terraform state 에 상태 파일이 생성된다. Operate -> Terraform states 에서 확인이 가능하다.
결론
인터넷을 살펴보면 Gitlab 을 이용한 Terraform state 관련 내용에서 Personal Access Token 으로 되지 않는다는 내용이 많다. 핵심은 Access Token 의 권한이다. 반드시 Maintainer 권한이 있어야 하며 이 권한만 있다면 Personal 이던 Project 이던 상관이 없다.