Terraform 提供了基礎設施即程式碼(IaC)的管理能力,能有效控制和追蹤基礎設施的變更。匯入現有資源是 Terraform 的核心功能之一,讓既有基礎設施也能納入版本控制和自動化管理。本文將聚焦於 VMware 虛擬機器的自動化匯入,並搭配 Python 指令碼簡化組態檔案的生成過程,提升整體效率。首先,我們需要了解 Terraform 資源區塊的定義和引數設定,例如網路介面、CPU、記憶體等。接著,透過 Python 指令碼從 vCenter 取得 VM 的詳細資訊,並生成對應的 Terraform 組態檔案(例如 JSON 或 HCL 格式)。此組態檔案包含所有必要的引數,確保 Terraform 能夠正確匯入現有資源。最後,使用 terraform import 命令將指定的 VM 匯入 Terraform 管理,並透過 terraform plan 驗證匯入結果,確保組態檔案與實際狀態一致。此方法能大幅減少手動組態的負擔,並降低人為錯誤的風險,尤其在管理大量虛擬機器時更能展現其優勢。

Terraform 進階應用:VMware 虛擬機器的自動化匯入

資源區塊的定義與引數設定

在 Terraform 中,資源區塊是核心部分,定義了我們需要管理的資源。無論是虛擬機器(VM)還是其他基礎設施,這些區塊都包含多種必需和可選引數。例如,管理一台 VM 的資源區塊會包含 VM 名稱、儲存函式庫詳細資訊、CPU、記憶體等引數。

以下是一個範例程式碼片段,展示如何以 JSON 格式定義一台 VM 的資源區塊:

{
  "resource": {
    "vsphere_virtual_machine": {
      "VMresource": {
        "network_interface": {
          "adapter_type": "vmxnet3",
          "network_id": "${data.vsphere_network.network0.id}"
        },
        "name": "UbuntuTest",
        "resource_pool_id": "${data.vsphere_resource_pool.pool.id}",
        "datastore_id": "${data.vsphere_datastore.datastore.id}",
        "boot_retry_enabled": false,
        "enable_disk_uuid": false,
        "enable_logging": false,
        "num_cores_per_socket": 1,
        "num_cpus": 3,
        "guest_id": "ubuntu64Guest",
        "memory": 12288,
        "cpu_hot_add_enabled": true,
        "memory_hot_add_enabled": true,
        "firmware": "bios",
        "scsi_type": "${data.vsphere_virtual_machine.template.scsi_type}",
        "lifecycle": {
          "ignore_changes": [
            "custom_attributes",
            "tags"
          ]
        },
        "disk": {
          "label": "disk0",
          "size": 16,
          "unit_number": 0,
          "thin_provisioned": false,
          "path": "[Datastore name] UbuntuTest/UbuntuTest.vmdk",
          "keep_on_remove": true
        }
      }
    }
  }
}

內容解密:

  • network_interface:定義了網路介面卡的型別及所連線的網路 ID。這裡使用的是 vmxnet3 介面卡,並且連線到名為 network0 的網路。
  • name:虛擬機器的名稱,這裡命名為 UbuntuTest
  • resource_pool_id:虛擬機器所屬的資源池 ID。
  • datastore_id:虛擬機器所使用的儲存函式庫 ID。
  • boot_retry_enabled:是否啟用開機重試功能。
  • enable_disk_uuid:是否啟用磁碟 UUID。
  • enable_logging:是否啟用日誌記錄。
  • num_cores_per_socket:每個 CPU 插槽中的核心數量。
  • num_cpus:虛擬 CPU 的數量。
  • guest_id:作業系統型別,這裡設定為 ubuntu64Guest
  • memory:分配給虛擬機器的記憶體大小(單位為 MB)。
  • cpu_hot_add_enabledmemory_hot_add_enabled:是否啟用動態調整 CPU 和記憶體。
  • firmware:虛擬機器的韌體型別,這裡選擇 BIOS 模式。
  • scsi_type:SCSI 控制器型別。
  • lifecycle:定義了某些引數變更時應該忽略的設定,例如自訂屬性和標籤。
  • disk:磁碟組態,包括標籤、大小、單元號碼、是否細粒度組態等。

這些引陣列合在一起形成了一個完整的 VM 資源區塊。除了資源區塊之外,Terraform 組態檔案還包括輸入變數、輸出變數、本地變數等其他部分。這些部分可以根據實際需求進行組合,形成一個完整的 Terraform 組態檔案(例如 main.tf)。

自動化匯入現有資源

Terraform 不僅能夠建立新的基礎設施,還能夠匯入現有的資源。這意味著可以將已經存在的基礎設施(例如 VMware 虛擬機器)納入 Terraform 的管理範圍內。匯入資源需要一個已經填寫好的組態檔案,這個檔案可以幫助 Terraform 擷取現有資源的狀態並生成相應的狀態檔案。

動手實驗:Python 指令碼自動生成組態檔案

在實際操作中,我們可以使用 Python 指令碼來自動生成所需的組態檔案。這個指令碼會從 VMware vCenter 中提取必要的引數並生成對應的 Terraform 組態檔案。以下是一些關鍵步驟:

  1. 使用 Python 指令碼從 vCenter 提取 VM 的詳細資訊。
  2. 生成符合 Terraform 格式的組態檔案(例如 JSON 或 HCL)。
  3. 將生成的組態檔案放置在指定位置。

動手實驗:Terraform 載入現有 VM

假設我們有一台名為 UbuntuTest 的 VM 已經存在於 vCenter 中,我們可以使用以下命令將其匯入到 Terraform 中:

terraform import vsphere_virtual_machine.VMresource /<Cluster>/vm/UbuntuTest

內容解密:

  1. python 指令碼從 vCenter 提取 VM 的詳細資訊: 在實際應用中,Python 指令碼會使用 VMware 的 API(如 pyvmomi)來與 vCenter 進行互動,提取所需的 VM 資料。這些資料包括網路組態、儲存函式庫組態、CPU 和記憶體設定等。
  2. 生成符合 Terraform 格式的組態檔案: Python 指令碼會根據提取到的資料生成一個 JSON 或 HCL 格式的組態檔案。這個檔案包含了所有必要的引數設定,確保 Terraform 能夠正確匯入現有資源。
  3. 將生成的組態檔案放置在指定位置: 生成好的組態檔案(例如 main.tf.json)需要放置在特定目錄中(例如 import 資料夾),以便後續 Terraform 命令能夠正確找到並使用它。

驗證匯入結果

成功匯入後,我們需要驗證匯入結果是否正確。可以使用 terraform plan 命令來檢查是否有任何建議修改。如果 terraform plan 沒有建議任何修改,則表示匯入成功且組態檔案完整反映了當前資源狀態。

terraform plan

如果 terraform plan 建議修改某些引數,則表示組態檔案中某些引數未被正確取得或缺失。這時需要根據錯誤資訊進一步調整 Python 指令碼或手動補充缺失引數。

在實務中的應用

玄貓認為這種自動化匯入方法不僅能夠提高工作效率,還能夠減少人為錯誤。IT管理員可以根據自身環境中的 VM 組態調整 Python 指令碼和 Terraform 組態檔案,確保每次匯入操作都能夠順利完成。

小段落標題

Terraform 在基礎設施即程式碼(IaC)領域中具有重要地位,而自動化匯入現有資源則是其強大功能之一。透過結合 Python 指令碼和 Terraform 組態檔案,我們可以輕鬆地將現有基礎設施納入管理範圍內。這不僅提高了工作效率,還能夠減少人為錯誤,確保基礎設施管理的穩定性和可靠性。

自動化生成組態檔的 VMware 虛擬機器進口

在這篇文章中,玄貓將帶領大家深入瞭解如何自動化生成組態檔來進口 VMware 虛擬機器。這個過程涉及到反向工程概念,並使用 Python 語言編寫的指令碼來從 MOB(Managed Object Browser)取得詳細資訊,並在進口 VMware 虛擬機器時自動生成組態檔。

背景與目的

這個實作練習旨在展示如何利用反向工程概念來自動化進口樣本 VM。這個指令碼會從 MOB 取得詳細資訊,並生成一個組態檔,使得能夠成功進口 VMware 虛擬機器。雖然這個例子是針對 VMware,但這個進口組態也適用於大多數環境中的工作負載。根據你的具體環境,可能需要額外的引數來取得 VM 工作負載的詳細資訊。此外,這個反向工程邏輯也可以輕鬆應用到其他平台,以透過 Terraform 進行自動化。

步驟與程式碼解說

首先,我們需要從 GitHub 倉函式庫取得最新的進口指令碼。以下是重點程式碼的解說。

1. 設定基本引數

首先,我們需要設定一些基本引數,包括 API 認證資訊、vCenter IP、VM 名稱等。

import json
import requests
import sys
from requests.packages.urllib3.exceptions import InsecureRequestWarning
from pyVim import connect
import ssl
from pyVmomi import vim
import re
import collections

class OrderedConfig(collections.OrderedDict):
    pass

app_settings = {
    'api_pass': "XXXX",
    'api_user': "administrator@vsphere.local",
    'api_url': "https://<vCenter FQDN>/rest/",
    'vcenter_ip': "xx.xx.xx.xx",
    'VM_name': "UbantuTest",  # 想要取得詳細資訊的 VM 名稱 (大小寫敏感)
    'vsphere_datacenter': "ECM"
}

內容解密:

在這段程式碼中,我們首先匯入了所需的模組和類別。然後,我們定義了一些基本引數,包括 API 認證資訊、vCenter IP 地址、VM 名稱等。OrderedConfig 是一個有序字典類別,用來結構化地收集組態檔引數。

2. 認證與取得 API 資料

接下來,我們需要編寫函式來進行 vCenter 認證並取得 API 資料。

def auth_vcenter(username, password):
    resp = requests.post(
        '{}/com/vmware/cis/session'.format(app_settings['api_url']),
        auth=(app_settings['api_user'], app_settings['api_pass']),
        verify=False
    )
    if resp.status_code != 200:
        print('錯誤!API 回應狀態碼:{}'.format(resp.status_code))
        return
    return resp.json()['value']

def get_api_data(req_url):
    sid = auth_vcenter(app_settings['api_user'], app_settings['api_pass'])
    resp = requests.get(req_url, verify=False, headers={'vmware-api-session-id': sid})
    if resp.status_code != 200:
        print('錯誤!API 回應狀態碼:{}'.format(resp.status_code))
        return
    return resp.json()

內容解密:

auth_vcenter 函式用來進行 vCenter 認證,並傳回一個 session ID。get_api_data 函式則利用這個 session ID 去取得所需的 API 資料。

3. 取得虛擬機器詳情

接下來,我們需要編寫函式來取得虛擬機器的詳細資訊。

def get_vm(vm_name):
    resp = get_api_data('{}/vcenter/vm?filter.names={}'.format(app_settings['api_url'], vm_name))
    return resp

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
vmdetails = get_vm(app_settings['VM_name'])
vmid = vmdetails['value'][0]['vm']

內容解密:

get_vm 函式用來取得虛擬機器的詳細資訊,包括 VM ID。透過這個函式取得到的詳細資訊會用於後續的操作。

4. 接入 MOB 和取得詳細資訊

接下來,我們需要連線到 MOB(Managed Object Browser)並取得詳細資訊。

s = ssl._create_unverified_context()
service_instance = connect.SmartConnect(
    host=app_settings['vcenter_ip'], user=app_settings['api_user'], pwd=app_settings['api_pass'], sslContext=s
)
content = service_instance.RetrieveContent()
container = content.rootFolder # 開始查詢的起點
viewType = [vim.VirtualMachine] # 查詢物件型別
recursive = True # 是否遞迴查詢
containerView = content.viewManager.CreateContainerView(container, viewType, recursive) # 建立容器檢視
children = containerView.view
for child in children:
    if str(vmid) in str(child):
        vm_summary = child.summary # 想要匯入的虛擬機器摘要資訊
        vm_config = child.config # 虛擬機器完整組態資料
        vm_resourcepool = child.resourcePool # 資源池詳細資訊
        vm_network = child.network # 虛擬機器網路詳細資訊
        vm_datastore = child.datastore[0].name # 資料儲存詳細資訊
        vm_parent = child.parent # 虛擬機器父級資訊

內容解密:

在這段程式碼中,我們使用 pyVimpyVmomi 模組來連線到 vCenter 的 MOB。然後,我們建立了一個容器檢視來查詢所需的虛擬機器。當找到目標虛擬機器後,我們會取得其摘要資訊、完整組態、資源池、網路和資料儲存等詳細資訊。

5. 生成組態檔

最後,我們需要將取得到的詳細資訊結構化地寫入組態檔中。

data = OrderedConfig()
data["provider"] = OrderedConfig()
data["provider"]["vsphere"] = OrderedConfig()
data["provider"]["vsphere"]["user"] = "sampleuser"
data["provider"]["vsphere"]["password"] = "samplepassword"
data["provider"]["vsphere"]["allow_unverified_ssl"] = "true"

resourcepool_string = str(vm_resourcepool.owner.name) + '/' + str(vm_resourcepool.name)
data["data"] = OrderedConfig()
data["data"]["vsphere_datacenter"] = OrderedConfig()
data["data"]["vsphere_datacenter"]["dc"] = OrderedConfig()
data["data"]["vsphere_datacenter"]["dc"]["name"] = app_settings['vsphere_datacenter']
data["data"]["vsphere_resource_pool"] = OrderedConfig()
data["data"]["vsphere_resource_pool"]["pool"] = OrderedConfig()
data["data"]["vsphere_resource_pool"]["pool"]["name"] = resourcepool_string
data["data"]["vsphere_resource_pool"]["pool"]["datacenter_id"] = "${data.vsphere_datacenter.dc.id}"

datastore_string = str(vm_datastore)
data["data"]["vsphere_datastore"] = OrderedConfig()
data["data"]["vsphere_datastore"]["datastore"] = OrderedConfig()
data["data"]["vsphere_datastore"]["datastore"]["name"] = datastore_string
data["data"]["vsphere_datastore"]["datastore"]["datacenter_id"] = "${data.vsphere_datacenter.dc.id}"

network_adapter = []
for item_netadapter in vm_config.hardware.device:
    if "Network adapter" in str(item_netadapter.deviceInfo.label):
        vm_networkadapter = item_netadapter

if "E1000e" in str(type(vm_networkadapter)):
    network_adapter.append("e1000e")
if "Vmxnet3" in str(type(vm_networkadapter)):
    network_adapter.append("vmxnet3")

for index, nic in enumerate(vm_network):

提示與注意事項

  • 安全性:在生產環境中請勿使用明文儲存密碼。
  • 自動化:這個指令碼可以輕鬆擴充套件到其他平台和環境。
  • 模組依賴:確保已安裝所有必要的 Python 模組(如 requestspyVimpyVmomi)。

隨著自動化工具和技術的不斷進步,未來可以考慮將這些指令碼進一步整合到 CI/CD Pipeline中,以實作完全無人值守的虛擬機器管理。