hidemium's blog

日々学んだことをアウトプットする。

vSphere7.0U3でのcloudbase-initを利用したWindowsのカスタマイズ

前回は、cloud-initを使った仮想マシンのカスタマイズについて試してみました。今回は、vSphere環境でのWindowsのcloudbase-initの設定方法について書いてみようと思います。

hidemium.hatenablog.com

構成

  • vCenter 7.0 U3
  • ESXi 7.0 Update 3
  • Windows Server 2019 (テンプレートVM)

テンプレートVMの作成

テンプレートVMを用意するために以下の設定を行っていきます。

まずは、Windows Server 2019のISOイメージを用意し、Ubuntu Server 2019のOSをインストールします。

OSのインストール後に、スナップショットを取っておきます。(その後の操作でログインができない状態となるとOSのインストールから再開する必要があるため)

次に、cloudbase-initのインストーラーを以下でダウンロードします。

https://cloudbase.it/cloudbase-init/#download

CloudbaseInitSetup_1_1_2_x64.msi を実行し、インストールを行っていきます。

  1. セットアップウィザードでNextをクリックします。
  2. I accept the terms in the License Agreementをチェックし、Nextをクリックします。
  3. 特に変更せずに、Nextをクリックします。
  4. Use metadata passwodのチェックはそのままにし、Run Cloudbase-init service as LocalSystemをチェックし、Nextをクリックします。
  5. Installをクリックします。
  6. インストーラーをそのままの状態にし、C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init.conf をメモ帳で開き以下のように修正します。
[DEFAULT]
username=Admin
groups=Administrators
inject_user_password=true
config_drive_raw_hhd=true
config_drive_cdrom=true
config_drive_vfat=true
bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe
mtools_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\
verbose=true
debug=true
logdir=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\
logfile=cloudbase-init.log
default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN
logging_serial_port_settings=
mtu_use_dhcp_config=true
ntp_use_dhcp_config=true
local_scripts_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\LocalScripts\
check_latest_version=true
metadata_services=cloudbaseinit.metadata.services.vmwareguestinfoservice.VMwareGuestInfoService
plugins=cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin,cloudbaseinit.plugins.common.userdata.UserDataPlugin,cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin,cloudbaseinit.plugins.windows.createuser.CreateUserPlugin,cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin,cloudbaseinit.plugins.common.networkconfig.NetworkConfigPlugin
  1. C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init-unattend.conf をメモ帳で開き以下のように修正します。
[DEFAULT]
username=Admin
groups=Administrators
inject_user_password=true
config_drive_raw_hhd=true
config_drive_cdrom=true
config_drive_vfat=true
bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe
mtools_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\
verbose=true
debug=true
logdir=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\
logfile=cloudbase-init-unattend.log
default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN
logging_serial_port_settings=
mtu_use_dhcp_config=true
ntp_use_dhcp_config=true
local_scripts_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\LocalScripts\
check_latest_version=false
metadata_services=cloudbaseinit.metadata.services.vmwareguestinfoservice.VMwareGuestInfoService
plugins=cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin,cloudbaseinit.plugins.common.userdata.UserDataPlugin,cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin,cloudbaseinit.plugins.windows.createuser.CreateUserPlugin,cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin,cloudbaseinit.plugins.common.networkconfig.NetworkConfigPlugin
allow_reboot=false
stop_service_on_exit=false
  1. 最後に、Run Sysprep to cretate a generalized imageとShutdown when Sysprep treminatesにチェックを入れFinishをクリックします。
  2. syspreが実行され、仮想マシンの電源が停止します。

テンプレートからVMのクローン

テンプレートからカスタマイズを行うVMをクローンにより作成します。

この時電源はオフのままとします。

cloud-initのメタデータの作成

cloud-initによるカスタマイズを行うために、metadata-windows.yamlとuserdata-windows.yamlを用意します。

$ vi metadata-windows.yaml
instance-id: windows2019-1
local-hostname: windows2019-1
admin-password: password

VMwareGuestInfoServiceのネットワークの設定は、まだ実装されていないようです。(PRのマージ待ち)

VMwareGuestInfoService is not implementing static network configuration · Issue #78 · cloudbase/cloudbase-init · GitHub

ファイルを作成したい場合は以下のように設定を行います。

$ vi userdata-windows.yaml
#cloud-config
write_files:
- encoding: gz+b64
  content: ファイルに記載したい内容をgzip+base64でエンコードした内容を貼り付け
  path: C:\\vmware-guestinfo-cloudinit-datasource.txt

govcによるメタデータの追加

メタデータは、仮想マシンの以下のパラメータに追加することでゲストOS側に受け渡すことができます。

guestinfo.metadata
guestinfo.metadata.encoding
guestinfo.userdata
guestinfo.userdata.encoding

vSphere Clinetでメタデータを追加することも可能ですが、govcを使った方法が簡単なため、こちらで設定を行います。

以下の手順でgovcのインストールを行います。また、合わせて環境変数を設定しておきます。

$ curl -L -o - "https://github.com/vmware/govmomi/releases/latest/download/govc_$(uname -s)_$(uname -m).tar.gz" | sudo tar -C /usr/local/bin -xvzf - govc
$ export GOVC_URL=https://<vcenter fqdn>/sdk
$ export GOVC_USERNAME="username"
$ export GOVC_PASSWORD="password"
$ export GOVC_INSECURE="1"
$ export VM="/Datacenter/vm/path/to/vm name"
$ govc vm.info "${VM}"
Name:              vm name
  Path:            /Datacenter/vm/path/to/vm name
  Guest name:      Microsoft Windows Server 2019 (64-bit)
  Memory:          4096MB
  CPU:             2 vCPU(s)
  Power state:     poweredOff
  Boot time:       <nil>
  IP address:   
  Host:            hostname

環境変数メタデータとユーザーデータの値を設定します。

export METADATA=$(gzip -c9 <metadata-windows.yaml | { base64 -w0 2>/dev/null || base64; })      USERDATA=$(gzip -c9 <userdata-windows.yaml | { base64 -w0 2>/dev/null || base64; })

VMメタデータとユーザデータを設定します。

govc vm.change -vm "${VM}" -e guestinfo.metadata="${METADATA}" -e guestinfo.metadata.encoding="gzip+base64" -e guestinfo.userdata="${USERDATA}" -e guestinfo.userdata.encoding="gzip+base64"

VMの電源を入れます。

govc vm.power -on "${VM}"

VMが起動後に、コンソールで接続すると、Administratorユーザのパスワードのリセットが求められるため、新しいパスワードを設定します。

ログインユーザの追加の動作について

Administratorsグループに所属する、Adminユーザが作成され、初回ログイン時にmetadataで指定したパスワードを入力すると、パスワードの更新が求められました。

metadataで追加ユーザのパスワード指定を行う場合は、 CreateUserPlugin だけではなく、 SetUserPasswordPlugin の指定も必要でした。

参考

vSphere7.0U3でのcloud-initを利用した仮想マシンのカスタマイズ

vSphere7.0U3からcloud-initを使った仮想マシンのカスタマイズがサポートされるようになりました。vSphere環境でのcloud-initの設定方法について書いてみようと思います。

構成

  • vCenter 7.0 U3
  • ESXi 7.0 Update 3
  • Ubuntu 22.04 (テンプレートVM)

cloud-initを利用するための要件

以下のKBにcloud-initを利用するための要件の記載がありました。

https://kb.vmware.com/s/article/82250

Prerequisites
• Ensure that vSphere version is 7.0 Update 3 or later
• Ensure that VMware Tools version 11.3.0 or later is installed.
• Ensure that cloud-init version 21.1 or later is installed.

このあたりのバージョンを満たしているUbuntu 22.04を利用して手順を試してみました。

テンプレートVMの作成

テンプレートVMを用意するために以下の設定を行っていきます。

まずは、Ubuntu 22.04のISOイメージを用意し、Ubuntu 22.04のOSをインストールします。

OSのインストール後に、スナップショットを取っておきます。(その後の操作でログインができない状態となるとOSのインストールから再開する必要があるため)

次に、cloud-initの構成ファイルの末尾のエントリに次を追加します。

この設定は分かりにくいですが、 disable_vmware_customizationfalse でcloud-initによるカスタマイズを有効にする設定となり、 true仮想マシンのカスタマイズ仕様によるカスタマイズを有効にする設定となります。

$ sudo vi /etc/cloud/cloud.cfg
disable_vmware_customization: false

次のファイルを削除します。

$ cd  /etc/cloud/cloud.cfg.d/
$ sudo rm 99-installer.cfg
$ sudo rm subquity-disable-cloudinit-networking.cfg

cloud-initコマンドでクリーン操作を実施します。その後シャットダウンを行います。

$ sudo /usr/bin/cloud-init clean --logs
$ sudo shutdown -h now

テンプレートからVMのクローン

テンプレートからカスタマイズを行うVMをクローンにより作成します。

この時電源はオフのままとします。

cloud-initのメタデータの作成

cloud-initによるカスタマイズを行うために、metadata.yamlとuserdata.yamlを用意します。

ネットワークをstaticに設定を行いたい場合は以下のように設定を行います。

instance-idは設定を行わない場合は、 /sys/class/dmi/id/product_uuid から読み取られるようです。

$ vi metadata.yaml
instance-id: ubuntu22-1
local-hostname: ubuntu22-1
hostname: ubuntu22-1
network:
  version: 2
  ethernets:
    ens192:
      dhcp4: false
      addresses:
      - 192.168.1.2/24
      gateway4: 192.168.1.1
      nameservers:
        addresses:
        - 192.168.1.1

ネットワークをDHCPで設定を行いたい場合は以下のように設定を行います。

$ vi metadata.yaml
instance-id: ubuntu22-1
local-hostname: ubuntu22-1
hostname: ubuntu22-1
network:
  version: 2
  ethernets:
    ens192:
      dhcp4: true

公開鍵認証を行うユーザを新規に追加する場合は、以下のように設定します。また、必要なパッケージも追加することで自動インストールすることができます。

$ vi userdata.yaml
#cloud-config

users:
  - default
  - name: username
    ssh_authorized_keys:
      - 公開鍵をペースト
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups: sudo, wheel
    lock_passwd: true
    shell: /bin/bash
 
packages:
    - 必要なパッケージ名を追加

govcによるメタデータの追加

メタデータは、仮想マシンの以下のパラメータに追加することでゲストOS側に受け渡すことができます。

guestinfo.metadata
guestinfo.metadata.encoding
guestinfo.userdata
guestinfo.userdata.encoding

vSphere Clinetでメタデータを追加することも可能ですが、govcを使った方法が簡単なため、こちらで設定を行います。

以下の手順でgovcのインストールを行います。また、合わせて環境変数を設定しておきます。

$ curl -L -o - "https://github.com/vmware/govmomi/releases/latest/download/govc_$(uname -s)_$(uname -m).tar.gz" | sudo tar -C /usr/local/bin -xvzf - govc
$ export GOVC_URL=https://<vcenter fqdn>/sdk
$ export GOVC_USERNAME="username"
$ export GOVC_PASSWORD="password"
$ export GOVC_INSECURE="1"
$ export VM="/Datacenter/vm/path/to/vm name"
$ govc vm.info "${VM}"
Name:              vm name
  Path:            /Datacenter/vm/path/to/vm name
  Guest name:      Ubuntu Linux (64-bit)
  Memory:          2048MB
  CPU:             1 vCPU(s)
  Power state:     poweredOff
  Boot time:       <nil>
  IP address:   
  Host:            hostname

環境変数メタデータとユーザーデータの値を設定します。

export METADATA=$(gzip -c9 <metadata.yaml | { base64 -w0 2>/dev/null || base64; })      USERDATA=$(gzip -c9 <userdata.yaml | { base64 -w0 2>/dev/null || base64; })

VMメタデータとユーザデータを設定します。

govc vm.change -vm "${VM}" -e guestinfo.metadata="${METADATA}" -e guestinfo.metadata.encoding="gzip+base64" -e guestinfo.userdata="${USERDATA}" -e guestinfo.userdata.encoding="gzip+base64"

VMの電源を入れます。

govc vm.power -on "${VM}"

VMが起動後に、公開鍵認証を利用してsshでログインできることを確認します。

ssh username@192.168.1.2

vSphere環境でもcloud-initが利用できるようになり、より自動化がしやすくなっていくのでは思います。

参考

Visual Studio Codeのdevcontainerを設定する

開発環境として、Visual Studio Codeでdevcontainerのセットアップ方法についてまとめてみました。

構成

Dockerのインストール (Ubuntu 20.04側)

まずは、前回の記事のVisual Studio CodeのRemote Developmentの設定を行っておきます。

hidemium.hatenablog.com

devcontainerを利用するために、Dockerをインストールしておきます。

dockerコマンドをsudoなしで実行できるように設定を行っておきます。

$  sudo apt install docker docker-compose
$ sudo groupadd docker
$ sudo gpasswd -a $USER docker
$ sudo systemctl restart docker

作業用のディレクトリの用意 (Ubuntu 20.04側)

Ubuntu 20.04側で作業用ディレクトリを用意します。

$ mkdir <project directory>
$ cd <project directory>

devcontainerの設定方法について、MSがサンプルコードを公開しています。

GitHub - microsoft/vscode-remote-try-python: Python sample project for trying out the VS Code Remote - Containers extension

上記を参考に、devcontainerに必要なディレクトリとファイルを用意していきます。

$ mkdir .devcontainer
$ cd .devcontainer
$ vi devcontainer.json
$ vi Dockerfile
$ cd ..
$ vi requirements.txt
$ tree -a
├── .devcontainer
│   ├── devcontainer.json
│   └── Dockerfile
├── app.py
└── requirements.txt

devcontainer.jsonの中で、Dockerfile、pythonのlint設定、Visual Studio Code拡張機能のpylance、requirements.txtの指定などを行っています。開発環境の構成を統一して管理できるというメリットがあります。

devcontainerの接続

Visual Studio CodeのRemote DevelopmentでUbuntu 20.04へ接続を行います。

右下のグリーンのボタンをクリックすると、メニューが表示されるため、 Reopen in Container をクリックします。

コンテナのビルドが実行し、開発環境が用意されます。

ターミナルの画面に以下のように表示され、コンテナ内で操作ができるようになります。

vscode ➜ /workspaces/vscode-container $ 

起動したコンテナは、コンテナホスト側のディレクトリがマウントされており、コンテナ内で作成したファイルはコンテナホスト側に保存されます。

設定は以上となります。

Visual Studio CodeのRemote Developmentを設定する

開発環境として、Visual Studio CodeでRemote Developmentのセットアップ方法についてまとめてみました。

構成

Visual Studio CodeのRemote Developmentのインストール (Windows 10側)

Visual Studio CodeのExtensionsのアイコンをクリックし、 Remote - SSH をインストールします。

Remote Explorerのアイコンが出てくるため、こちらをクリックし、歯車のアイコンをクリックし、SSH構成ファイルを選択します。通常は C:\Users\User Name\.ssh/config でよいかと思います。

新規にSSHターゲットを追加します。sshのコマンドのフォーマットでログイン設定を登録します。 C:\Users\User Name\.ssh/config に設定が追加されていることが確認できます。

追加したSSHターゲットの右横にアイコンをクリックし、新規ウインドでホストに接続します。

プラットフォームの種類を聞かれるため、 Linux を選択します。

フィンガープリントを聞かれるため、続行をクリックします。

Ubuntu側では .vscode-server ディレクトリが作成され、必要なファイルが自動的にダウンロードされます。

初期設定では、ログインパスワードを聞かれるため、公開鍵認証を使ってログインする設定を行います。設定方法はターミナルを使ってログインする方法と変わりません。

Windowsを使っているので、PowerShellで公開鍵と秘密鍵を生成します。

> ssh-keygen

C:\Users\User Name\.ssh/id_rsaC:\Users\User Name\.ssh/id_rsa.pub が生成されます。

公開鍵認証の設定 (Ubuntu 20.04側)

Ubuntu側にログインし、公開鍵認証の設定を行っていきます。

$ mkdir .ssh
$ chmod 700 ./.ssh/

id_rsa.pubファイルをUbuntuに転送しておきます。

$ cd .ssh/
$ cat ./id_rsa.pub >> ./authorized_keys

Visual Studio CodeのRemote Developmentの設定 (Windows 10側)

Windows 10に戻り、Visual Studio CodeのExtensionsのアイコンをクリックしすると、LOCALと接続したSSHターゲットのパッケージ情報が確認できるようになります。

Pythonのコードを書きたい場合は、MicrosoftPython拡張機能をインストールします。

Pythonで検索して、拡張機能の画面にいくと、 Install in SSH: <SSHターゲット> という表示に変わっています。

Python拡張機能がリモート側にインストールされることが分かります。

Install in SSH: <SSHターゲット> をクリックして、拡張機能をインストールします。

Pythonの仮想環境の設定

Pythonの仮想環境についても準備しておきます。

プロジェクトフォルダにvenvの環境をインストールします。

$ python3 --version
Python 3.8.10
$ sudo apt install python3.8-venv
$ mkdir <project directory>
$ cd <project directory>
$ python3 -m venv venv

Visual Studio Codeのプロジェクトフォルダを開き、Terminalを開くと、自動的にvenvの環境がactivateされるようになります。

$ source /home/username/project_directory/venv/bin/activate
(venv) $

Pythonのコードを書いていくと、Visual Studio Code拡張機能により入力補完など便利な機能が利用できるようになっていることが分かります。

設定は以上となります。

Ansibleのディレクトリ構成とロールの作成について

前回、AnsibleのVMwareモジュールについてインストールしてみましたが、利便性を高める方法について書いてみようと思います。小規模環境を想定して書いています。

構成

  • vCenter 7.0 U2
  • ESXi 7.0 Update 2
  • Ubuntu 20.04 (Ansible実行環境)

Ansibleのディレクトリ構成について

前回はシンプルに動作確認を行うために、インベントリファイルとplaybookのみの構成でした。AnsibleのSample directory layoutという構成をベースに作り替えていきたいと思います。

Sample Ansible setup — Ansible Documentation

Sample directory layoutは、以下のような構成となっています。

production                # inventory file for production servers
staging                   # inventory file for staging environment

group_vars/
   group1.yml             # here we assign variables to particular groups
   group2.yml
host_vars/
   hostname1.yml          # here we assign variables to particular systems
   hostname2.yml

library/                  # if any custom modules, put them here (optional)
module_utils/             # if any custom module_utils to support modules, put them here (optional)
filter_plugins/           # if any custom filter plugins, put them here (optional)

site.yml                  # main playbook
webservers.yml            # playbook for webserver tier
dbservers.yml             # playbook for dbserver tier
tasks/                    # task files included from playbooks
    webservers-extra.yml  # <-- avoids confusing playbook with task files

roles/
    common/               # this hierarchy represents a "role"
        tasks/            #
            main.yml      #  <-- tasks file can include smaller files if warranted
        handlers/         #
            main.yml      #  <-- handlers file
        templates/        #  <-- files for use with the template resource
            ntp.conf.j2   #  <------- templates end in .j2
        files/            #
            bar.txt       #  <-- files for use with the copy resource
            foo.sh        #  <-- script files for use with the script resource
        vars/             #
            main.yml      #  <-- variables associated with this role
        defaults/         #
            main.yml      #  <-- default lower priority variables for this role
        meta/             #
            main.yml      #  <-- role dependencies
        library/          # roles can also include custom modules
        module_utils/     # roles can also include custom module_utils
        lookup_plugins/   # or other types of plugins, like lookup in this case

    webtier/              # same kind of structure as "common" was above, done for the webtier role
    monitoring/           # ""
    fooapp/               # ""

playbookとロールの作成

このSample directory layoutを一括で作成する公式ツールは見当たらなかったので、mkdirで作成していきます。

$ cd ~/ansible-vmware
$ mkdir {group_vars,host_vars,roles}

次に、inventoryを定義しておきます。仮想マシンhomelab_vm グループとして定義しておきます。

$ cd ~/ansible-vmware
$ vi inventory.yml
---
all:
  children:
    homelab_vm:
      hosts:
        VM name:

次に、playbookを定義しておきます。 homelab_vm グループのホストに対して、 guest_info というロールを実行するように定義します。

$ cd ~/ansible-vmware
$ vi pb_guest_info.yml
---
- hosts: homelab_vm
  gather_facts: false
  roles:
    - guest_info

次にロールを書いていきます。前回の仮想マシンの情報を取得する処理をベースにしていきます。

まず、rolesに guest_info というロールを作成します。ロールの作成はansible-galaxyコマンドを利用します。

$ cd ~/ansible-vmware
$ cd roles
$ ansible-galaxy init guest_info
$ tree -L 2
.
└── guest_info
    ├── defaults
    │   └── main.yml
    ├── files
    ├── handlers
    │   └── main.yml
    ├── meta
    │   └── main.yml
    ├── README.md
    ├── tasks
    │   └── main.yml
    ├── templates
    ├── tests
    │   ├── inventory
    │   └── test.yml
    └── vars
        └── main.yml

taskのmain.ymlを編集します。

$ cd guest_info
$ vi task/main.yml
---
- name: Gather info for VM
  community.vmware.vmware_guest_info:
    hostname: "{{ vcenter_hostname }}"
    username: "{{ vcenter_username }}"
    password: "{{ vcenter_password }}"
    validate_certs: no
    datacenter: "{{ datacenter_name }}"
    name: "{{ inventory_hostname }}"
  delegate_to: localhost
  register: result

- debug: var=result

group_varsにvCenterの情報を記載していきます。Ansible Vaultのベストプラクティスに沿って、Vaultで暗号化された変数として vault_ を変数の頭につけます。

Tips and tricks — Ansible Documentation

$ cd ~/ansible-vmware/group_vars
$ mkdir all
$ cd all
$ vi main.yml 
vcenter_username: "{{ vault_vcenter_username }}"
vcenter_password: "{{ vault_vcenter_password }}
$ vi vault.yml
---
vault_vcenter_username: vCenter username
vault_vcenter_password: password
$ ansible-vault encrypt vault.yml
New Vault password: 
Confirm New Vault password: 
Encryption successful

Ansible Vaultのパスワードを毎回入力することが大変なため、 パスワードを記載したファイルを定義しておきます。

$ cd ~/ansible-vmware
$ vi .vault_password
password
$ vi ansible.cfg
[defaults]
vault_password_file = .vault_password

次に、taskの実行に必要な変数について homelab_vm グループの情報として取得できるように、group_vars配下にフォルダを作成して記載していきます。

$ cd ~/ansible-vmware/group_vars
$ mkdir homelab_vm
$ cd homelab_vm
$ vi main.yml
---
vcenter_hostname: vCenter Name
datacenter_name: Datacenter Name

最後に、playbookを実行できるか確認します。

$ ansible-playbook -i inventory.yml pb_guest_info.yml
PLAY [homelab_vm] ************************************************************************************************************************************************************************

TASK [guest_info : Gather info for VM] ***************************************************************************************************************************************************
ok: [VM name -> localhost]

TASK [guest_info : debug] ****************************************************************************************************************************************************************
ok: [VM name] => {
    "result": {
        "changed": false,
        "failed": false,
        "instance": {
            "advanced_settings": {
                "ethernet0.pciSlotNumber": "192",
~ 中略 ~
            "vimref": "vim.VirtualMachine:vm-2028",
            "vnc": {}
        }
    }
}

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

必要なファイルが増えましたが、全体構成として以下のようになりました。

$ tree -L 4
.
├── ansible.cfg
├── group_vars
│   ├── all
│   │   ├── main.yml
│   │   └── vault.yml
│   └── homelab_vm
│       └── main.yml
├── host_vars
├── inventory.yml
├── pb_guest_info.yml
├── requirements.yml
├── roles
│   └── guest_info
│       ├── defaults
│       │   └── main.yml
│       ├── files
│       ├── handlers
│       │   └── main.yml
│       ├── meta
│       │   └── main.yml
│       ├── README.md
│       ├── tasks
│       │   └── main.yml
│       ├── templates
│       ├── tests
│       │   ├── inventory
│       │   └── test.yml
│       └── vars
│           └── main.yml
└── venv
    ├── bin
~ 中略 ~

AnsibleのVMwareモジュールについて

Ansibleを利用すると、ESXiやvCenter、仮想マシンに対しての操作を自動化することができます。AnsibleのVMwareモジュールについて最近の状況について確認してみたいと思います。

構成

  • vCenter 7.0 U2
  • ESXi 7.0 Update 2
  • Ubuntu 20.04 (Ansible実行環境)

VMwareモジュールについて

Ansible 2.9まではAnsibleのコアとコミュニティーなどが一つにまとまって配布されていましたが、2.10以降からはコア以外はCollectionsとして外出しとなりました。

2022/6/15現在、Ansibleのバージョンは5となっており、community.vmware というVMwareのCollectionsのモジュールは以下で確認できます。

Community.Vmware — Ansible Documentation

community.vmware` のVMwareのCollectionsのモジュールは以下のGitHubリポジトリで開発されています。

GitHub - ansible-collections/community.vmware: Ansible Collection for VMWare

VMwareモジュールには、VMware vSphere APIPython SDKのpyVmomiが必要になります。

$ pip install pyvmomi

また、NSX-TやVMware Cloud on AWS向けに vSphere Automation Python SDK が必要となります。

$ pip install --upgrade git+https://github.com/vmware/vsphere-automation-sdk-python.git

また、 vmware.vmware_rest というVMwareのCollectionsのモジュールもあり、こちらは、pyVmomiやvSphere Automation Python SDKに依存せずに、vSphereのREST APIの仕様に基づいてコミニュティーが開発しているものになります。

Vmware.Vmware_Rest — Ansible Documentation

vmware.vmware_restVMwareのCollectionsのモジュールは以下のGitHubリポジトリで開発されています。

GitHub - ansible-collections/vmware.vmware_rest: Ansible Collection for VMWare (REST modules)

インストール

community.vmware を利用したAnsibleが実行できる環境を準備してみようと思います。

Python 3.8以降がインストールされている必要があります。

venvの環境をインストールします。(Ansibleの公式サイトでは、virtualenvを使っていましたが、Python 3.3からはvenvがPython標準ライブラリとなったためこちらを利用します。)

$ python3 --version
Python 3.8.10
$ sudo apt install python3.8-venv
$ mkdir ansible-vmware
$ cd ansible-vmware
$ python3 -m venv venv (python3 -m venv [仮想環境ディレクトリ名])

venvというフォルダが作成されました。

$ tree -L 4
.
└── venv
    ├── bin
    │   ├── activate
    │   ├── activate.csh
    │   ├── activate.fish
    │   ├── Activate.ps1
    │   ├── easy_install
    │   ├── easy_install-3.8
    │   ├── pip
    │   ├── pip3
    │   ├── pip3.8
    │   ├── python -> python3
    │   └── python3 -> /usr/bin/python3
    ├── include
    ├── lib
    │   └── python3.8
    │       └── site-packages
    ├── lib64 -> lib
    ├── pyvenv.cfg
    └── share
        └── python-wheels
            ├── appdirs-1.4.3-py2.py3-none-any.whl
            ├── CacheControl-0.12.6-py2.py3-none-any.whl
            ├── certifi-2019.11.28-py2.py3-none-any.whl
            ├── chardet-3.0.4-py2.py3-none-any.whl
            ├── colorama-0.4.3-py2.py3-none-any.whl
            ├── contextlib2-0.6.0-py2.py3-none-any.whl
            ├── distlib-0.3.0-py2.py3-none-any.whl
            ├── distro-1.4.0-py2.py3-none-any.whl
            ├── html5lib-1.0.1-py2.py3-none-any.whl
            ├── idna-2.8-py2.py3-none-any.whl
            ├── ipaddr-2.2.0-py2.py3-none-any.whl
            ├── lockfile-0.12.2-py2.py3-none-any.whl
            ├── msgpack-0.6.2-py2.py3-none-any.whl
            ├── packaging-20.3-py2.py3-none-any.whl
            ├── pep517-0.8.2-py2.py3-none-any.whl
            ├── pip-20.0.2-py2.py3-none-any.whl
            ├── pkg_resources-0.0.0-py2.py3-none-any.whl
            ├── progress-1.5-py2.py3-none-any.whl
            ├── pyparsing-2.4.6-py2.py3-none-any.whl
            ├── requests-2.22.0-py2.py3-none-any.whl
            ├── retrying-1.3.3-py2.py3-none-any.whl
            ├── setuptools-44.0.0-py2.py3-none-any.whl
            ├── six-1.14.0-py2.py3-none-any.whl
            ├── toml-0.10.0-py2.py3-none-any.whl
            ├── urllib3-1.25.8-py2.py3-none-any.whl
            ├── webencodings-0.5.1-py2.py3-none-any.whl
            └── wheel-0.34.2-py2.py3-none-any.whl

仮想環境のアクティベートし、Ansibleをインストールします。

$ source venv/bin/activate
(venv) $ python -m pip install ansible
(venv) $ pip list
$ deactivate #仮想環境を終了する場合
Package       Version
------------- -------
ansible       5.9.0  
ansible-core  2.12.6 
cffi          1.15.0 
cryptography  37.0.2 
Jinja2        3.1.2  
MarkupSafe    2.1.1  
packaging     21.3   
pip           20.0.2 
pkg-resources 0.0.0  
pycparser     2.21   
pyparsing     3.0.9  
PyYAML        6.0    
resolvelib    0.5.4  
setuptools    44.0.0

Ansibleをインストールすると、 .ansible というCollectionがインストールされるディレクトリが作成されます。

.ansible # Collection
ansible-vmware/venv # 仮想環境のディレクトリ

Collectionをインストールします。requirements.ymlを用意し、インストールしてみます。

$ vi requirements.yml
collections:
- name: community.vmware
$ ansible-galaxy collection install -r requirements.yml

collectionのフォルダ内にrequirements.txtがあり、こちらを利用し、pyvmomiとvSphere Automation Python SDKをインストールします。

(venv) $ python -m pip install -r ~/.ansible/collections/ansible_collections/community/vmware/requirements.txt
(venv) $ pip list
Package                            Version    
---------------------------------- -----------
ansible                            5.9.0      
ansible-core                       2.12.6     
certifi                            2022.5.18.1
cffi                               1.15.0     
charset-normalizer                 2.0.12     
cryptography                       37.0.2     
idna                               3.3        
Jinja2                             3.1.2      
lxml                               4.9.0      
MarkupSafe                         2.1.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  
packaging                          21.3       
pip                                20.0.2     
pkg-resources                      0.0.0      
pycparser                          2.21       
pyOpenSSL                          22.0.0     
pyparsing                          3.0.9      
pyvmomi                            7.0.3      
PyYAML                             6.0        
requests                           2.28.0     
resolvelib                         0.5.4      
setuptools                         44.0.0     
six                                1.16.0     
urllib3                            1.26.9     
vapi-client-bindings               3.8.0      
vapi-common-client                 2.34.0     
vapi-runtime                       2.34.0     
vmc-client-bindings                1.59.0     
vmc-draas-client-bindings          1.19.0     
vSphere-Automation-SDK             1.77.0

まずはシンプルに、vCenterに接続し、仮想マシンの情報を取得する処理を実行してみます。delegate_to: localhost を記載することで、Ansibleの実行ホストでplaybookを実行するように指定します。

$ vi test.yml
---
- name: Collections vmware sample playbook
  hosts: all
  gather_facts: no
  vars:
    vcenter_hostname: <vCenter Name>
    vcenter_username: administrator@vsphere.local
    vcenter_password: <password>
    datacenter_name: <Datacenter Name>
  tasks:
    - name: Gather info for VM
      community.vmware.vmware_guest_info:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        validate_certs: no
        datacenter: "{{ datacenter_name }}"
        name: "{{ inventory_hostname}}"
      delegate_to: localhost
      register: result

    - debug: var=result

vmグループを定義し、その中に情報を取得したいVM名を記載します。

$ vi inventory.yml
all:
  children:
    vm:
      hosts:
        <VM Name>:

playbookを実行し、仮想マシンの情報が取得できていることを確認します。

$ ansible-playbook -i inventory.yml test.yml

PLAY [Collections vmware sample playbook] ************************************************************************************************************************************************

TASK [Gather info for VM] ****************************************************************************************************************************************************************
ok: [<VM name> -> localhost]

TASK [debug] *****************************************************************************************************************************************************************************
ok: [<VM name>] => {
    "result": {
        "changed": false,
        "failed": false,
        "instance": {
            "advanced_settings": {
                "ethernet0.pciSlotNumber": "192",

~ 中略 ~
            "vimref": "vim.VirtualMachine:vm-2028",
            "vnc": {}
        }
    }
}

PLAY RECAP *******************************************************************************************************************************************************************************
<VM name>                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

参考

AnsibleのVMware Collectionsを使う方法 | 日常系エンジニアのTech Blog

Homelabの2022年の更新について

Intel NUCでHomelabを構築していますが、2022年になり構成の見直しを行ってみました。

当初の構成

変更後の更新

更新のための検討事項について

静音の対応

自宅でHomelabを構築していると、どうしてもファンの音について考慮する必要がでてきます。Synology DS416slimは、コンパクトな大きさでファンの音がそこまで大きくはないのですが、静かな時間帯になるとどうしても音が気になってしまいます。そのため、NASを配置しないという構成ができないか検討しました。

NASの代わりに、ESXiの内蔵ディスクを増強し、内蔵ディスクに仮想マシンを展開する方針としました。また、NVMeであれば、シーケンシャルの読み取りが3500MB/s、シーケンシャルの書き込みが3000MB/s程度あるため、性能としてはNASと比較するとかなり良くなります。ただし、可用性は下がるので、可用性が下がることを許容した構成となります。

また、内蔵ディスクとしてもともとは256GBのNVMeを利用していましたが、容量が不足するため、1TBのNVMeに変更しました。

共有ストレージを利用しない構成

vMotionについても、共有ストレージを利用しないshared nothing vMotionが利用できため、利用上問題はないと考えました。 また、共有ストレージを利用せず、検証環境であるためDRSは無効とします。vSphere7.0u1からvCLS(vSphere Cluster Services)が実装されたため、vCLSのVMが自動的に展開されるため、vCLSも無効にします。

vCLSを無効にするためには、vCenter Server の詳細設定に以下の設定を追加します。

  • 名前: config.vcls.clusters.domain-c8(対象環境のクラスタのオブジェクト名).enabled
  • 値: false

ESXi 7.0のブート領域の変更

ESXi 7.0からは、USBフラッシュメモリブートの非推奨化されました。

VMware Knowledge Base

USBフラッシュメモリでもインストール可能ですが、推奨構成に合わせるために、2.5インチのSSDを追加し、2.5インチのSSDにブート領域としてインストールします。 また、ブート領域がデフォルトで138GB消費されるため、検証環境のためサイズを節約するため、サイズを小さく指定します。

min(33 GB、1 台のディスクまたは組み込みのサーバ用)
small(69 GB、512 GB 以上の RAM を搭載したサーバ用)
default (138 GB)
max(使用可能なすべての容量を使用、マルチテラバイトのサーバ用)

ESXi のシステム ストレージの概要

ブートメディアからのスタートアップでShift+Oを押し、オプションを指定します。Shift+Oの入力は素早くする必要があるので、電源を入れてから連打しておくとよいかと思います。 ブートオプションに systemMediaSize=small を追加します。

runweasel cdromBoot systemMediaSize=small

ESXi 7.0のカスタムインストーラの作成

ESXi 7.0のブート領域の変更するため、新しくカスタムインストーラを用意します。カスタムインストーラはPowerCLIを利用することで作成することができます。

PowerCLIをインストールします。

ESXiのバイナリとUSB Network Native Driver for ESXiのバイナリを作業フォルダに配置します。(今回はESXi 7.0U2のイメージを利用しました。) * VMware-ESXi-7.0U2e-19290878-depot.zip * ESXi702-VMKUSB-NIC-FLING-47140841-component-18150468.zip * USB Network Native Driver for ESXi | VMware Flings

バイナリを追加します。

Add-EsxSoftwaredepot -DepotUrl .\VMware-ESXi-7.0U2e-19290878-depot.zip
Add-EsxSoftwaredepot -DepotUrl .\ESXi702-VMKUSB-NIC-FLING-47140841-component-18150468.zip

パッケージを確認します。

 Get-EsxSoftwarePackage |ft -AutoSize

イメージプロファイルを定義します。

$ip = (Get-EsxImageprofile)[0]
New-EsxImageprofile -CloneProfile $ip -Vendor homelab -Name Intel-NUC-7.0U2e -AcceptanceLevel CommunitySupported

USB Network Native Driverのパッケージを追加します。

Add-EsxSoftwarePackage -ImageProfile Intel-NUC-7.0U2e -SoftwarePackage vmkusb-nic-fling

カスタムインストーラをzipファイルとisoファイルとしてエクスポートします。

Export-EsxImageprofile -Imageprofile Intel-NUC-7.0U2e -FilePath .\Intel-NUC-7.0U2e.zip -ExportToBundle
Export-EsxImageprofile -Imageprofile Intel-NUC-7.0U2e -FilePath .\Intel-NUC-7.0U2e.iso -ExportToIso

UNetbootinを起動し、ディスクイメージにチェックを入れ、ISOを選択し、Intel-NUC-7.0U2e.isoを選択することで、USBドライブにブートイメージを作成します。 USBドライブをIntel NUCに接続し、電源をオンすることでESXiのインストーラーが起動します。

Western DigitalのNVMe SSD WDS100T3B0C-ECはCommunity NVMe Driver for ESXiをインストールせずに動作することが確認ができました。

メモリの増強について

NUC7i3BNHの最大メモリサイズは32GBですが、32GBサポートのIntel NUCで64GBのメモリまで認識することが以下の記事に上がっており、今回32GBのメモリが認識するか試してみました。16GBのメモリを32GBのメモリに入れ替え、全体で32GBから48GBになることが確認できました。

64GB memory on the Intel NUCs?

Intel Core i5Intel NUCについて

Intel Core i5プロセッサーを利用したIntel NUCも検討しましたが、ファンの音が大きいというレビューがあり、静音を優先して今回は見送りました。

更新後の構成について

更新後のスペックとして、このようになりました。ほぼ無音で快適な環境になりました。今後Tanzu Community Editionなどメモリが必要な検証が可能か試してみようと思います。

参考

自宅らぼ再入門 おうちクラウドのすすめ 20210922