2
votes

I am deploying Ubuntu 18.04 VMs on VMware vSphere using Terraform, and I need to apply some basic configurations so I'm using cloud-init.

Most of the things are working correctly (setting the hostname, adding users, running commands) but I'm totally failing to configure a static IP address to network interfaces.

I am using Ubuntu's stock cloud images deployed from their .ova files and immediately converted to templates without ever powering them on. I can see my data gets correctly rendered to a multi-part file in /var/lib/cloud/instance/user-data.txt.i, but then the network configuration does not get applied.

I cannot understand what I'm doing wrong, I don't even know if the problem lies in the data location (multipart file name and content-type) or in its contents. Any help would be appreciated.

This is my cloud-init related code in Terraform:

data "template_file" "cloud-config" {
  template = <<YAML
#cloud-config
hostname: ${var.vm_hostname}
# Adds a user called 'example' with the password hash of 'passwort', sudo rights and the default ubuntu groups
users:
  - name: example
    passwd: $6$rounds=4096$P0uvlB9.8nsiY67$uuOxYSk6n/74Ds3JtV1mT6xYjOguwTWgNmOeHvcHiQa9zan57l8dvfHE/zlu19fDmJGySNzLmh6K0R2I1AU9o0
    lock_passwd: false 
    sudo: ALL=(ALL) ALL
    groups: [adm, audio, cdrom, dialout, floppy, video, plugdev, dip, netdev]
runcmd:
  - echo 'This instance was provisioned by Terraform.' >> /etc/motd
  - sed -i s/^PasswordAuthentication\ no\$/PasswordAuthentication\ yes/ /etc/ssh/sshd_config
power_state:
  mode: 'reboot'
  message: 'reboot triggered by cloud-init'
YAML
}

# network-config
data "template_file" "network-config-v2" {
  template = <<YAML
version: 2
ethernets:
  ens192:
    addresses: [${var.vm_ip4address}/${var.vm_ip4subnet}]
    gateway4: ${var.vm_ip4gateway}
YAML
}

data template_cloudinit_config "config" {
  gzip          = true
  base64_encode = true
  part {
    filename     = "init.cfg"
    content_type = "text/cloud-config"
    content      = "${data.template_file.cloud-config.rendered}"
  }
  part {
    filename     = "network-config"
    # also tried text/plain here
    content_type = "text/cloud-config"
    content      = "${data.template_file.network-config-v2.rendered}"
  }
}

resource "vsphere_virtual_machine" "vm" {
  # some details omitted for brevity
  network_interface {
    network_id = "${data.vsphere_network.network.id}"
    adapter_type = "${data.vsphere_virtual_machine.template.network_interface_types[0]}"
  }
  wait_for_guest_net_routable = false
  vapp {
    properties {
      user-data = "${data.template_cloudinit_config.config.rendered}"
    }
  }
}

These are the only relevant cloud-init.log lines I could find, which just say it is falling back to default dhcp configuration:

2019-04-26 13:04:14,373 - __init__.py[DEBUG]: no work necessary for renaming of [['00:50:56:86:ca:38', 'ens192', 'vmxnet3', '0x07b0']]
2019-04-26 13:04:14,375 - stages.py[INFO]: Applying network configuration from fallback bringup=False: {'config': [{'type': 'physical', 'name': 'ens192', 'mac_address': '00:50:56:86:ca:38', 'subnets': [{'type': 'dhcp'}]}], 'version': 1}
2019-04-26 13:04:14,397 - __init__.py[DEBUG]: Selected renderer 'netplan' from priority list: None
2019-04-26 13:04:14,405 - util.py[DEBUG]: Writing to /etc/netplan/50-cloud-init.yaml - wb: [644] 477 bytes

For what it's worth, I also tried using network config format 1 without any luck.

1

1 Answers

1
votes

Alright so i had the same problem today, and i want to share the solution here.

The problem is that the user-data, that you are using via vsphere for the ubuntu cloud image cant change the network stuff! So you need to do things manually.

This was already spotted here, and dalo presented a nice, smart answer that really helped me out, and should fix your problem too: https://communities.vmware.com/message/2872244#2872244

So basically you override the default network config by cloud-init with your own and activate it afterwards. But be aware that the vm is getting a ip via dhcp on first boot,. After your netplan apply command was executed the vm gets the static ip and that persists across restarts.