dmacvicar / terraform-provider-libvirt

Terraform provider to provision infrastructure with Linux's KVM using libvirt
Apache License 2.0
1.54k stars 457 forks source link

Cloud-Init is ignored when using MicroOS #855

Closed lostiniceland closed 3 years ago

lostiniceland commented 3 years ago

System Information

Linux distribution

openSUSE 15.3

Terraform version

Terraform v0.15.5

Provider and libvirt versions

0.6.3 for OpenSuse 15.2 (even though I am on 15.3)


Description of Issue/Question

Cloud-Init is ignored when using MicroOS as the the guest-os. The machine is provisioned but no configuration from cloud-init is applied.

According to the MicroOS/Kubic docs for cloud-init, a mounted filesystem should be picked up

To setup the network to access configuration files on the network local configuration files can be used. NoCloud will search on all devices, which do not contain a partition table and contain a vfat or iso9660 filesystem. The filesystem volume label must be cidata. So this could be a ISO-image, USB-Stick or an unpartitioned harddisk.

I checked the libvirt-provider source, and as far as I can tell it looks correct.

However, using the libvirt-provider with an Ubuntu image works as expected. For instance when following this article. So there must be a difference in how cloud-init is recognized. It seems to me that the cloud-init files must reside in the root of the filesystem, which I could not verify. Maybe one of the prerequisites mentioned above are not met (vfat or iso9660, not partition-table, etc).

Setup

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

variable "libvirt_disk_path" {
  description = "path for libvirt pool"
  default     = "/opt/kvm/pool1"
}

variable "micro_os_img_url" {
  description = "micro os image"
  default     = "https://download.opensuse.org/tumbleweed/appliances/openSUSE-MicroOS.x86_64-kvm-and-xen.qcow2"
}

variable "vm_hostname" {
  description = "vm hostname"
  default     = "kubic"
}

variable "ssh_username" {
  description = "the ssh user to use"
  default     = "kubic"
}

variable "ssh_private_key" {
  description = "the private key to use"
  default     = "~/.ssh/vnet_rsa"
} 

resource "libvirt_pool" "kubic" {
  name = "kubic"
  type = "dir"
  path = var.libvirt_disk_path
}

resource "libvirt_volume" "kubic-qcow2" {
  name = "kubic-qcow2"
  pool = libvirt_pool.kubic.name
  source = var.micro_os_img_url
  format = "qcow2"
}

data "template_file" "meta_data" {
  template = file("${path.module}/config/meta_init.yml")
}

data "template_file" "user_data" {
  template = file("${path.module}/config/cloud_init.yml")
}

data "template_file" "network_config" {
  template = file("${path.module}/config/network_config.yml")
}

data "template_file" "ignition_config" {
  template = file("${path.module}/config/config.ign")
}

resource "libvirt_ignition" "ignition" {
  name    = "config.ign"
  pool    = libvirt_pool.kubic.name
  content = data.template_file.ignition_config.rendered
}

resource "libvirt_cloudinit_disk" "commoninit" {
  name           = "commoninit.iso"
  meta_data      = data.template_file.meta_data.rendered
  user_data      = data.template_file.user_data.rendered // empty
  network_config = data.template_file.network_config.rendered // not relevant
  pool           = libvirt_pool.kubic.name
}

resource "libvirt_domain" "domain-kubic" {
  name   = var.vm_hostname
  memory = "512"
  vcpu   = 1

//  coreos_ignition = libvirt_ignition.ignition.id
  cloudinit = libvirt_cloudinit_disk.commoninit.id

  network_interface {
    network_name   = "default"
    wait_for_lease = true
    hostname       = var.vm_hostname
  }

  console {
    type        = "pty"
    target_port = "0"
    target_type = "serial"
  }

  console {
    type        = "pty"
    target_type = "virtio"
    target_port = "1"
  }

  disk {
    volume_id = libvirt_volume.kubic-qcow2.id
  }

  graphics {
    type        = "spice"
    listen_type = "address"
    autoport    = true
  }

  provisioner "remote-exec" {
    inline = [
      "transactional-update pkg install docker"
    ]

    connection {
      type                = "ssh"
      user                = "root" //var.ssh_username
      host                = libvirt_domain.domain-kubic.network_interface[0].addresses[0]
      private_key         = file(var.ssh_private_key)
      timeout             = "2m"
    }
  }
} 

Cloud-Init

#cloud-config
# vim: syntax=yaml
debug: True
disable_root: False
chpasswd:
  list: |
    root:password
  expire: False
ssh_pwauth: True
ssh_deletekeys: False
ssh_authorized_keys:
  - ssh-rsa AAAAB3Nza...
hostname: kubic
fqdn: kubic.vnet.de
timezone: Europe/Berlin
ntp:
  servers:
    - 0.de.pool.ntp.org
    - 1.de.pool.ntp.org
    - 2.de.pool.ntp.org
runcmd:
  - /usr/bin/localectl set-keymap de-latin1-nodeadkeys
  - /usr/bin/systemctl enable --now ntpd

Steps to Reproduce Issue

  1. Run terraform apply with above configuration.
  2. Try to login on the machines console with root and password (which is enabled via cloud-init)

Additional information:

It seems that cloud-init configuration is different based on the distribution. For Micro-OS the docs are here.

anthr76 commented 3 years ago

As far as I'm aware cloud-init is only support on Openstack's flavor of Kubic/MicroOS

Examples can be found here using ignition

lostiniceland commented 3 years ago

You are right: using an OpenStack build works. I just changed the downloaded image url and cloud-init is triggered and I can login with the configured root user. Maybe I will try ignition as well, though I hate JSON configs :-)

Anyways, sorry for opening an issue which was on my side.