20
27

More than 3 years have passed since last update.

Ansible + PXE + Kickstart で ESXi Server 上にVMを作成し、OSをインストールする

Last updated at Posted at 2020-07-29

無償版 ESXi Server 上にVMを作成し、OSをインストールするまでを自動化できないか試行錯誤した結果をまとめます。

目標

  • 無償版 ESXi Server に Ansible から指定する構成で VM を作成できるようにする
  • VMを起動すると PXE boot、Kickstart によりOSを自動でインストールできるようにする

構成

  • ESXi Server (192.168.33.50)
    • VMware vSphere Hypervisor 7.0
  • Ansible client (192.168.33.11)
    • CentOS8
    • Ansible 2.8 + vsphere_guest モジュール
  • PXE / Kickstart Server (192.168.33.10)
    • CentOS8
    • tftp-server
    • dhcp
    • httpd
    • syslinux

Ansible client の構成

無償版ESXi ServerをAnsibleから操作する場合、Ansible2.9でobsoleteとなった vsphere_guest を選択するしかないようです。(公式モジュールの vmware_guest を使用したら以下のエラーが出て使えませんでした。)

Failed to create virtual machine due to product versioning restrictions: Current license or ESXi version prohibits execution of the requested operation.

※ vsphere_guest と vmware_guest の比較については下記記事を参照してください:

仕方がないので、virtualenv で Ansible2.8 環境をつくることにします。

PXE / Kickstart Server の構成

PXE, Kickstart によるOSインストールの流れは以下の通りです:

  1. VMの電源を入れる
  2. VMがdhcp serverに通信する
  3. dhcp serverがIPアドレスとPXE ServerのIPアドレスを返す
  4. tftp server に PXE boot file を取りに行く
  5. http server に Kickstart file, OS イメージを取りに行く
  6. OSの自動インストール

4.の処理では、まず、MACアドレスに対応する名前(16進数が小文字で表記されハイフンで区切られたもの)のブート構成ファイルを検索する仕様になっています。たとえば、MACアドレスが88:99:AA:BB:CC:DDの場合は、01-88-99-aa-bb-cc-dd (01-{MAC-ADDRESS}) というファイルを検索します。見つからない場合は default という名前のファイルを検索します。

したがって、ESXi Server にVMを作成するときは、MACアドレスを手動で設定し、そのMACアドレスに対応した PXE boot file を配置するとよさそうです。

資材

以下のISOイメージを用意します。

Ansible client のインストール

pysphere は Python2系のようなので、Python2をインストールします。Ansibleは2.8系の最新版である 2.8.12 をインストールします。

sudo dnf -y install python2
sudo pip2 install virtualenv
python2 -m virtualenv ansible-py2
source ansible-py2/bin/activate
pip install ansible==2.8.12
pip install pysphere
ansible -i localhost, all -m ping -c local

最後の ansible コマンドで pong が返れば成功です。

PXE / Kickstart Server のインストール

dhcp server, tftp server, http server をインストールし、各種資材を配置していきます。

dhcp server のインストール

以下の設計でインストール・設定します。

パラメータ
subnet 192.168.33.0/24
range 192.168.33.100 - 192.168.33.199
pxe server 192.168.33.10
boot BIOS
sudo dnf -y install dhcp-server
sudo vi /etc/dhcp/dhcpd.conf
sudo systemctl enable --now dhcpd
sudo firewall-cmd --add-service=dhcp --permanent 
sudo firewall-cmd --reload 
/etc/dhcp/dhcpd.conf
option space pxelinux;
option pxelinux.magic code 208 = string;
option pxelinux.configfile code 209 = text;
option pxelinux.pathprefix code 210 = text;
option pxelinux.reboottime code 211 = unsigned integer 32;
option architecture-type code 93 = unsigned integer 16;

authoritative;
default-lease-time 3600;
max-lease-time 43200;

subnet 192.168.33.0 netmask 255.255.255.0 {
        range 192.168.33.100 192.168.33.199;
        option subnet-mask 255.255.255.0;
        option broadcast-address 192.168.0.255;

        class "pxeclients" {
                match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
                next-server 192.168.33.10; # pxe server
                filename "pxelinux.0";
        }
}

tftp server のインストール

sudo dnf -y install tftp-server
sudo systemctl enable --now tftp
sudo firewall-cmd --add-service=tftp --permanent
sudo firewall-cmd --reload 

http server のインストール

Kickstart file は /var/www/html/pub/kickstart に配置することとします。

sudo dnf -y install httpd 
sudo systemctl enable --now httpd 
sudo firewall-cmd --add-service=http --permanent 
sudo firewall-cmd --reload 

tftp server および http server に PXE boot file, OSイメージの資材を配置

tftp server のコンテンツは /var/lib/tftpboot/ に、CentOS のメディアは /var/www/html/pub/centos8/ に配置します。
資材は syslinux パッケージ、CentOS8 のメディアから取得します。

sudo dnf -y install syslinux
sudo cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/ 
sudo cp /usr/share/syslinux/{menu.c32,vesamenu.c32,ldlinux.c32,libcom32.c32,libutil.c32} /var/lib/tftpboot/ 
sudo mkdir -p /var/www/html/pub/centos8
sudo mount -t iso9660 -o loop,ro ~/CentOS-8.2.2004-x86_64-dvd1.iso /var/www/html/pub/centos8

PXE boot file は後程 Ansible で作成します。

Kickstart file の配置

Kickstart file の書きかたについては、Red Hat のマニュアルが詳しいです。詳細はここでは割愛します。

Ansible playbook の作成

環境が用意できたので、いよいよ Ansible playbook を書きます。
処理したい内容は以下の通りです:

  1. PXE boot file を MACアドレスごとに生成する
  2. Kickstart file を VMごとに生成する
  3. ESXi にVMを作成し、起動する

inventory

以下のようにVMごとにホスト名とMACアドレス、NWの設定をセットにして、リスト形式で定義します。

inventory/esxi/group_vars/all.yml
---
## createvms (ESXi Server)
esx_hostname: esxi
esx_ipaddr: 192.168.11.50
esx_user: root
esx_password: <<PASSWORD>>
esx_datastore_name: datastore1

## create VMs
vms:
  - hostname: server-a
    notes: server-a
    macaddr: 52:54:00:98:09:69
    disksize: 10
    nic1_network: "2032_ProviApp"
    nic2_network: "VM Network"
    memory: 2048
    cpus: 1
    osid: centos8_64Guest
    network:
      - "--bootproto=dhcp --device=ens192 --ipv6=auto"
      - "--bootproto=static --device=ens224 --ip=192.168.11.20 --netmask=255.255.255.0 --gateway=192.168.11.1 --ipv6=auto --activate"
  - hostname: server-b
    notes: server-b
    macaddr: 52:54:00:98:09:70
    disksize: 10
    nic1_network: "2032_ProviApp"
    nic2_network: "VM Network"
    memory: 2048
    cpus: 1
    osid: centos8_64Guest
    network:
      - "--bootproto=dhcp --device=enp0s3 --ipv6=auto"
      - "--bootproto=static --device=enp0s8 --ip=192.168.11.21 --netmask=255.255.255.0 --gateway=192.168.11.1 --ipv6=auto --activate"

inventory/esxi/group_vars/pxeserver.yml
---
## pxe boot files
pxe_basedir: "/var/lib/tftpboot"
pxe_ks_basedir: "{{ pxe_basedir }}/pxelinux.cfg"
pxe_img_basedir: "{{ pxe_basedir }}/images/CentOS8"
pxe_label: "Kickstart Install CentOS8 x64 with local Repository"
pxe_kernel: "images/CentOS8/vmlinuz"
pxe_initrd: "images/CentOS8/initrd.img"
pxe_server: "192.168.10.1"

## Kickstart files
ks_basedir: "/var/www/html/pub/kickstart"
ks_server: "{{ dhcpd_next_server }}"

PXE boot file を MACアドレスごとに生成する

Ansible playbook は以下のように書きます。

pxeserver.yml
---
- hosts: pxeserver
  become: yes
  gather_facts: no
  tasks:
    - name: create PXE boot files
      template:
        src: pxelinux.cfg.j2
        dest: "{{ pxe_ks_basedir }}/01-{{ item.macaddr | regex_replace(':','-') }}"
      with_items:
        - "{{ vms }}"
pxelinux.cfg.j2
default 1
PROMPT 0
TIMEOUT 30
ONTIMEOUT local

menu title ######## PXE Boot Menu ##########

label 1
  menu label ^1) {{ pxe_label }}
  kernel {{ pxe_kernel }}
  append initrd={{ pxe_initrd }} inst.ks=http://{{ pxe_server }}/pub/kickstart/{{ item.hostname }}.cfg

生成するファイルは「01-{MACアドレス}」という命名規則ですが、「-」区切りなので、インベントリに「:」区切りで定義しても置換するようにしています。

Kickstart file を VMごとに生成する

Ansible playbook は以下のように書きます。(先ほどの pxeserver.yml に続けて書きます)

pxeserver.yml
    - name: create Kickstart directory
      file:
        path: "{{ ks_basedir }}"
        state: directory
        owner: "root"
        group: "root"
        mode: "0755"
        recurse: "yes"
    - name: create Kickstart files
      template:
        src: ks.cfg.j2
        dest: "{{ ks_basedir }}/{{ item.hostname }}.cfg"
      with_items:
        - "{{ vms }}"
ks.cfg.j2
# System authorization information
auth --enableshadow --passalgo=sha512

# Use CDROM installation media
# cdrom
# # Use network installation
url --url=http://{{ ks_server }}/pub/centos8/

# Use text install
text
# Run the Setup Agent on first boot
firstboot --enable
ignoredisk --only-use=sda
# Keyboard layouts
keyboard --vckeymap=jp --xlayouts='jp'
# System language
lang ja_JP.UTF-8

# Network information
{% for network in item.network %}
network {{ network }}
{% endfor %}
network  --hostname={{ item.hostname }}
(以下略)

ESXi にVMを作成し、起動する

vsphere_guest モジュールを使用します。使いかたは公式ドキュメントを参照してください。

createvms.yml
---
- hosts: 127.0.0.1
  connection: local
  user: root
  sudo: false
  gather_facts: false
  serial: 1
  tasks:
    - name: Deploy guest VMs
      vsphere_guest:
        vcenter_hostname: "{{ esx_ipaddr }}"
        validate_certs: no
        username: "{{ esx_user }}"
        password: "{{ esx_password }}"
        guest: "{{ item.hostname }}"
        state: powered_off
        vm_hw_version: vmx-08
        vm_extra_config:
          vcpu.hotadd: yes
          mem.hotadd:  yes
          notes: "{{ item.notes }}"
        vm_disk:
          disk1:
            size_gb: "{{ item.disksize }}"
            type: thin
            datastore: "{{ esx_datastore_name }}"
        vm_nic:
          nic1:
            type: vmxnet3
            network: "{{ item.nic1_network }}"
            network_type: standard
            mac_address: "{{ item.macaddr | regex_replace('-',':') }}"
          nic2:
            type: vmxnet3
            network: "{{ item.nic2_network }}"
            network_type: standard
        vm_hardware:
          memory_mb: "{{ item.memory }}"
          num_cpus: "{{ item.cpus }}"
          osid: "{{ item.osid }}"
          scsi: paravirtual
        esxi:
          datacenter: ha-datacenter
          hostname: "{{ esx_hostname  }}"
      with_items:
        - "{{ vms }}"

PXE boot file と違って、MACアドレスの指定は「:」区切りでないとエラーになりますので、インベントリに「-」区切りで定義しても置換するようにしています。
また、osid については、以下のページを参考にしてください。

Ansible playbook の実行

pxeserver.yml で PXE boot file および Kickstart file を作成し、createvms.yml で ESXi Server にVMを作成し、電源を入れます。

ansible-playbook -i inventory/esxi/inventory.ini pxeserver.yml
ansible-playbook -i inventory/esxi/inventory.ini createvms.yml

うまくいくと、VMが作成され、電源が入った後、OSが自動でインストールされます。

参考

20
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
27