0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Terraform Libvirt Provider で Q35 タイプの KVM を作成する

Last updated at Posted at 2025-01-21

前置き

Terraform libvirt provider で Q35 type の KVM を作ろうとすると、エラーになる場合がある。同 provider は、Q35 machine type の指定そのものはサポートしている が、CD-ROM をマウントするようなコードが共存する場合、失敗する。原因は、同 provider が CD-ROM に自動的に IDE bus を割り当てるためである。この形式はレガシーであり、Q35 machine にマウントできない。したがって、次のような典型的なユースケースにおいて、VM 作成時にエラーが発生してしまう:

  • インストール用の Bootable デバイスを 仮想 CD-ROM としてマウントするケース
  • cloudinit でインストールするケース (ISO イメージのマウントが発生)

この問題については Issue #1018 が報告されているが、2025年1月現在まで修正されておらず、現状は XSLT パッチ を用いて IDE bus を SATA bus に編集する対処が勧められている。

本記事では、Terraform Libvirt Provider で Q35 マシンを作成するための XSLT パッチの当て方を紹介する。

準備

Terraform 実行ホストに次のソフトウェアをインストールする(Terraform Libvirt Provider が XSLT を解釈する際に必要となる)。

Ubuntu 系の場合:

$ sudo apt install xsltproc

RHEL 系の場合:

$ sudo dnf install libxslt

テスト用 OS image として、Rocky Linux の qcow2 image をダウンロードしておく:

$ sudo curl -o /var/lib/libvirt/images/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2 -LO https://download.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2

プロビジョニングファイルの作成

XSLT パッチの用意

次の pathc.xsl を用意する:

patch.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <!-- Identity transform to copy everything as is -->
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <!-- Use SATA CD-ROM for Linux setup -->
  <xsl:template match="target[@bus='ide']">
    <xsl:copy>
      <xsl:apply-templates select="@*[name()!='bus']"/>
      <xsl:attribute name="bus">sata</xsl:attribute>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

<!-- Use SATA CD-ROM for Linux setup --> のブロック内で、IDE bus の指定を SATA bus に修正する処理を行っている:

  1. <target> 要素にマッチする要素を探す
  2. 属性名が bus 以外の場合、元の属性値をそのままコピーする
  3. 属性名が bus の場合、属性値を sata に変更する。

それ以外の部分は、基本的な宣言や、もとの domain xml の内容をそのままコピーする処理が書かれている、いわゆる「おまじない部分」である。

Terraform file の作成

VM 構築テスト用に、次の main.tf を作成する。

main.tf
terraform {
  required_providers {
    libvirt = {
      source  = "dmacvicar/libvirt"
      version = "0.8.1"
    }
  }
}

provider "libvirt" {
  uri = "qemu:///system"
}

resource "libvirt_cloudinit_disk" "commoninit" {
  name      = "commoninit_q35-test.iso"
  user_data = templatefile("cloud_init.cfg", {})
  pool      = "default"
}

resource "libvirt_domain" "vm" {
  name    = "q35-test"
  vcpu    = 2
  memory  = 8000
  machine = "q35"

  disk {
    volume_id = libvirt_volume.volume.id
    scsi      = true
  }

  cloudinit = libvirt_cloudinit_disk.commoninit.id
  autostart = true

  network_interface {
    network_name = "default"
    addresses    = ["192.168.122.100"]
  }

  cpu {
    mode = "host-passthrough"
  }

  graphics {
    type        = "vnc"
    listen_type = "address"
  }

  # Makes the tty0 available via `virsh console`
  console {
    type        = "pty"
    target_port = "0"
    target_type = "serial"
  }

  xml {
    xslt = file("${path.module}/patch.xsl")
  }
}

# Download from https://download.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2
resource "libvirt_volume" "volume" {
  name           = "q35-test.qcow2"
  pool           = "default"
  format         = "qcow2"
  base_volume_id = "/var/lib/libvirt/images/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2"
  size           = 100 * 1024 * 1024 * 1024
}

ポイントは libvirt_domain リソース内の次の2箇所:

  • machineq35 を指定する
  • xml ブロックで xslt パッチを渡す

TIPS: 利用可能な qemu machine type の一覧は /usr/libexec/qemu-kvm -machine help コマンド (RHEL 系以外の OS では /usr/bin/qemu-system-x86_64 -machine help コマンド) で確認することができる:

# /usr/libexec/qemu-kvm -machine help
Supported machines are:
pc                   RHEL 7.6.0 PC (i440FX + PIIX, 1996) (alias of pc-i440fx-rhel7.6.0)
pc-i440fx-rhel7.6.0  RHEL 7.6.0 PC (i440FX + PIIX, 1996) (default) (deprecated)
q35                  RHEL-9.4.0 PC (Q35 + ICH9, 2009) (alias of pc-q35-rhel9.4.0)
pc-q35-rhel9.4.0     RHEL-9.4.0 PC (Q35 + ICH9, 2009)
pc-q35-rhel9.2.0     RHEL-9.2.0 PC (Q35 + ICH9, 2009)
pc-q35-rhel9.0.0     RHEL-9.0.0 PC (Q35 + ICH9, 2009)
pc-q35-rhel8.6.0     RHEL-8.6.0 PC (Q35 + ICH9, 2009) (deprecated)
pc-q35-rhel8.5.0     RHEL-8.5.0 PC (Q35 + ICH9, 2009) (deprecated)
pc-q35-rhel8.4.0     RHEL-8.4.0 PC (Q35 + ICH9, 2009) (deprecated)
pc-q35-rhel8.3.0     RHEL-8.3.0 PC (Q35 + ICH9, 2009) (deprecated)
pc-q35-rhel8.2.0     RHEL-8.2.0 PC (Q35 + ICH9, 2009) (deprecated)
pc-q35-rhel8.1.0     RHEL-8.1.0 PC (Q35 + ICH9, 2009) (deprecated)
pc-q35-rhel8.0.0     RHEL-8.0.0 PC (Q35 + ICH9, 2009) (deprecated)
pc-q35-rhel7.6.0     RHEL-7.6.0 PC (Q35 + ICH9, 2009) (deprecated)

なお、Terraform libvirt provider は、デフォルトで pc-i440fx machine type の VM を作成する。このタイプはレガシーであり、例えば PCIe device の passthrough といったモダンな機能をサポートしていない。

cloudinit 設定ファイル cloud_init.cfg を作成する:

cloud_init.cfg
#cloud-config
users:
  - name: root
    ssh-authorized-keys:
      - "<SSH_KEY>"

VM の作成

次のコマンドを実行し、VM を作成する。

$ terraform init
$ terraform apply
...
libvirt_cloudinit_disk.commoninit: Creating...
libvirt_volume.volume: Creating...
libvirt_volume.volume: Creation complete after 0s [id=/var/lib/libvirt/images/q35-test.qcow2]
libvirt_cloudinit_disk.commoninit: Creation complete after 0s [id=/var/lib/libvirt/images/commoninit_q35-test.iso;0a9b23c1-c711-469f-968b-e8adc566ea79]
libvirt_domain.vm: Creating...
libvirt_domain.vm: Creation complete after 1s [id=81cf19ea-54cb-4544-aaae-fbc8222fde98]

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

cloudinit を用いながらも、q35 type によるマシン作成が成功した。

VM の作成 (失敗例)

成功例だけ見ても、ああそう、という感じなので、前置きで述べた失敗例も示す。main.tf XSLT patch の部分だけコメントアウトしてみる:

main.tf
...
  #xml {
  #  xslt = file("${path.module}/patch.xsl")
  #}
...

再度 VM の作成を試みると、今度はエラーになる:

$ terraform destroy   # 先程の VM を削除
$ terraform apply
...
libvirt_cloudinit_disk.commoninit: Creating...
libvirt_volume.volume: Creating...
libvirt_volume.volume: Creation complete after 0s [id=/var/lib/libvirt/images/q35-test.qcow2]
libvirt_cloudinit_disk.commoninit: Creation complete after 0s [id=/var/lib/libvirt/images/commoninit_q35-test.iso;548e73d8-1fb5-4141-9a0e-efd49d8e078f]
libvirt_domain.vm: Creating...
╷
│ Error: error defining libvirt domain: unsupported configuration: IDE controllers are unsupported for this QEMU binary or machine type
│ 
│   with libvirt_domain.vm,
│   on main.tf line 20, in resource "libvirt_domain" "vm":
│   20: resource "libvirt_domain" "vm" {
│ 
╵

Q35 type がサポートしない IDE bus が使われたことでエラーになっている。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?