สร้าง Infrastructure as Code (IaC) ด้วย Terraform บน VMware vSphere

Create Infrastructure as Code (IaC) using Terraform on VMware vSphere

Nopnithi Khaokaew (Game)
7 min readAug 15, 2020

— — — — — — — — — — — — — — —
สารบัญเนื้อหาทั้งหมด (My Contents)
— — — — — — — — — — — — — — —

แม้ Infrastructure as Code (IaC) จะเป็นคอนเซ็ปต์ที่เรามักจะได้ยินมาพร้อมกับยุค cloud แต่ใช่ว่าเราจะ apply มันได้แค่บน public cloud หรือ private cloud เท่านั้น

บทความนี้ผมจะอธิบายให้เข้าใจกันว่า Infrastructure as Code (IaC) คืออะไรกันแน่ พร้อมตัวอย่างการทำ Infrastructure as Code (IaC) บน VMware vSphere ด้วย Terraform ซึ่งเป็นหนึ่งในเครื่องมือที่ฮอตที่สุดในยุค cloud

Infrastructure as Code (IaC) คืออะไร?

Infrastructure as Code (IaC) คือ การจัดการ (managing), การกำหนดค่า (configuring) หรือการจัดเตรียม (provisioning) ระบบภายใน infrastructure หรือ data center ด้วย code แทนการแก้ไข configuration โดยตรง

อ่าว…แล้วถ้าเราต้องการที่จะทำอย่างนี้หละ

  • สร้าง VM ใหม่
  • เพิ่ม CPU หรือ memory ให้กับ VM ที่มีอยู่
  • แก้ไข IP ของ Ubuntu server
  • ติดตั้ง software ภายใน Windows server
  • สร้าง VLAN ขึ้นมาบน switch

พวก activity เหล่านี้มันจะเป็น code ไปได้ยังไง?

คำตอบก็คือเวลาที่เราจะทำอะไรกับ infrastructure ของเรา แทนที่เราจะ login เข้าระบบหรือเข้า OS ไปทำเอง เราก็หันมาใช้เครื่องมือ (tools) เข้ามาช่วยในการ interact กับ infrastructure แทนเรา ซึ่ง code มันก็เกิดขึ้นจาก configuration ของเครื่องมือตัวที่เราใช้นั่นแหละครับ

เครื่องมือเหล่านั้นอาจเป็น Terraform (ทำในระดับ VM), Ansible (ทำในระดับ OS) หรือใช้การเขียน code โดยตรง เช่น Python ซึ่งจะทำในระดับไหนยังไงก็ได้ (แต่งานจะหนักมาก)

เมื่อเป็นแบบนี้แล้ว operation ในการจัดการกับ infrastructure ของเราจะง่ายขึ้นมาก เพราะ code ก็คือไฟล์ text-based ซึ่งเราสามารถนำไปจัดเก็บ, เปรียบเทียบ, ทำซ้ำ แก้ไขเปลี่ยนแปลง หรือทำงานร่วมกันหลายคน ได้ง่ายมากหากใช้งานร่วมกับ VCS (Version Control System) อย่าง Git เหมือนที่ developer ทำงานกับ code ซึ่งจะทำให้เกิดข้อดีตามมามากมาย เช่น

  • สร้าง infrastructure ขึ้นใหม่หรือทำซ้ำได้ง่าย
  • ทำงานได้รวดเร็วขึ้นมาก
  • ลด human error ลงได้เยอะ
  • Track changes ได้ง่าย (แม้ทำ operation หลาย platform หรือ system)
  • Rollback ง่าย (แม้ทำ operation หลาย platform หรือ system)

Terraform คืออะไร?

Terraform คือ เครื่องมือที่ทำให้เราสามารถนำคอนเซ็ปต์ Infrastructure as Code มาใช้ได้ง่าย ๆ บน infrastructure ของเรา เช่น สมมุติว่าบริษัทผมใช้งาน AWS อยู่ และเมื่อผมต้องการที่จะสร้าง VM ขึ้นมา ปกติแล้วสิ่งที่ผมต้องทำก็คือ login เข้าไปที่ AWS management console แล้วก็สร้างมันขึ้นมาตามปกติ (คลิกและกรอกข้อมูลเอง)

แต่ด้วย Terraform จะทำให้เราสามารถสร้าง VM ขึ้นมาได้ด้วยการเขียน code แทน และแน่นอนว่า Terraform ยังสามารถทำงานกับ cloud หรือ infrastructure software อีกหลายตัวได้มากมาย ซึ่งหนึ่งในนั้นคือ VMware vSphere ที่ผมจะลองทำให้ดูในบทความนี้

Terraform ทำงานกับ Platform ใดได้บ้าง?

https://www.terraform.io/docs/providers/index.html

ใช้ Python ก็ได้ ทำไมต้องใช้ Terraform?

ใช่ครับ จริง ๆ ถ้าผมต้องการสร้าง VM บน AWS เนี่ย ผมใช้ Python คู่กับ Boto3 ก็ทำได้เหมือนกัน แล้วทำไมผมต้องใช้ Terrraform หละ? ในมุมของผมนอกจากความง่ายแล้ว จุดสำคัญคือเรื่องของการ keep state

Terraform จะ Keep State ของ Infrastructure ตาม Code

สมมุติว่าใน code ของผมเขียนไว้ให้ Terraform สร้าง VM ขึ้นมา 5 ตัว ได้แก่ VM A ไปจนถึง E แล้วจู่ ๆ เพื่อนร่วมงานผมเกิดเผลอไปลบ VM C เข้า สิ่งที่เกิดขึ้นก็คือ Terraform มันจะสร้าง VM C ขึ้นมาใหม่ให้เองโดยอัตโนมัติ เนื่องจากมันจะคอย keep state ตาม code ล่าสุดที่เรา apply ไป ซึ่งการใช้ Python เพื่อเขียนส่วนนี้ขึ้นมานั้นก็สามารถทำได้ แต่ก็จะกินเวลามากโข

Terraform เป็น Declarative Language

ขยายความต่อกันที่นี่ครับ

Code ตัวอย่าง

เริ่มสร้าง Infrastructure as Code ด้วย Terraform

สิ่งที่เราจะทำกันในโพสต์นี้ก็คือ

  • สร้าง VM จำนวน 3 instance จาก template
  • จากนั้นลองเพิ่ม memory จาก 1 GB เป็น 4 GB
  • สุดท้ายลอง destroy VM ทั้งหมดทิ้ง

1) เตรียม Terraform Variable

กำหนดตัวแปรเพื่อใช้ใน Terraform configuration ซึ่งเดี๋ยวเราจะนำตัวแปรเหล่านี้ไปใช้กับส่วนอื่น ๆ ภายใน configuration ต่อไป

ไฟล์ variables.tf

variable "vsphere_user" {
description = "vSphere user"
default = "administrator@vsphere.local"
}
variable "vsphere_password" {
description = "Password for vSphere user"
default = "G@me1234"
}
variable "vsphere_server" {
description = "vSphere host name"
default = "vcenter.nopnithi.lab"
}
variable "dns_servers" {
description = "DNS Server IPs"
default = ["8.8.8.8", "8.8.4.4"]
}
variable
"vm_count" {
description = "Number of VMs we want to spin up"
default = 3
}

2) ตั้งค่า Terraform Provider สำหรับ VMware vSphere

เตรียม Provider เพื่อใช้ในการ authenticate กับ VMware vSphere โดยจะมี parameter ทั้งหมด 4 ตัว คือ

  1. Host (IP หรือ DNS ของ VMware vCenter)
  2. Username
  3. Password
  4. Self-signed certificate (ใครมีก็ใส่ true ไป)

ไฟล์ main.tf (ส่วนที่ 1)

# Configure VMware vSphere Provider
provider
"vsphere" {
user = var.vsphere_user
password = var.vsphere_password
vsphere_server = var.vsphere_server
allow_unverified_ssl = true
}

สังเกตว่าผมดึงค่าจากตัวแปรที่เราสร้างขึ้นในข้อก่อนหน้านี้

3) ตั้งค่า Terraform Data Source

ส่วนนี้จะเป็นการดึงค่าต่าง ๆ ของ resource จาก infrastructure เช่น resource ID เพื่อนำมาใช้ภายใน Terraform ซึ่งถ้าลองอ่านดูจะพอทราบครับว่าผมดึงอะไรมาบ้าง โดยข้อมูลพวกนี้จะนำมาใช้สำหรับสร้าง VM ขึ้นมานั่นเอง

  • ชื่อ Datacenter
  • ชื่อ Datastore
  • ชื่อ Resource Pool
  • ชื่อ Network
  • ชื่อ Template

ไฟล์ main.tf (ส่วนที่ 2)

# Build Virtual Machine
data
"vsphere_datacenter" "dc" {
name = "Nopnithi-DC"
}
data "vsphere_datastore" "datastore" {
name = "datastore1"
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_resource_pool" "pool" {
name = "resource-pool1"
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_network" "network" {
name = "vlan10-blue"
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_virtual_machine" "template" {
name = "ubuntu-18-04-terraform-template"
datacenter_id = data.vsphere_datacenter.dc.id
}

4) สร้าง VM Resouce

ตอนนี้เราต้องทำการสร้าง VM resource ขึ้นมาโดยมี criteria มากมาย ซึ่งบางอย่างก็ดึงมาจาก template แต่บางอย่างเราก็กำหนดเอง

ไฟล์ main.tf (ส่วนที่ 3)

resource "vsphere_virtual_machine" "vm" {
count = var.vm_count
name = "ubuntu${count.index + 1}"
num_cpus = 2
memory = 1024
resource_pool_id = data.vsphere_resource_pool.pool.id
datastore_id = data.vsphere_datastore.datastore.id
guest_id = data.vsphere_virtual_machine.template.guest_id
network_interface {
network_id = data.vsphere_network.network.id
}
disk {
label = "ubuntu-18-04-terraform-template.vmdk"
thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
size = 20
}
clone {
template_uuid = data.vsphere_virtual_machine.template.id

customize {
linux_options {
host_name = "ubuntu${count.index + 1}"
domain = "nopnithi.lab"
}
network_interface {
ipv4_address = "10.1.10.${count.index + 101}"
ipv4_netmask = 24
}
ipv4_gateway = "10.1.10.254"
dns_server_list = var.dns_servers
}
}
}

5) ใช้ Terraform ในการ Deploy

เมื่อเตรียมทุกอย่างพร้อมเราก็สามารถ spin up VM ขึ้นมาบน VMware vSphere ได้ด้วย Terraform แล้วโดยใช้ command ที่สำคัญทั้งหมด ดังนี้

  • terraform init ใช้ในการ initial หลังจากที่เขียน configuration เสร็จแล้ว
  • terraform validate ใช้ตรวจสอบ syntax ของ configuration (ผมไม่ใช้)
  • terraform plan ใช้เพื่อดูว่า Terraform จะทำอะไรบ้างจาก configuration
  • terraform apply ใช้เพื่อเริ่มทำการเริ่มดำเนินงานตาม configuration
  • terraform destroy ใช้เพื่อลบ infrastructure ที่สร้างขึ้นมาจาก configuration

บน Terminal

เริ่มด้วย terraform init ก่อนเลย

$> terraform initInitializing the backend...Initializing provider plugins...The following providers do not have any version constraints in configuration,
so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.
* provider.vsphere: version = "~> 1.22"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.

จากนั้นต่อด้วย terraform plan ครับ เราจะเห็นว่า Terraform มันมี plan ที่จะทำอะไรบ้างโดยการนำ configuration ไปเปรียบเทียบกับ infrastructure ณ ปัจจุบัน

$> terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
data.vsphere_datacenter.dc: Refreshing state...
data.vsphere_resource_pool.pool: Refreshing state...
data.vsphere_network.network: Refreshing state...
data.vsphere_datastore.datastore: Refreshing state...
data.vsphere_virtual_machine.template: Refreshing state...
------------------------------------------------------------------------An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:# vsphere_virtual_machine.vm[0] will be created
...
# vsphere_virtual_machine.vm[1] will be created
...
# vsphere_virtual_machine.vm[2] will be created
...
Plan: 3 to add, 0 to change, 0 to destroy.------------------------------------------------------------------------Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

ทีนี้ก็เริ่ม deploy ได้เลยด้วย terraform apply โดยมันก็ทำการสร้าง VM ขึ้นมาทั้งหมด 3 instance ตาม configuration นั่นเอง

$> terraform apply
data.vsphere_datacenter.dc: Refreshing state...
data.vsphere_network.network: Refreshing state...
data.vsphere_resource_pool.pool: Refreshing state...
data.vsphere_datastore.datastore: Refreshing state...
data.vsphere_virtual_machine.template: Refreshing state...
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:...
...
...
Plan: 3 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: yesvsphere_virtual_machine.vm[1]: Creating...
vsphere_virtual_machine.vm[0]: Creating...
vsphere_virtual_machine.vm[2]: Creating...
vsphere_virtual_machine.vm[1]: Still creating... [10s elapsed]
vsphere_virtual_machine.vm[0]: Still creating... [10s elapsed]
vsphere_virtual_machine.vm[2]: Still creating... [10s elapsed]
vsphere_virtual_machine.vm[0]: Still creating... [20s elapsed]
vsphere_virtual_machine.vm[1]: Still creating... [20s elapsed]
vsphere_virtual_machine.vm[2]: Still creating... [20s elapsed]
vsphere_virtual_machine.vm[0]: Still creating... [30s elapsed]
vsphere_virtual_machine.vm[2]: Still creating... [30s elapsed]
vsphere_virtual_machine.vm[1]: Still creating... [30s elapsed]
vsphere_virtual_machine.vm[0]: Still creating... [40s elapsed]
vsphere_virtual_machine.vm[1]: Still creating... [40s elapsed]
vsphere_virtual_machine.vm[2]: Still creating... [40s elapsed]
vsphere_virtual_machine.vm[0]: Still creating... [50s elapsed]
vsphere_virtual_machine.vm[2]: Still creating... [50s elapsed]
vsphere_virtual_machine.vm[1]: Still creating... [50s elapsed]
vsphere_virtual_machine.vm[2]: Still creating... [1m0s elapsed]
vsphere_virtual_machine.vm[1]: Still creating... [1m0s elapsed]
vsphere_virtual_machine.vm[0]: Still creating... [1m0s elapsed]
vsphere_virtual_machine.vm[2]: Still creating... [1m10s elapsed]
vsphere_virtual_machine.vm[1]: Still creating... [1m10s elapsed]
vsphere_virtual_machine.vm[0]: Still creating... [1m10s elapsed]
vsphere_virtual_machine.vm[1]: Creation complete after 1m18s [id=420d2e85-1902-c7a4-131d-04123fe7ad9a]
vsphere_virtual_machine.vm[0]: Still creating... [1m20s elapsed]
vsphere_virtual_machine.vm[2]: Still creating... [1m20s elapsed]
vsphere_virtual_machine.vm[0]: Creation complete after 1m28s [id=420dde69-a078-f698-763b-8e0c35a53844]
vsphere_virtual_machine.vm[2]: Creation complete after 1m28s [id=420d7dd3-89a9-6b29-59f8-384fa346630d]
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

ผลที่ได้ก็คือผมมี VM ทั้งหมด 3 instance ตาม configuration

ทีนี้ผมจะลองเปลี่ยน memory จาก 1024 เป็น 4096 โดยแก้จากไฟล์ main.tf แล้วรัน terraform apply อีกรอบ

...
num_cpus = 2
memory = 4096
resource_pool_id = data.vsphere_resource_pool.pool.id
...

จะเห็นว่าหลังจากที่มันเช็ค state เสร็จ มันก็เตรียมเปลี่ยน memory ให้เราแล้ว

...
latency_sensitivity = "normal"
~ memory = 1024 -> 4096
memory_hot_add_enabled = false
...

หลังจากนั้นก็เป็นอันจบบริบูรณ์ เมื่อลองเช็ค VM ดูจะเห็นว่าทุกตัวมี memory เป็น 4 GB เรียบร้อยแล้ว

vsphere_virtual_machine.vm[2]: Modifying... [id=420d7dd3-89a9-6b29-59f8-384fa346630d]
vsphere_virtual_machine.vm[0]: Modifying... [id=420dde69-a078-f698-763b-8e0c35a53844]
vsphere_virtual_machine.vm[1]: Modifying... [id=420d2e85-1902-c7a4-131d-04123fe7ad9a]
vsphere_virtual_machine.vm[1]: Still modifying... [id=420d2e85-1902-c7a4-131d-04123fe7ad9a, 10s elapsed]
vsphere_virtual_machine.vm[0]: Still modifying... [id=420dde69-a078-f698-763b-8e0c35a53844, 10s elapsed]
vsphere_virtual_machine.vm[2]: Still modifying... [id=420d7dd3-89a9-6b29-59f8-384fa346630d, 10s elapsed]
vsphere_virtual_machine.vm[1]: Still modifying... [id=420d2e85-1902-c7a4-131d-04123fe7ad9a, 20s elapsed]
vsphere_virtual_machine.vm[0]: Still modifying... [id=420dde69-a078-f698-763b-8e0c35a53844, 20s elapsed]
vsphere_virtual_machine.vm[2]: Still modifying... [id=420d7dd3-89a9-6b29-59f8-384fa346630d, 20s elapsed]
vsphere_virtual_machine.vm[0]: Still modifying... [id=420dde69-a078-f698-763b-8e0c35a53844, 30s elapsed]
vsphere_virtual_machine.vm[2]: Still modifying... [id=420d7dd3-89a9-6b29-59f8-384fa346630d, 30s elapsed]
vsphere_virtual_machine.vm[1]: Still modifying... [id=420d2e85-1902-c7a4-131d-04123fe7ad9a, 30s elapsed]
vsphere_virtual_machine.vm[1]: Still modifying... [id=420d2e85-1902-c7a4-131d-04123fe7ad9a, 40s elapsed]
vsphere_virtual_machine.vm[0]: Still modifying... [id=420dde69-a078-f698-763b-8e0c35a53844, 40s elapsed]
vsphere_virtual_machine.vm[2]: Still modifying... [id=420d7dd3-89a9-6b29-59f8-384fa346630d, 40s elapsed]
vsphere_virtual_machine.vm[0]: Still modifying... [id=420dde69-a078-f698-763b-8e0c35a53844, 50s elapsed]
vsphere_virtual_machine.vm[2]: Still modifying... [id=420d7dd3-89a9-6b29-59f8-384fa346630d, 50s elapsed]
vsphere_virtual_machine.vm[1]: Still modifying... [id=420d2e85-1902-c7a4-131d-04123fe7ad9a, 50s elapsed]
vsphere_virtual_machine.vm[0]: Still modifying... [id=420dde69-a078-f698-763b-8e0c35a53844, 1m0s elapsed]
vsphere_virtual_machine.vm[1]: Still modifying... [id=420d2e85-1902-c7a4-131d-04123fe7ad9a, 1m0s elapsed]
vsphere_virtual_machine.vm[2]: Still modifying... [id=420d7dd3-89a9-6b29-59f8-384fa346630d, 1m0s elapsed]
vsphere_virtual_machine.vm[2]: Modifications complete after 1m8s [id=420d7dd3-89a9-6b29-59f8-384fa346630d]
vsphere_virtual_machine.vm[1]: Modifications complete after 1m8s [id=420d2e85-1902-c7a4-131d-04123fe7ad9a]
vsphere_virtual_machine.vm[0]: Modifications complete after 1m8s [id=420dde69-a078-f698-763b-8e0c35a53844]
Apply complete! Resources: 0 added, 3 changed, 0 destroyed.

การสร้าง VM template ของ Ubuntu 18.04 บน VMware vSphere

เผื่อใครอยากลองทำตาม อันนี้เป็นวิธีการสร้าง template ขึ้นมาครับ

https://blog.inkubate.io/create-a-ubuntu-18-04-terraform-template-for-vmware-vsphere/

— — — — — — — — — — — — — — —
สารบัญเนื้อหาทั้งหมด (My Contents)
— — — — — — — — — — — — — — —

--

--

Nopnithi Khaokaew (Game)
Nopnithi Khaokaew (Game)

Written by Nopnithi Khaokaew (Game)

Cloud Solutions Architect & Hobbyist Developer | 6x AWS Certified, CKA, CKAD, 2x HashiCorp Certified (Terraform, Vault), etc.