2022年8月27日土曜日

AnsibleでESXi上に仮想マシンを構築する

これまでAnsibleで、LinuxやWindows Serverの初期構築と単体テストを実施してきた。今回は、Ansibleを使ってESXi上に仮想マシンを構築するPlaybookを作ってみたので紹介する。なお、私の環境の問題でESXiを用いているが、少し修正すればvCenter Server経由でも実行することができるだろう。

今までのAnsible関連記事

環境

コントロールノードのLinuxのOSは、AlmaLinuxにて構築している。実行対象のESXiは、ESXi 6.7となる。なお、ESXiの無償ライセンスではPlaybookを実行できないため注意する。

  • コントロールノード
    • OS : AlmaLinux 8.5
    • Ansible : ansible [core 2.13.1]
  • Ansible実行対象サーバ
    • OS : ESXi 6.7

Ansibleコントロールノードでの設定

1. pyVmomiをインストール

PythonでESXiやvCenter Serverの管理をできるようpyVmomiをインストールする。これはpipを使ってインストールすればよい。

# pip install pyvmomi

2. vSphere Automation Python SDKをインストール

pyVmomiとは別に、vSphere Automation Python SDKもインストールを行う。こちらは、gitを使う必要があるので、gitをインストールしたのち、pipにてインストールを行う。

# dnf install git -y
# pip install --upgrade git+https://github.com/vmware/vsphere-automation-sdk-python.git
Collecting git+https://github.com/vmware/vsphere-automation-sdk-python.git
  Cloning https://github.com/vmware/vsphere-automation-sdk-python.git to /tmp/pip-req-build-qjay0ffh
  Running command git clone --filter=blob:none --quiet https://github.com/vmware/vsphere-automation-sdk-python.git /tmp/pip-req-build-qjay0ffh
  Resolved https://github.com/vmware/vsphere-automation-sdk-python.git to commit 4bad74ad6be25a41fef7f0bfaa13a17b25039d25
  Preparing metadata (setup.py) ... done

~(中略)~

Installing collected packages: lxml, pyOpenSSL, vapi-runtime, vapi-common-client, vapi-client-bindings, vmc-draas-client-bindings, vmc-client-bindings, nsx-vmc-policy-python-sdk, nsx-vmc-aws-integration-python-sdk, nsx-python-sdk, nsx-policy-python-sdk, vSphere-Automation-SDK
  Running setup.py install for vSphere-Automation-SDK ... done
Successfully installed lxml-4.9.1 nsx-policy-python-sdk-3.1.5.0.0 nsx-python-sdk-3.1.5.0.0 nsx-vmc-aws-integration-python-sdk-3.1.5.0.0 nsx-vmc-policy-python-sdk-3.1.5.0.0 pyOpenSSL-22.0.0 vSphere-Automation-SDK-1.78.0 vapi-client-bindings-3.8.0 vapi-common-client-2.34.0 vapi-runtime-2.34.0 vmc-client-bindings-1.60.0 vmc-draas-client-bindings-1.19.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

3. 動作確認

これだけでESXiやvCenter Serverに対してAnsible実行ができるようになる。テスト用として、ESXiの情報を取得するPlaybookを作成したので、実際にPlaybookを実行して、問題なく実行できることを確認してみよう。

インベントリーファイル

hostsというファイル名で以下の通り1台のESXiを記載したインベントリーファイルを作成した。

[vmware_servers]
esxi01 ansible_host=192.168.1.1

Playbook

test_esxi_connection.ymlというファイル名で以下の通りPlaybookを作成した。ユーザ名、パスワードなどの変数は、環境に合わせて修正すること。

---
- name: Test esxi connection
  gather_facts: false
  hosts: vmware_servers

  vars:
    ansible_connection: local
    ansible_python_interpreter: /usr/bin/python3.8
    esxi_username: root
    esxi_password: !vault |
      $ANSIBLE_VAULT;1.1;AES256
      37316332366436396537613265366334323663646463306163353665323836636362323334313763
      ~(中略)~
      3730

  tasks:
    - name: Get vmware host facts
      community.vmware.vmware_host_facts:
        hostname: "{{ inventory_hostname }}"
        username: "{{ esxi_username }}"
        password: "{{ esxi_password }}"
        validate_certs: false
      register: result

    - name: Show vmware host facts
      ansible.builtin.debug:
        msg: "{{ result }}"

実行結果

ok=2となることが確認できればOKとなる。

# ansible-playbook -i hosts test_esxi_connection.yml 

PLAY [Create vmware vm] ********************************************************************************************

TASK [Get vmware host facts] ***************************************************************************************
ok: [esxi01]

TASK [Show vmware host facts] **************************************************************************************
ok: [esxi01] => {
    "msg": {
        "ansible_facts": {
            "ansible_all_ipv4_addresses": [
                "192.168.1.1",
                "192.168.2.1"
            ],
            "ansible_bios_date": "2018-07-12T00:00:00+00:00",
            "ansible_bios_version": "P3.00",
            "ansible_datastore": [
                {
                    "free": "326.41 GB",
                    "name": "Datastore_01",
                    "total": "458.25 GB"
                },
                {
                    "free": "641.69 GB",
                    "name": "Datastore_02",
                    "total": "931.25 GB"
                },
                {
                    "free": "584.54 GB",
                    "name": "nfs_01",
                    "total": "1.94 TB"
                }
            ],
            "ansible_distribution": "VMware ESXi",
            "ansible_distribution_build": "18828794",
            "ansible_distribution_version": "6.7.0",
            "ansible_hostname": "esxi01",
            "ansible_in_maintenance_mode": false,
            "ansible_interfaces": [
                "vmk0",
                "vmk1"
            ],
            "ansible_memfree_mb": 6108,
            "ansible_memtotal_mb": 32420,
            "ansible_os_type": "vmnix-x86",
            "ansible_processor": "Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz",
            "ansible_processor_cores": 6,
            "ansible_processor_count": 1,
            "ansible_processor_vcpus": 6,
            "ansible_product_name": "To Be Filled By O.E.M.",
            "ansible_product_serial": "To Be Filled By O.E.M.",
            "ansible_system_vendor": "To Be Filled By O.E.M.",
            "ansible_uptime": 13418913,
            "ansible_uuid": "8cc28570-1edb-0000-0000-000000000000",
            "ansible_vmk0": {
                "device": "vmk0",
                "ipv4": {
                    "address": "192.168.1.1",
                    "netmask": "255.255.255.0"
                },
                "macaddress": "70:85:c2:8c:xx:xx",
                "mtu": 1500
            },
            "ansible_vmk1": {
                "device": "vmk1",
                "ipv4": {
                    "address": "192.168.2.1",
                    "netmask": "255.255.255.0"
                },
                "macaddress": "00:50:56:64:xx:xx",
                "mtu": 1500
            },
            "cluster": null,
            "host_date_time": {
                "date": "2022-08-21",
                "day": "21",
                "epoch": "1661038759",
                "hour": "08",
                "iso8601": "2022-08-21T08:39:19Z",
                "iso8601_basic": "20220821T083919210083",
                "iso8601_basic_short": "20220821T083919",
                "iso8601_micro": "2022-08-21T08:39:19.210083Z",
                "minute": "39",
                "month": "08",
                "second": "19",
                "time": "08:39:19",
                "tz": "UTC",
                "tz_offset": "+0000",
                "weekday": "日曜日",
                "weekday_number": "0",
                "weeknumber": "33",
                "year": "2022"
            },
            "vsan_cluster_uuid": null,
            "vsan_health": "unknown",
            "vsan_node_uuid": null
        },
        "changed": false,
        "failed": false
    }
}

PLAY RECAP *********************************************************************************************************
esxi01                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

ESXi上に仮想マシンを作成するPlaybook

Playbookのファイルの記載内容は大きく以下のように構成される。

設定項目 説明
hosts 実行対象のサーバを記載する。サーバのリストは別ファイルで作成し、そのファイルの中で実行する対象のサーバやグループを指定する。
vars 変数を記載する。ここで記載した変数は{{ 変数名 }}という形で参照できる。また、変数は配列して複数の要素を持たせることもできる。
tasks Ansibleで実行するメインの処理を記載する。
handlers Ansibleでメイン処理実行状況に応じて実行する事後処理を記載する。例えば、設定ファイル更新がされた場合 (実行結果がchangedの場合) は設定反映のためにサービス再起動を行うといった使い方をする。今回のPlaybookでは未使用となる。

今回はcreate_vmware_vm.ymlというファイル1つにすべての内容を記載して作成した。以下にそれぞれの記載内容を説明する。

hosts : 実行対象のESXiを指定

hostsというファイル名で以下の通り1台のESXiを記載したインベントリーファイルを作成した。

[vmware_servers]
esxi01 ansible_host=192.168.1.1

vars : 変数①(ESXiに接続するための変数)

変数名 内容
ansible_connection ESXiへの接続の場合はlocalhostを使用する。
ansible_python_interpreter Pythonの実行パスを指定する。これを指定しない場合、「The error was: ModuleNotFoundError: No module named 'pyVim'」といったモジュールが見つからないというメッセージが表示され、タスクの実行に失敗する。
esxi_username ESXiへ接続するためのユーザ名を指定する。
esxi_password ESXiへ接続するためのパスワードを指定する。平文で記載するとセキュリティ上よろしくないので、Ansible Vaultを使って暗号化して記載しよう。
  vars:
    ansible_connection: local
    ansible_python_interpreter: /usr/bin/python3.8
    esxi_username: root
    esxi_password: !vault |
      $ANSIBLE_VAULT;1.1;AES256
      37316332366436396537613265366334323663646463306163353665323836636362323334313763
      ~(中略)~
      3730

vars : 変数②(仮想マシンのパラメータ)

変数名 内容
vm_name 仮想マシン名を指定する。
vm_annotation 仮想マシンの注釈を指定する。
vm_folder 仮想マシンのフォルダを指定する。ESXiにはフォルダの概念がないが、指定が必須となる。この場合は/を指定する。
vm_guest_id 仮想マシンのOS種別を指定する。OS種別とIDの紐づけはVMwareのドキュメントを参照。今回はother4xLinux64Guestを指定する。
vm_hardware 仮想マシンのハードウェアとして、CPU数とメモリ容量を指定する。
vm_disk 仮想マシンのハードデイスクを指定する。
vm_networks 仮想マシンのNICを指定する。
vm_cdrom 仮想マシンの光学ドライブを指定する。今回はOSのインストールメディアであるISOファイルをマウントさせるため、ISOファイルのパスを指定する。
vm_boot 起動時にEFIを使用し、セキュアブートを有効化するよう指定する。
vm_usb_type USBコントローラとして、USB 2.0のコントローラを指定する。
  vars:
      ~(中略)~
    vm_name: ansible-test
    vm_annotation: "Create Ansible"
    vm_folder: /
    vm_guest_id: other4xLinux64Guest
    vm_hardware:
      num_cpus: 2
      num_cpu_cores_per_socket: 2
      memory_mb: 2048
    vm_disk:
      size_gb: 16
      type: thin
      datastore: Datastore-01
    vm_networks:
      name: Network_01
      device_type: vmxnet3
    vm_cdrom:
      iso_path: '[nfs_01] ISO/AlmaLinux/AlmaLinux-8.5-x86_64-minimal.iso'
    vm_boot:
      boot_firmware: efi
      secure_boot_enabled: true
    vm_usb_type: usb2

tasks : 処理内容

VMwareのAnsibleモジュールでは、毎回実行対象ESXiのホスト名、ユーザ名、パスワード、証明書検証の無効化を指定する必要があるため、以下4行を各タスクに設定するようにしよう。

        hostname: "{{ inventory_hostname }}"
        username: "{{ esxi_username }}"
        password: "{{ esxi_password }}"
        validate_certs: false

各タスクの処理概要を以下に記載する。
※モジュール名はFQCNで記載すると長くなるため名前だけの記載にしているが、PlaybookにはFQCNで記載することを推奨する。

タスク名 モジュール 設定
Create vm vmware_guest 仮想マシンを作成する。作成する仮想マシン名nameを指定し、CPU、メモリ、光学ドライブ、ディスク、ネットワークなどを設定する。ただし、一部起動時の設定やUSBコントローラの追加はできないため、それについては他タスクにて対応する。
Set boot settings vmware_guest_boot_manager 起動時BIOS/EFIの設定を行う。
Set usb controller vmware_guest_controller USBコントローラを追加する。
  tasks:
    # 仮想マシン作成
    - name: Create vm
      community.vmware.vmware_guest:
        hostname: "{{ inventory_hostname }}"
        username: "{{ esxi_username }}"
        password: "{{ esxi_password }}"
        validate_certs: false
        name: "{{ vm_name }}"
        annotation: "{{ vm_annotation }}"
        folder: "{{ vm_folder }}"
        guest_id: "{{ vm_guest_id }}"
        hardware:
          num_cpus: "{{ vm_hardware.num_cpus }}"
          num_cpu_cores_per_socket: "{{ vm_hardware.num_cpu_cores_per_socket }}"
          memory_mb: "{{ vm_hardware.memory_mb }}"
        cdrom:
          - controller_number: 0
            controller_type: sata
            unit_number: 0
            iso_path: "{{ vm_cdrom.iso_path }}"
            type: iso
        disk:
          - size_gb: "{{ vm_disk.size_gb }}"
            type: "{{ vm_disk.type }}"
            datastore: "{{ vm_disk.datastore }}"
        networks:
          - name: "{{ vm_networks.name }}"
            device_type: "{{ vm_networks.device_type }}"
            start_connected: true
        state: present

    # BIOS/EFI設定
    - name: Set boot settings
      community.vmware.vmware_guest_boot_manager:
        hostname: "{{ inventory_hostname }}"
        username: "{{ esxi_username }}"
        password: "{{ esxi_password }}"
        validate_certs: false
        name: "{{ vm_name }}"
        boot_firmware: "{{ vm_boot.boot_firmware }}"
        secure_boot_enabled: "{{ vm_boot.secure_boot_enabled }}"

    # USBコントローラ設定
    - name: Set usb controller
      community.vmware.vmware_guest_controller:
        hostname: "{{ inventory_hostname }}"
        username: "{{ esxi_username }}"
        password: "{{ esxi_password }}"
        validate_certs: false
        name: "{{ vm_name }}"
        controllers:
          - state: present
            type: "{{ vm_usb_type }}"

実行結果

実際にPlaybookを実行した結果を以下に記載する。

# ansible-playbook -i hosts create_vmware_vm.yml 

PLAY [Create vmware vm] *********************************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [esxi01]

TASK [Create vm] ****************************************************************************************************
changed: [esxi01]

TASK [Set boot settings] ********************************************************************************************
changed: [esxi01]

TASK [Set usb controller] *******************************************************************************************
changed: [esxi01]

PLAY RECAP **********************************************************************************************************
esxi01                  : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

実際にESXi上で作成した仮想マシンを確認すると、設定したパラメータ通りに作成が成功していた。


Ansibleを使ってESXi上に仮想マシンを構築するPlaybookの説明は以上となる。

参照

0 件のコメント:

コメントを投稿

人気の投稿