我们希望听到您的声音!帮助我们深入了解 Ansible 生态系统现状。
参加 2024 年 Ansible 项目调查

使用 Ansible 管理 VMware 模板生命周期

使用 Ansible 管理 VMware 模板生命周期

当我们管理大量虚拟机 (VM) 时,我们希望减少它们之间的差异并创建标准模板。通过使用标准模板,可以更轻松地管理并在不同节点上传播相同的操作。当使用 VMware vSphere 时,共享标准化的 VM 模板并使用它创建新的 VM 是一种常见做法。此模板通常称为黄金映像。其创建涉及一系列可以使用 Ansible 自动化的步骤。在本篇博文中,我们将了解如何创建和使用新的黄金映像。

准备黄金映像

screenshot

我们使用 镜像构建器 来准备新的镜像。该工具提供了一个用户界面,允许用户定义自定义镜像。在本例中,我们包含了 SSH 服务器和 tmux。生成的镜像是一个 VMDK4 格式的文件,VMware vSphere 7 不完全支持,因此我们使用 .vmdk-4 后缀。

create image ui screenshot

我们使用 uri 模块上传镜像。使用此方法上传大文件相当缓慢。如果可以,您可能希望直接将文件放到数据存储中(例如:NFS/CIFS)。以下示例认为数据存储名为 rw_datastore,数据中心名为 my_dc。以下摘录自剧本,展示了我们如何上传镜像。

- name: Upload from contents of remote file
  ansible.builtin.uri:
    force_basic_auth: true
    url: 'https://vcenter.test/folder/my-vmdk/my-golden-image.vmdk-4?dcPath=my_dc&dsName=rw_datastore'
    url_username: '{{ lookup("ansible.builtin.env", "VMWARE_USER") }}'
    url_password: '{{ lookup("ansible.builtin.env", "VMWARE_PASSWORD") }}'
    method: PUT
    status_code: 201
    src: my-golden-image.vmdk-4
    validate_certs: false
    follow_redirects: yes

现在我们已上传文件,我们将将其转换为最新的 VMDK 文件。为此,我们使用 vmkfstools。该工具默认在 ESXi7 主机上可用。在下面的任务中,我们使用 delegate_to: esxi1.test 在我们的一个主机上运行该命令。

- name: Convert the image in an up to date VMDK format
  ansible.builtin.command: "vmkfstools -i /vmfs/volumes/rw_datastore/my-vmdk/my-golden-image.vmdk-4.vmdk-4   /vmfs/volumes/rw_datastore/my-vmdk/my-golden-image.vmdk -d thin"
  delegate_to: esxi1.test
  vars:
      ansible_user: root
      ansible_python_interpreter: /bin/python3

准备黄金 VM

在此阶段,磁盘已准备就绪,我们可以将其连接到 VM。

- name: Create a VM
  vmware.vmware_rest.vcenter_vm:
    placement:
      cluster: ""
      datastore: ""
      folder: ""
      resource_pool: ""
    name: my-golden-vm
    guest_OS: RHEL_7_64
    hardware_version: VMX_11
    memory:
      hot_add_enabled: true
      size_MiB: 1024
    disks:
      - type: SATA
        backing:
          type: VMDK_FILE
          vmdk_file: "[rw_datastore] my-vmdk/my-golden-image.vmdk"
    cdroms:
      - type: SATA
        sata:
          bus: 0
          unit: 2
    nics:
      - backing:
          type: STANDARD_PORTGROUP
          network: ""
  register: my_vm

有四种不同的方法可以使用 Ansible 的 vmware.vmware_rest 集合克隆 VM。本文解释了它们之间的区别以及如何使用 Ansible 使用它们。

克隆 VM

当我们克隆 VM 时,我们会创建一个原始 VM 的副本。但是,原始 VM 仍然可以发展,并且从同一 VM 进行的第二次克隆很可能会有所不同。无法保证两个克隆都基于完全相同的镜像。

vmware.vmware_rest.vcenter_vm 模块允许我们准备瞬时克隆或常规克隆。

瞬时克隆

根据 VMware 官方文档,瞬时克隆是正在运行的 VM 的轻量级副本。它与原始 VM 共享内存块。这就是为什么在克隆之前必须运行原始 VM 的原因。

- name: Turn the power on the VM on, since it's are pre-condition for Instant Clone
  vmware.vmware_rest.vcenter_vm_power:
    state: start
    vm: '{{ my_vm.id }}'

- name: Wait until my VM is ready
  vmware.vmware_rest.vcenter_vm_tools_info:
    vm: '{{ my_vm.id }}'
  register: vm_tools_info
  until:
  - vm_tools_info is not failed
  - vm_tools_info.value.run_state == "RUNNING"
  retries: 10
  delay: 5

现在我们已启动并运行了 VM,我们可以对其进行瞬时克隆

- name: Create an instant clone of a VM
  vmware.vmware_rest.vcenter_vm:
    placement:
      datastore: "{{ lookup('vmware.vmware_rest.datastore_moid', '/my_dc/datastore/local') }}"
      folder: "{{ lookup('vmware.vmware_rest.folder_moid', '/my_dc/vm') }}"
      resource_pool: "{{ lookup('vmware.vmware_rest.resource_pool_moid', '/my_dc/host/my_cluster/Resources') }}"
    state: instant_clone
    source: "{{ my_vm.id }}"
    name: instant_clone_1

常规克隆

我们还可以 克隆现有的 VM。如果 VM 带有大型磁盘,则该操作需要更多时间,最多可能需要几个小时。该操作会创建原始 VM 的完整克隆。这次,原始 VM 不需要运行。

- name: Create a full clone of a VM
  vmware.vmware_rest.vcenter_vm:
    placement:
      datastore: "{{ lookup('vmware.vmware_rest.datastore_moid', '/my_dc/datastore/local') }}"
      folder: "{{ lookup('vmware.vmware_rest.folder_moid', '/my_dc/vm') }}"
      resource_pool: "{{ lookup('vmware.vmware_rest.resource_pool_moid', '/my_dc/host/my_cluster/Resources') }}"
    state: clone
    source: "{{ my_vm.id }}"
    name: full_clone_1

构建模板

与克隆不同,模板可以保证 VM 继承自静态 VM 镜像。vmware.vmware_rest 集合使我们能够准备 OVF 包,并且从 2.2.0 版本开始,我们还可以准备模板 VM。

将 VM 导出为内容库中的 OVF 包

我们可以将 VM 导出为 OVF 包并将包上传到内容库中。如果您想准备一个将在 vSphere 基础架构中重复使用的标准模板,这将非常方便。此外,OVF 包可以从一个 vSphere 下载并在另一个 vSphere 中重新上传。

在本例中,我们使用 Ansible 来准备 OVF 包。在本例中,my_vm 未运行,内容库名为 my_library_on_nfs

- name: List all Local Content Library
  vmware.vmware_rest.content_locallibrary_info:
  register: all_content_libraries

- name: Use the name to identify the right Content Library
  set_fact:
    nfs_lib: "{{ all_content_libraries.value | selectattr('name', 'equalto', 'my_library_on_nfs')|first }}"

- name: Export the VM as an OVF on the library
  vmware.vmware_rest.vcenter_ovf_libraryitem:
    session_timeout: 2900
    source:
      type: VirtualMachine
      id: "{{ my_vm.id }}"
    target:
      library_id: "{{ nfs_lib.id }}"
    create_spec:
      name: golden_image
      description: an OVF example
      flags: []
    state: present

vsphere client screenshot

要基于此 OVF 包生成新的 VM,您首先需要在内容库中识别其项目条目。

- name: Get the list of items of the NFS library
  vmware.vmware_rest.content_library_item_info:
    library_id: '{{ nfs_lib.id }}'
    register: lib_items
- name: Define a new fact with the golden image ID
  ansible.builtin.set_fact:
    golden_image_id: '{{ (lib_items.value|selectattr("name", "equalto", "golden_image")|first).id }}'

获得项目 ID 后,我们可以调用 vcenter_ovf_libraryitem 来生成新的 VM。由于 ID 是不变的,因此我们可以将其保存以供将来使用。

- name: Create a new VM based on the OVF
  vmware.vmware_rest.vcenter_ovf_libraryitem:
    ovf_library_item_id: '{{ golden_image_id }}'
    state: deploy
    target: resource_pool_id: "{{ lookup('vmware.vmware_rest.resource_pool_moid', '/my_dc/host/my_cluster/Resources') }}"
    deployment_spec:
      name: my_vm_from_ovf
      accept_all_EULA: true
      storage_provisioning: thin

将 VM 导出为内容库中的 VM 模板

模板创建通过一次调用 vmware.vmware_rest.vcenter_vmtemplate_libraryitems 模块来完成。此模块是在 vmware_rest 集合 2.2.0 中引入的。

这里,nfs_lib 是您的内容库,您的 VM 详细信息已注册到 my_vm 变量中。

- name: Create a VM template on the library
  vmware.vmware_rest.vcenter_vmtemplate_libraryitems:
    name: golden-template
    library: "{{ nfs_lib.id }}"
    source_vm: "{{ my_vm.id }}"
    placement:
      cluster: "{{ lookup('vmware.vmware_rest.cluster_moid', '/my_dc/host/my_cluster') }}"
      folder: "{{ lookup('vmware.vmware_rest.folder_moid', '/my_dc/vm') }}"
      resource_pool: "{{ lookup('vmware.vmware_rest.resource_pool_moid', '/my_dc/host/my_cluster/Resources') }}"

vsphere client screenshot

要基于此模板生成新的 VM,我们再次需要识别内容库中的项目。

- name: Get the list of items of the NFS library
  vmware.vmware_rest.content_library_item_info:
    library_id: '{{ nfs_lib.id }}'
  register: lib_items

- name: Use the name to identify the item
  set_fact:
    my_template_item: "{{ lib_items.value | selectattr('name', 'equalto', 'golden-template')|first }}"

我们使用相同的模块进行部署

- name: Deploy a new VM based on the template
  vmware.vmware_rest.vcenter_vmtemplate_libraryitems:
    name: vm-from-template
    library: "{{ nfs_lib.id }}"
    template_library_item: "{{ my_template_item.id }}"
    placement:
      cluster: "{{ lookup('vmware.vmware_rest.cluster_moid', '/my_dc/host/my_cluster') }}"
      folder: "{{ lookup('vmware.vmware_rest.folder_moid', '/my_dc/vm') }}"
      resource_pool: "{{ lookup('vmware.vmware_rest.resource_pool_moid', '/my_dc/host/my_cluster/Resources') }}"
    state: deploy

总之,只需几个 Ansible 任务,我们就可以将现有 VM 提升为模板。这使我们能够依靠 Ansible 自动化 VM 模板的维护并确保流程的可重复性。