본문 바로가기
개발/Terraform on NaverCloud

Terraform 프로바이더 개발 세미나 1

by 컴쏘 2023. 7. 19.

Terraform providers

  • Cloud providers (aws, NAVER Cloud, Azure, Google Cloud … )
  • PaaS, SaaS providers (k8s, github, docker, … )
  • other APIs

위의 것들을 terraform에서 사용할 수 있도록 제공해주는 provider

 

현재 Terraform on NAVER Cloud는 NAVER Cloud 플랫폼에 Cloud 서비스를 Terraform에서 사용할 수 있도록 제공하는 provider를 개발하고 있다.

  • 해당 provider를 통해서 terraform config 파일을 작성해서 원하는 리소스를 생성해서 프로비저닝 할 수 있게 된다.

Terraform providers 종류

How Terraform works

기본적인 Terraform 동작 과정

Terraform 동작 원리

  • 사용자가 만들고 싶은 인프라 리소스를 terraform config 파일(.tf 파일)로 작성
  • 작성한 리소스를 Terraform core가 제공하는 CLI(Command Line Interface)에 terraform apply 명령어 입력하면 실제 리소스들을 Terraform provider (plugin) 을 통해서 NAVER Cloud 플랫폼에 실제 인프라로 생성, 변경하는 등의 프로비저닝 작업을 하게 된다.
  • 생성된 리소스들에 대한 정보는 Terraform state 파일(.tfstate)에 저장

세부적으로 살펴보기

예시) Terraform으로 VPC 서버 생성을 해보자.

.tf파일 작성으로 실제 프로바이더 개발 예시

.tf 파일

  • vpc 생성
  • subnet 생성
  • server 생성

프로바이더

  • NAVER Cloud 내부에
  • VPC 내부에
  • Subnet 내부에
  • Server

최초 리소스 생성 시

terraform plan

plan 명령을 통한 확인

  • 처음 리소스를 생성할 때 바로 apply를 적용하는 것이 아닌, plan으로 리소스들이 어떻게 생성되는지 확인할 수 있다.
  • 작성한 terraform config (.tf) 파일을 가지고 plan 과정을 최초에 1번 수행하게 되면, 기존의 terraform cloud 인프라를 확인한 후에 아무것도 없는 것을 알기 때문에 새롭게 추가되는 것을 terraform plan을 통해 알 수 있다.

terraform apply

apply를 통한 리소스 생성

  • 동일한 리소스를 가지고 terraform apply를 수행하게 되면, 해당 리소스들이 존재하지 않는 상태이므로 프로바이더를 통해 해당 리소스들을 생성하게 된다.
  • 각각의 api를 통해서 vpc를 생성하게 된다.

apply의 마지막 과정

apply의 마지막 과정

  • 생성을 하고 나면 apply의 마지막 과정이 실제 cloud 인프라에 생성된 리소스들에 대한 정보를 read API를 통해 리소스 정보를 가져온다.
  • 가져온 정보들을 최종적으로 terraform state 파일에 저장하게 된다.

apply 과정을 모두 거치고 나면, config 파일, state 파일, 실제 provider가 모두 동일한 상태로 유지된다.

 

리소스 삭제하는 경우

 

주석 처리하기

삭제할 리소스 주석 처리하기

  • 주석 처리(주석 처리를 하면 해당 리소스를 삭제한 것과 같은 효과가 있다.)

apply 하기 전에 plan 적용

plan 먼저 해보기

  • plan을 수행하기 되면, 사용자가 작성한 config와 Terraform state를 비교하게 된다.
  • 비교하기 전에 Cloud 인프라에 있는 리소스 정보를 read API를 통해 다시 한번 확인
    • Cloud 인프라에 있는 환경들이 terraform과 무관하게 Console을 이용해서 수정 혹은 변경이 생길 수도 있다.
    • 따라서, 항상 read API를 통해 상태를 확인해줘야 한다.
  • 사용자가 변경한 config와 state 파일을 비교해서 변경이 발생한 부분을 terraform core에서 인지하게 되고, 그 결과로 CLI의 output으로 1개의 리소스가 삭제될 것임을 명시

apply 적용

apply 적용

  • apply 적용 시 state와 비교해서 config 서버가 삭제될 것임을 인지한다.
  • 서버가 삭제될 것을 인지하고 state파일로 가면 아직 있기 때문에 실제 인프라로 간다.
  • 실제 인프라에서 서버를 삭제하도록 delete API를 호출하여 서버 삭제
  • state 파일에서 다시 read API해서 state 파일에도 반영해주기

최종 모습

최종 모습

  • 최종적으로는 .tf 파일과 .state 파일과 provider가 동일한 상태를 가지게 된다.

리소스 추가하는 경우

리소스 추가 후 plan 실행

  • 리소스 추가 후 plan 실행
  • 동일한 과정을 거쳐서 하나의 리소스가 추가될 것임을 명시

apply 실행 시

state 파일 업데이트

  • apply를 실행하면 state에는 없지만, config에는 있기 때문에 서버 리소스를 create API로 생성하기

terraform과 NAVER Cloud의 동작 과정

  • read API로 다시 state 파일을 업데이트 한다.
  • 이렇게 되면, 최종적으로 .tf 파일과 .state 파일과 provider가 동일한 상태를 가지게 된다.

실제 Terraform Core는 NAVER Cloud와 어떻게 동작할까?

  • Terraform provider(plugin)의 CRUD operation을 통해, 인프라를 반영하고 상태를 업데이트
  • terraform core와 terraform provider는 RPC(Remote Procedure Call)를 통해서 메시지를 주고받는다.

Q. RPC?

A. 원격의 어떠한 작업을 수행하는 것 (추상적인 개념이다.)

RPC의 구체적인 구현체는 HTTP의 REST API 같은 것이다.

여기서는 gRPC를 사용해서 terraform core와 provider가 메시지를 주고 받는다.

현재 NAVER Cloud on Terraform 에서는 Terraform Core와 Terraform provider가 각각의 process로 동작하게 된다.

Terraform provider 만들기

필요한 것

1) CRUD를 지원하는 REST API (NCLOUD API)

API

서비스들에 대한 API를 제공하고 있다. (NAVER Cloud에서 API 가이드를 통해 확인해볼 수 있다.)

 

2) REST API를 호출하는 GO CLIENT LIBRARY (NCLOUD GO SDK)

Client Library

Terraform과 Terraform provider는 Go lang으로 개발되고 있다.

NAVER Cloud API를 Client와 쉽게 소통할 수 있도록 해주는 Client 라이브러리가 중간에 있다.

 

현재 Terraform on NAVER Cloud는 ncloud-sdk-go-v2를 제공하고 있다.

  • 개발할 때 ncloud-sdk-go-v2를 밀접하게 사용하고 있기 때문에 ncloud-sdk-go-v2 내용을 개발할 때 많이 참고하게 될 것이다.

Q. NCLOUD GO SDK의 구성 ?

A. Go SDK를 자동으로 만들자.

Go SDK의 구성

  • API Gate Way를 통해 약 1000개가 넘는 요청과 응답을 관리한다.

API Gate Way를 사용하였을 때

swagger meta data를 이용한 SDK 추출

  • Swagger를 통해서 원하는 API를 json 형태로 된 SDK 자동 생성 가능

모델로 코드를 추출

따라서 ncloud-sdk-go-v2는 API Gate Way에 있는 모델들을 바탕으로 Swagger를 통해서 자동으로 생성된 API이다.

 

만약 개발을 하다가 부족하거나 잘못된 부분을 발견한다면 멘토님께 요청드리기! (이 부분은 멘티가 컨트롤 할 수 없는 부분)

 

3) Terraform plugin

terraform plugin

terraform provider는 ncloud-sdk-go Client를 사용해서 NAVER Cloud의 리소스들을 생성, 삭제 등의 작업을 수행

 

그림으로 봤을 때는 분리되어 보이지만, 사실상 provider와 library는 하나의 쌍이기 때문에 하나의 프로세스라고 생각하면 된다.

Terraform provider 개발 어떻게 해야할까?

Terraform plugin 개발

Terraform plugin이 해야 할 일

provider 선언

  • API 호출에 사용되는 포함된 라이브러리의 인증 및 초기화
  • 서비스에 매핑 되는 리소스 정의

Terraform plugin 프로젝트 구조

변경 전

  • Resource와 Datasource는 /ncloud 에 위치 (과거)
    • 변경 후 (현재) : 각각의 서비스 별로 분리가 되었다.
    • 변경 전에는 모든 것이 하나의 패키지 안에 포함되어 있어서 관리의 어려움이 있었다.
    • 변경 후 (현재)는 관리의 차원에서 리팩토링을 하게 되었다.
  • 예제들은 /example 그리고 문서는 /docs
    • 처음에 terraform 사용할 때, 예제를 참고해서 따라 진행해보는 것을 추천한다.
    • 하다가 모르는 것이 생긴다면 ncloud documentation 참고해보기
  • Provider 정의는 provider.go
  • terraform-provider-scaffolding을 통해 빠른 시작 가능
    • terraform-provider-scaffolding은 시작할 때의 참고할 수 있는 template 같은 것이다.
    • 전체적인 구조를 보고 싶을 때 참고해볼 수 있다.

Provider 정의

provider 정의 - Schema 정의

1) Schema 정의

인증키, 리전 등이 메타 정보를 정의

provider에서 access_key, secret_key, region, suport_vpc 등의 값들을 schema로 정의하게 된다.

이때, provider 정의할 때 각각의 필드의 타입을 정의해줄 수 있다.

 

2) Resource와 Data Source들을 정의

Resource 정의

  • Provider에서 DataSourceMap필드, ResourceMap 필드가 있다.
  • config 파일을 통해 리소스를 정의해서 사용하면 (그림에서 정리(x) → 정의(o)) 클라우드 리소스들을 CRUD 할 수 있게 된다.

3) ConfigureFunc 추가하기

provider를 정의할 때는 ConfigureFunc을 추가해야 한다.

→ Provider가 API를 호출하기 위한 인증이나 초기화를 수행하게 되는데, 이를 위한 사전 작업이다.

 

ConfigureFunc

  • API 호출에 사용되는 포함된 라이브러리의 인증 및 초기화
  • 메타정보 설정 (리전 코드)

사용자가 config 파일을 작성하고 나서 apply를 해서 vpc를 생성한다고 가정했을 때, provider를 구성할 때 configure가 한번 호출된다.

configureFunc 동작 과정

  • configure가 호출될 때, 인자로 ResourceData를 가져오게 된다.
  • ResourceData 안에는 사용자가 입력한 값들이 담겨있다.
  • 따라서, 사용자가 입력한 값들을 providerConfigure에 전달을 하게 된다.
  • providerConfigure 함수 안에서 인증, 클라우드 사용과 관련한 초기화 등과 같은 로직을 담을 수 있다. (사전 작업을 수행하는 것)
  • vpc를 생성하게 될 때, 이 초기화 정보를 가지고 vpc를 생성하게 된다.

여기까지 하면 기본적인 provider 구성은 완료되었다.

Resource 개발하기 (ex. vpc)

console - terraform config 파일 비교

  • Schema Attributes과 Type을 정의
  • VPC는 이름과 IP주소 범위를 String형 입력으로 받음

Schema Attributes과 Type을 정의

Schema 정보 추가

  • Attributes는 name과 ipv4_cidr_block으로 지정
  • Types는 모두 TypeString으로 지정

여러가지 속성들을 정의할 수 있다.

 

Schema Behaviors 정의

Schema Behaviors 정의
Schema Behaviors 정의

  • name은 필수 값이 아니기 때문에 Optional (넣어도 되고 안 넣어도 되고)
  • ipv4_cidr_block는 필수라서 Required
  • ipv4_cidr_block은 수정을 지원하지 않기 때문에 ForceNew(재생성)
  • computed : 실제 인프라가 cloud에 생성되고 난 이후에, cloud를 통해서 얻을 수 있는 정보들을 정보를 입력하지 않았을 때 cloud에서 생성되는 default 정보를 넣을 수 있음을 의미
  • 언제 어느 속성을 넣어야 하는지에 대한 정보는 개발에 도움이 된다.

ValidateFunc

ValidateFunc

  • 속성을 정의할 때 ValidateFunc 사용 가능
  • 입력 값이 format에 맞는지 검증 가능

직접 구현한 ValidateFunc 예시

  • Terraform SDK에서 기본적으로 제공하는 API도 있고, 직접 구현할 수도 있음
  • 나온 예제는 직접 구현한 것임
  • 조건에 부합하지 않으면 plan이나 apply에서 Error 발생
  • 실제 사용자가 API를 호출하기 전에 빠르게 바로 Error를 받을 수 있고 구체적인 Error가 어떤 것이 잘못되었는지 확인 가능
  • 따라서, 이러한 기능을 제공할 수 있다면, 제공하는 것이 좋다.

CRUD Func

CRUD Func 구현

  • Terraform core가 해당 구현체를 통해 인프라를 생성/수정/삭제
  • Read operation을 통해 **state(.tfstate)**를 refresh 함
  • CRUD 각각을 구현하면 된다.

OSSCA Terraform on NAVER Cloud 
"이원철 멘토님"의 Terraform 프로바이더 개발 세미나 1 내용을
terraform provider 개발 시 참고하기 위해 공부한 내용을 정리한 글입니다.