Terraform 을 통한 multi vSphere VM 배포 (hello-world)

INYEONG KIM·2024년 8월 24일
post-thumbnail

개요

Multi Cloud 환경을 염두해둔 범용적인 VM 프로비저닝 환경에 대한 리서칭
(vSphere 기반 On-Prem, AWS, GCP 등)

다수의 vSphere VM을 배포하는 방법에는 여러 방법이 존재한다.

기존에는 vSphere PowerCli나 vCenter REST API를 활용하는 방법을 주로 사용하였다. (특히 vSphere PowerCli)

다만 vSphere 환경에서만 유효하였고, 스크립트 형태로 작성되다보니 비교적 다수의 사용자환경에 대한 구성상의 어려움과 스크립트의 작성내용을 여러 사용자가 쉽게 수정할 수 없다는 이슈가 발생하였다.

Terraform 이라는 툴을 활용하면 비교적 직관적인 형태로 인프라에 대한 Code를 공유 및 변경이 가능할 것으로 예상되어 관련하여 테스트를 진행하였다.

Terraform 주요 가이드

Terraform install (macOS)

brew update-reset && brew update
brew tap hashicorp/tap
brew install hashicorp/tap/terraform

terraform binary hello world

간단한 사용을 통해 terraform 커맨드가 정상 설치 되었는지 확인

# 1. main.tf 파일을 생성한 뒤
vi main.tf
resource "null_resource" "default" {
  provisioner "local-exec" {
    command = "echo 'Hello World'"
  }
}

# 2. terraform init
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/null...
- Installing hashicorp/null v3.2.2...
- Installed hashicorp/null v3.2.2 (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 has been successfully initialized!

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

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.


# 3. main.tf 실행에 대한 dry-run (실제 배포 X)
$ terraform plan

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:

  # null_resource.default will be created
  + resource "null_resource" "default" {
      + id = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.
### 현재 작업 공간에 대한 전체적인 실행 내용 및 결과를 1차적으로 보여준다



# 4. 실제 배포
$ terraform apply

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:

  # null_resource.default will be created
  + resource "null_resource" "default" {
      + id = (known after apply)
    }

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

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

null_resource.default: Creating...
null_resource.default: Provisioning with 'local-exec'...
null_resource.default (local-exec): Executing: ["/bin/sh" "-c" "echo 'Hello World'"]
null_resource.default (local-exec): Hello World
null_resource.default: Creation complete after 0s [id=6748890877075846659]

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

참고 사항

terraform init 과 apply 를 수행하였다면 현재 경로에 terraform.tfstate 파일이 생성된다.

$ tree .
.
├── main.tf
└── terraform.tfstate		# new

이 파일은 현재 작업 공간에 대한 배포 내용을 저장하는 파일로, terraform apply 및 plan 등의 명령은 해당 파일과 현재 작성된 .tf 파일을 비교하여 변경에 대한 내용을 적용한다.

즉, 아래 예시의 실제 인프라 배포 시에 variable 또는 main 파일의 내용을 바꾸더라고하더라도, terraform.tfstate 파일에 대한 정리가 되지 않을 경우 신규 인프라 배포가 아닌 기존 내용의 변경 이 발생하므로 배포 전 확인이 필요하다.

terraform workspace

동일한 예제를 apply 하면 create 가 아닌 not changed 가 발생한다

이슈를 해결하는 방법으로 가장 단순한 방법은 terraform.tfstate 파일을 삭제하는 것이지만, terraform workspace 를 분리함으로써 해결 역시 가능하다.

## 1. 생성이 아닌 미적용
$ terraform apply

null_resource.default: Refreshing state... [id=6748890877075846659]

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.

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

## 2. 바로 workspace 가 동일하기 때문이다 (default)
$  terraform workspace list
* default

terraform workspace 생성 및 재배포

# 1. workspace 커맨드를 통한 workspace 분리
$ terraform workspace new hello
Created and switched to workspace "hello"!

You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration.

# 2. 정상적으로 생성되었다면 기존과 달리 terraform.tfstate.d 가 추가된다.
$ tree .
.
├── main.tf
├── terraform.tfstate
└── terraform.tfstate.d
    └── hello

2 directories, 2 files


# 3. workspace 역시 변경된 것을 확인 가능
$ terraform workspace list
  default
* hello

# 4. 이제 새롭게 apply 를 실행하면 처음과 같이 create 가 가능 
terraform apply

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

Terraform will perform the following actions:

  # null_resource.default will be created
  + resource "null_resource" "default" {
      + id = (known after apply)
    }

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

terraform 을 통한 vSphere VM 배포

terraform 은 vSphere 인프라에 대한 프로비저닝을 지원한다.

hashicorp github에 vSphere 인프라 hello world 를 위한 좋은 예제가 있어 해당 github 에 있는 코드 중 필요한 항목만 추출하여 예제 작성하였다.

$ git clone https://github.com/hashicorp/learn-terraform-vsphere.git

해당 git에 저장된 파일들 중 아래 2개 파일만 사용 예정이다. (참고)

.
├── main.tf
└── variables.tf

단일 VM 배포

variables.tf

각 variable에 default 를 설정하지 않을 경우 terraform apply 시 사용자 입력을 받는다. (참고)

variable "vsphere_server" {
  description 	= "vSphere server"
  type        	= string
  default		= "my-vCenter.domain.com"	# 각자의 환경에 맞는 변수들을 지정
}

variable "vsphere_user" {
  description 	= "vSphere username"
  type        	= string
  default		= "administrator@vsphere.local"
}

### apply 시 사용자 비밀번호를 받고 싶다면 default 입력 X
variable "vsphere_password" {
  description = "vSphere password"
  type        = string
  sensitive   = true
}
...

### VM Clone 원본 이미지 이름 입력 (주로 goldend image)
variable "golden_image_name" {
  description = "VM Golden Image name"
  type        = string
  default	  = "vm-golden-image"
}

main.tf

## vsphere provider 에 대한 인프라 배포
provider "vsphere" {
  user           = var.vsphere_user
  password       = var.vsphere_password
  vsphere_server = var.vsphere_server
  allow_unverified_ssl = true
}

# variables.tf 에서 정의한 파일들은 var.{변수명} 형태로 정의 가능
data "vsphere_datacenter" "datacenter" {
  name = var.datacenter
}

	...

resource "vsphere_virtual_machine" "learn" {
	...

  # 생성될 vm의 hostname
  vm_hostname = "my-vm01"

  clone {
    template_uuid = data.vsphere_virtual_machine.ubuntu.id
  }
}

# 최종적으로 배포가 마무리되었을 경우 output 정의
output "vm_ip" {
  value = vsphere_virtual_machine.learn.guest_ip_addresses
}

모든 구성요소에 대한 작성이 완료되었다면 배포 진행

$ terraform init

$ terraform plan 		# optional

$ terraform apply

다수 VM 배포

다수 VM 에 대한 구성정보를 추가하기 위한 별도 terraform.tfvars 파일추가

단일 VM 배포와 달리 여러 값들을 동일한 코드에 적용하기 위해 반복변수 정의가 필요하다.

다양한 방법이 존재하지만, 우선은 가장 간단한 형태로 적용하였다.

.
├── main.tf
├── terraform.tfvars	# 다수 VM 배포를 위한 신규 파일 추가
└── variables.tf

cat terraform.tfvars
vm_names = ["test-01", "test-02", "test-03", "test-04"]

terraform.tfvars 에서 정의한 hostname 들을 이미 작성된 main.tf에서 사용하기 위한 variable 추가

variable "vm_names" {
  description = "VM hostnames"
  type        = list(string)
  default	  = "vm-golden-image"
}

main.tf 변경

# variables.tf 에서 정의한 vm_names 변수 내용을 적용하기 위한 반복변수 설정
resource "vsphere_virtual_machine" "cloned_vm" {
  count = length(var.vm_names)
  name  = var.vm_names[count.index]
	...
}

모든 변경사항이 작성되었다면 배포를 진행한다.

$ terraform plan 		# optional

$ terraform apply

참고

https://developer.hashicorp.com/terraform/install
https://developer.hashicorp.com/terraform/tutorials/virtual-machine/vsphere-provider
https://registry.terraform.io/providers/hashicorp/vsphere/latest/docs
https://github.com/hashicorp/learn-terraform-vsphere

profile
미래의 저를 위해 작성하는 중입니다 🙆‍♂️

0개의 댓글