背景#

目前的工作对虚拟化和cloud native技术使用的比较多。搭建新的homelab节点,也希望将这些技术应用到日常的家庭服务器的管理中。

Iac的实践从terraform开始,使用terraform管理proxmox虚拟机,可以提高虚拟机创建和配置的效率,方便后续的维护和扩展。

采用的工具#

网络配置#

我使用的机器是老旧的laptop,只有无线网卡,没有有线网卡。已经解决了wifi连接的问题,参考安装proxmox的wifi问题及解决方法

但是虚拟机的网络配置需要额外处理。

默认情况下,Proxmox VE使用vmbr0作为桥接网络接口,将虚拟机连接到物理网络。然而,在只有无线网卡的情况下,桥接网络可能无法正常工作。为了解决这个问题,我们可以使用NAT(网络地址转换)来为虚拟机提供网络连接。

修改Proxmox的网络配置文件/etc/network/interfaces,添加NAT配置:

auto lo
iface lo inet loopback

auto wlp1s0
iface wlp1s0 inet static
        address 192.168.50.3/24
        gateway 192.168.50.1
        wpa-ssid xxx
        wpa-psk xxx
        # 启用 IP 转发,允许 wlp1s0 路由来自 vmbr0 的流量
        post-up echo 1 > /proc/sys/net/ipv4/ip_forward
        # 设置 NAT 规则:将所有来自 vmbr0 的流量进行地址伪装后,通过 wlp1s0 发送
        post-up   iptables -t nat -A POSTROUTING -s '10.10.10.0/24' -o wlp1s0 -j MASQUERADE
        post-down iptables -t nat -D POSTROUTING -s '10.10.10.0/24' -o wlp1s0 -j MASQUERADE

# **********************************************
# 2. 配置 Bridge 接口 (vmbr0) - 供 VM 使用的私有网络
# **********************************************
auto vmbr0
iface vmbr0 inet static
        # 为 vmbr0 设置一个完全不同的私有 IP 网段 (例如 10.10.10.1/24)
        address 10.10.10.1/24
        # vmbr0 没有物理端口,因为它不直接桥接 Wi-Fi
        bridge-ports none
        bridge-stp off
        bridge-fd 0


source /etc/network/interfaces.d/*

配置完成后,重启网络服务:

systemctl restart networking

这样,虚拟机可以通过NAT访问外部网络,而不依赖于桥接网络。

Terraform#

Terraform安装#

这里使用的是从源码编译的terraform,版本是v1.15.0-dev

apt install golang
git clone https://github.com/hashicorp/terraform
cd terraform
go install
# move terraform binary to where is included in $PATH
mv ~/go/bin/terraform /usr/local/bin/
#  install the autocomplete package.
terraform -install-autocomplete

Proxmox Provider安装#

terraform {
  required_providers {
    proxmox = {
      source  = "bpg/proxmox"
      version = "0.85.1"
    }
  }
}

provider "proxmox" {
  insecure = true // necessary because of self-signed certificates
}

我的terraform跑在远程的服务器上,所以可以通过环境变量传递proxmox的连接信息:

export PROXMOX_VE_ENDPOINT="https://192.168.50.3:8006"
export PROXMOX_VE_USERNAME="root@pam"
export PROXMOX_VE_PASSWORD="your_password"

更好的方式是使用API token进行认证。可以查看官方文档Proxmox Terraform docs了解更多配置选项。

下载image#

在proxmox中创建虚拟机之前,需要先下载操作系统的image。 这里使用的是Ubuntu 24.04 server的cloud image。

image.tf:

resource "proxmox_virtual_environment_download_file" "ubuntu_cloud_image" {
  content_type = "iso"
  datastore_id = "iso-templates"
  node_name    = "pve"
  url          = "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img"
  file_name    = "ubuntu-24.04-noble-cloudimg.img"
}

iso-templates是我在proxmox中创建的一个datastore,用于存放iso和image文件。实际存储在一个NFS存储上。

iso-templates datastore

将image下载单独成一个tf文件,这样可以避免每次创建虚拟机都重新下载image。

创建虚拟机#

main.tf:

#  Create Ubuntu VM
resource "proxmox_virtual_environment_vm" "ubuntu_vm" {
  name      = "ubuntu"
  node_name = "pve"
  machine     = "q35"
  bios      = "ovmf"

  # should be true if qemu agent is not installed / enabled on the VM
  stop_on_destroy = true

  initialization {
    ip_config {
      ipv4 {
        address = "dhcp"
      }
    }
    user_account {
      username = var.vm_user
      password = var.vm_password
    }
  }
  network_device {
    bridge       = "vmbr0"
  }
  cpu {
    cores = var.vm_cores
  }

  memory {
    dedicated = var.vm_memory
  }

  serial_device {}

  efi_disk {
    datastore_id = "local-lvm"
  }

  disk {
    datastore_id = "local-lvm"
    file_id      = proxmox_virtual_environment_download_file.ubuntu_cloud_image.id
    interface    = "virtio0"
    iothread     = true
    discard      = "on"
    size         = 100
  }
}

Makefile#

执行terraform的命令比较多,可以使用Makefile简化操作。(从上一份golang的工作开始,Makefile就成了我的project的标配)

# Init
init: create-tfvars
	terraform init
# Plan: image download
create-tfvars:
	cp terraform.tfvars.example terraform.tfvars
plan-image:
	terraform plan -out=image.plan -target=proxmox_virtual_environment_download_file.ubuntu_cloud_image
# Apply: image download
apply-image: plan-image
	terraform apply "image.plan"
# Plan: VM creation
plan-vm:
	terraform plan -out=vm.plan -target=proxmox_virtual_environment_vm.ubuntu_vm
# Apply: VM creation
apply-vm: plan-vm
	terraform apply "vm.plan"
# Destroy - destroy all resources
destroy:
	terraform destroy
# Clean - remove local terraform files
clean:
	rm -rf .terraform/
	rm -f .terraform.lock.hcl
	rm -f *.tfstate*
	rm -f *.plan

# destry vm only
destroy-vm:
	terraform destroy -target=proxmox_virtual_environment_vm.ubuntu_vm
# destroy image only
destroy-image:
	terraform destroy -target=proxmox_virtual_environment_download_file.ubuntu_cloud_image

执行#

make init
make apply-image
make apply-vm

源码#

source code可以看这里

总结#

使用terraformproxmox创建虚拟机,可以大大简化虚拟机的创建和配置过程,提高效率。通过NAT配置,可以解决无线网卡环境下虚拟机的网络连接问题。未来可以进一步完善多虚拟机的管理和自动化部署,以及terraform state的管理。