これまでAnsibleで、LinuxやWindows Serverの初期構築と単体テストを実施してきた。今回は、Ansibleを使ってESXi上に仮想マシンを構築するPlaybookを作ってみたので紹介する。なお、私の環境の問題でESXiを用いているが、少し修正すればvCenter Server経由でも実行することができるだろう。
今までのAnsible関連記事
- AnsibleコントロールノードをAlmaLinux上に構築する
- AnsibleからLinuxサーバに接続するための事前作業
- AnsibleでLinuxサーバの初期設定と単体テストを行う
- Ansibleのベストプラクティスのディレクトリ構成でPlaybookを実行する
- AnsibleからWindows Serverに接続するための事前作業
- AnsibleでWindows Serverの初期設定と単体テストを行う
- AnsibleでESXi上に仮想マシンを構築する ←★本記事
環境
コントロールノードの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 件のコメント:
コメントを投稿