LoginSignup
16
6

More than 1 year has passed since last update.

Proxmox VEとTerraformでインターン生に仮想マシンを払い出す話

Last updated at Posted at 2023-03-07

はじめに

インターンシップを素晴らしい企業体験にするためには、課題に対して必要なリソースを素早く学生に提供する必要がありますよね。
すぐにでも課題の開発を始めたいのに、渡したパソコンにVirtualBoxを入れて仮想マシンにOSをインストールしてもらって...なんてことをやってたら、ただでさえ限られた時間がどんどん減ってしまいます。

今回はProxmox VEとcloud-initを組み合わせて必要なリソースのVMを素早く提供する方法について、CLIとTerraformを使った2パターンをご紹介します。
Proxmox VE自体については https://pve.proxmox.com/wiki/Main_Page を参照ください。

用意するもの

  • Proxmox VE 7.2がインストールされたマシン

以降は、Proxmox VEで仮想マシンが起動できる状態になったことを前提に進行します。
この記事では 7.2-14 以降をベースに記載しています。

仮想マシンのテンプレートの準備

まずは、ベースとなる仮想マシンイメージを作成しましょう。
今回は Ubuntu-22.04 のクラウドイメージを使用します。

クラウドイメージの取得

wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img -O ubuntu-22.04-server-cloudimg-amd64.img

ベースとなる仮想マシンの作成とテンプレート化

# Base VM configuration
qm create 9100 --net0 virtio,bridge=vmbr0
qm importdisk 9100 ubuntu-22.04-server-cloudimg-amd64.img local-lvm
qm set 9100 --name ubuntu-22.04a
qm set 9100 --scsihw virtio-scsi-pci --virtio0 local-lvm:vm-9100-disk-0
qm set 9100 --boot order=virtio0
qm set 9100 --ide2 local-lvm:cloudinit
qm set 9100 --nameserver 192.168.0.1 --searchdomain example.com
# Convert VM to VM Template
qm template 9100

ネットワーク設定は、管理者が把握しているという前提で、以下のように設定します。

  • 接続先bridge: vmbr0
  • subnet: 192.168.0.0/24
  • gateway: 192.168.0.1
  • nameserver: 192.168.0.1
  • domain: example.com

ここまでで、ベースのVM TemplateがProxmox VE上に作成されました。

提供の作業フロー

それでは 4 vCPU/8GB Memory/120GB Disk の仮想マシンが要望されたと仮定して、それを提供してみましょう。
作業フローは以下の通りです。

  1. 利用者は以下の情報を管理者に知らせる
    • 必要な仮想マシンのサイズ(今回は 4 vCPU/8GB Memory/120GB Disk)
    • ログイン用のユーザー名(sample01)と公開鍵(sample01-rsakey.pub)
  2. 管理者は受け取った情報から仮想マシンを作る
    • IPアドレスは管理者が把握しているという前提で 192.168.0.11 に設定します。
  3. 管理者は仮想マシン作成後、利用者にアクセス先のIPアドレスを通知する
  4. 完了

仮想マシンの提供(CLIを使うケース)

作成したテンプレートをクローンして、構成を変更して起動します。
IPアドレスやログイン情報をcloud-initで設定できるところが非常に便利です。

qm clone 9100 1001 --name sample01 --full --storage local-lvm
qm set 1001 --cores 4
qm set 1001 --memory 8192
qm resize 1001 virtio0 120G
qm set 1001 --ipconfig0 ip=192.168.0.11/24,gw=192.168.0.1
qm set 1001 --ciuser sample01 --sshkeys sample01-rsakey.pub
qm start 1001

あとは、使用者にIPアドレスを伝えて完了です。
これで必要なリソースを持った仮想マシンを提供できました。

これなら、管理者は使用者のパスワードを知る必要も、ログイン後に初期パスワードの変更を依頼する必要もありませんね。

仮想マシンの提供(Terraformを使うケース)

Proxmox VEではTerraformを使うこともできます。
早速 Proxmox Provider を使ってCLIと同じようなことができるか試してみましょう。

今回は管理者が実行するので、かなり緩めの設定をしていきます。
細かくリソースプールや権限を設定して、管理者以外のユーザーが直接Terraformを使えるようにしても良いでしょう。

APIトークンの取得

root権限をそのまま継承( --privsep 0 )したAPIトークンを作成します。

# pvesh create /access/users/root@pam/token/qiita-sample --privsep 0
┌──────────────┬──────────────────────────────────────┐
│ key          │ value                                │
╞══════════════╪══════════════════════════════════════╡
│ full-tokenid │ root@pam!qiita-sample                │
├──────────────┼──────────────────────────────────────┤
│ info         │ {"privsep":"0"}                      │
├──────────────┼──────────────────────────────────────┤
│ value        │ d2f33ee3-bf19-4155-bd7c-e23a3f14522d │
└──────────────┴──────────────────────────────────────┘

このトークンを使用することで、root権限で好きなだけProxmox VEのAPIを実行できます。

Terraformの記述

使用したTerraformのバージョンです。

$ terraform -version
Terraform v1.3.9
on linux_amd64
+ provider registry.terraform.io/telmate/proxmox v2.9.11

Terraformの記述例です。

variable username {}
variable public_key {}
variable cores {}
variable memory {}
variable disk_size {}
variable ip_address {}

terraform {
  required_providers {
    proxmox = {
      source  = "telmate/proxmox"
      version = "2.9.11"
    }
  }
}

provider "proxmox" {
  pm_api_token_id = "root@pam!qiita-sample"
  pm_api_token_secret = "d2f33ee3-bf19-4155-bd7c-e23a3f14522d"
  pm_api_url = "https://pve-sample:8006/api2/json"
  pm_tls_insecure = true
}

resource "proxmox_vm_qemu" "intern-vm" {
  name = "intern-vm-${var.username}"
  target_node = "pve-c01"
  clone = "ubuntu-22.04a"
  os_type = "cloud-init"
  boot = "order=virtio0"
  cores   = "${var.cores}"
  memory  = "${var.memory}"
  disk {
    storage = "local-lvm"
    type = "virtio"
    size = "${var.disk_size}G"
  }
  network {
    model = "virtio"
    bridge = "vmbr0"
    firewall = false
  }
  ipconfig0 = "ip=${var.ip_address}/24,gw=192.168.0.1"
  ciuser = "${var.username}"
  sshkeys = <<EOF
${var.public_key}
EOF

}

なお最新のTerraform providerは 2.9.13 ですが、API Token周りにバグがある terraform-provider-proxmox/issues/703 ようなので 2.9.11 を使用しています。

作成したいVMの情報を記載した変数ファイルを作成します。

$ cat sample01.tfvars 
username = "sample01"
public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHZYaK+tKWpOVCxhKeTeoKLW/UoAOaj03QXPGrqY2JQm user@sample"
cores = 4
memory = 8192
disk_size = 120
ip_address = "192.168.0.11"

Terraformの実行例

実行例です。

$ terraform apply -var-file sample01.tfvars

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # proxmox_vm_qemu.intern-vm will be created
  + resource "proxmox_vm_qemu" "intern-vm" {
      + additional_wait           = 0
      + agent                     = 0
      + automatic_reboot          = true
      + balloon                   = 0
      + bios                      = "seabios"
      + boot                      = "order=virtio0"
      + bootdisk                  = (known after apply)
      + ciuser                    = "sample01"
      + clone                     = "ubuntu-22.04a"
      + clone_wait                = 0
      + cores                     = 4
      + cpu                       = "host"
      + default_ipv4_address      = (known after apply)
      + define_connection_info    = true
      + force_create              = false
      + full_clone                = true
      + guest_agent_ready_timeout = 100
      + hotplug                   = "network,disk,usb"
      + id                        = (known after apply)
      + ipconfig0                 = "ip=192.168.0.11/24,gw=192.168.0.1"
      + kvm                       = true
      + memory                    = 8192
      + name                      = "intern-vm-sample01"
      + nameserver                = (known after apply)
      + numa                      = false
      + onboot                    = false
      + oncreate                  = true
      + os_type                   = "cloud-init"
      + preprovision              = true
      + reboot_required           = (known after apply)
      + scsihw                    = (known after apply)
      + searchdomain              = (known after apply)
      + sockets                   = 1
      + ssh_host                  = (known after apply)
      + ssh_port                  = (known after apply)
      + sshkeys                   = <<-EOT
            ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHZYaK+tKWpOVCxhKeTeoKLW/UoAOaj03QXPGrqY2JQm user@sample
        EOT
      + tablet                    = true
      + target_node               = "pve-c01"
      + unused_disk               = (known after apply)
      + vcpus                     = 0
      + vlan                      = -1
      + vmid                      = (known after apply)

      + disk {
          + backup             = 0
          + cache              = "none"
          + file               = (known after apply)
          + format             = (known after apply)
          + iops               = 0
          + iops_max           = 0
          + iops_max_length    = 0
          + iops_rd            = 0
          + iops_rd_max        = 0
          + iops_rd_max_length = 0
          + iops_wr            = 0
          + iops_wr_max        = 0
          + iops_wr_max_length = 0
          + iothread           = 0
          + mbps               = 0
          + mbps_rd            = 0
          + mbps_rd_max        = 0
          + mbps_wr            = 0
          + mbps_wr_max        = 0
          + media              = (known after apply)
          + replicate          = 0
          + size               = "120G"
          + slot               = (known after apply)
          + ssd                = 0
          + storage            = "local-lvm"
          + storage_type       = (known after apply)
          + type               = "virtio"
          + volume             = (known after apply)
        }

      + network {
          + bridge    = "vmbr0"
          + firewall  = false
          + link_down = false
          + macaddr   = (known after apply)
          + model     = "virtio"
          + queues    = (known after apply)
          + rate      = (known after apply)
          + tag       = -1
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

proxmox_vm_qemu.intern-vm: Creating...
proxmox_vm_qemu.intern-vm: Still creating... [10s elapsed]
proxmox_vm_qemu.intern-vm: Still creating... [20s elapsed]
proxmox_vm_qemu.intern-vm: Still creating... [30s elapsed]
proxmox_vm_qemu.intern-vm: Still creating... [40s elapsed]
proxmox_vm_qemu.intern-vm: Still creating... [50s elapsed]
proxmox_vm_qemu.intern-vm: Still creating... [1m0s elapsed]
proxmox_vm_qemu.intern-vm: Creation complete after 1m6s [id=pve-c01/qemu/103]

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

もちろん、削除も terraform destroy -var-file sample01.tfvars で簡単です。

おしまい

今回はProxmox VEとcloud-initにTerraformを組み合わせてVMを作る方法を書いてみました。
大抵のことはパブリッククラウドサービスで何とかなるとはいえ、手元の機材を使いたいケースもありますので、上手く使ってみてください。

16
6
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
16
6