Setting static ip using cloud init does not work here

Every time I find myself touching this issue, I always find myself spending hours never getting this to work. Which is odd to me as I have less trouble with cloud-init on other systems, it mostly just work OOTB.

Today, I had to quickly write up a bash script and test it. Then I attempted to launch a container using these parameters:

lxc launch local:centos7 centos7-dev --profile default < /tmp/config.yml

The fingerprint of image is: 0d0f0af9dc3f

Here is a copy of config.yml

config:
  user.network-config: |
    version: 1
    config:
      - type: physical
        name: eth0
        subnets:
          - type: static
            ipv4: true
            address: 192.168.103.13
            netmask: 255.255.255.0
            gateway: 192.168.103.1
            control: auto
      - type: nameserver
        address: 192.168.99.1

A copy of the container config:

architecture: x86_64
config:
  image.architecture: amd64
  image.description: Centos 7 amd64 (20210313_07:08)
  image.os: Centos
  image.release: "7"
  image.serial: "20210313_07:08"
  image.type: squashfs
  image.variant: cloud
  user.network-config: |
    version: 1
    config:
      - type: physical
        name: eth0
        subnets:
          - type: static
            ipv4: true
            address: 192.168.103.13
            netmask: 255.255.255.0
            gateway: 192.168.103.1
            control: auto
      - type: nameserver
        address: 192.168.99.1
  volatile.base_image: 0d0f0af9dc3f4d8fce76797c9d592789bba511e8365bcd0aa3796d50c5d7d55d
  volatile.eth0.host_name: veth2bf3443c
  volatile.eth0.hwaddr: 00:16:3e:95:59:0b
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.last_state.power: RUNNING
  volatile.uuid: 741d93ea-ac56-413f-a463-f9e99add5552
devices: {}
ephemeral: false
profiles:
- default
stateful: false
description: ""

Instead of the container being assigned the static IP I’ve set above, get it’s IP from DHCP, obviously not the behavior I was expecting. Doing everything I’m suppose to do in Custom Network Configuration with cloud-init. There is no /var/lib/cloud/seed/nocloud-net/network-config?

Full cloud-init log here: https://l.lhputils.info/GROUJ

Additionally, upon reviewing the logs, disturbingly openssh server isn’t installed by default on CentOS 7 cloud image which now requires me to add additional configuration options to cloud-init.

Is this suppose to be a simple process, am I misunderstanding the methodology here?

Host OS: OpenSUSE Tumbleweed
LXD Snap: server_version: "4.12"

I’ve made changes to default profile:

config:
  user.user-data: |
    user.user-data : |
    #cloud-config
    packages:
      - openssh-server
    users:
      - name: root
        passwd: $6$H.d4Kr1rXRr.CK4X$dK3Blpq9H2wY0gbI2qRzX5kheaz3C0C1zI2Fx.umTRX/G57ugVF5WXiLyw5ZC6vNYhrUYn49W.taHHB4HeRHe1
description: Default LXD profile
devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: virbr1
    type: nic
  root:
    path: /
    pool: storage
    type: disk
name: default
used_by:
- /1.0/instances/debian9-dev
- /1.0/instances/ubuntu1804-dev
- /1.0/instances/oracle7-dev
- /1.0/instances/alpine39-dev
- /1.0/instances/rainloop-stag
- /1.0/instances/archlinux-dev
- /1.0/instances/opensuse15-dev
- /1.0/instances/alpineedge-dev
- /1.0/instances/webserver-dev
- /1.0/instances/debian8-dev
- /1.0/instances/centos8-dev
- /1.0/instances/mailserver-dev
- /1.0/instances/archlinux-buildct
- /1.0/instances/ubuntu2010-dev
- /1.0/instances/centos7-devvm
- /1.0/instances/centos7-dev

And it looks like it did apply?

cat /var/lib/cloud/instances/centos7-dev/user-data.txt
user.user-data : |
#cloud-config
packages:
  - openssh-server
users:
  - name: root
    passwd: $6$H.d4Kr1rXRr.CK4X$dK3Blpq9H2wY0gbI2qRzX5kheaz3C0C1zI2Fx.umTRX/G57ugVF5WXiLyw5ZC6vNYhrUYn49W.taHHB4HeRHe1

1. openssh-server package did not get installed
2. root user password did not change?

I’m still baffled.

Actually a syntax error, fixing that now.

UPDATE: This is fixed, unfortunately network configuration still doesn’t work here, should it be in user-data?

I would take a look at these options:
https://linuxcontainers.org/lxd/docs/master/networks#network-bridge

I appreciate you offering alternative approach @toby63 , unfortunately I am already using a Linux Bridge that is tied to VLAN, that is then tied to my local network. The specific VLAN does offer DHCP leases, which I typically use for VMs. With that said, I have to postpone this for a bit, what I suspect might work is this:

config:
  user.network_mode: link-local
  user.user-data: |
    #cloud-config
    packages:
      - openssh-server
    users:
      - name: root
        passwd: $6$H.d4Kr1rXRr.CK4X$dK3Blpq9H2wY0gbI2qRzX5kheaz3C0C1zI2Fx.umTRX/G57ugVF5WXiLyw5ZC6vNYhrUYn49W.taHHB4HeRHe1
    runcmd:
      - [ systemctl, daemon-reload ]
      - [ systemctl, enable, sshd.service ]
      - [ systemctl, start, --no-block, sshd.service ]
      - [ ip, a, a, 192.168.103.13/24, dev, eth0 ]
      - [ ip, r, a, default, via, 192.168.103.1, dev, eth0 ]
    write_files:
      - content: nameserver 192.168.99.1
        path: /etc/resolv.conf

Which image did you use when creating the instance (not all of them have cloud-init installed)?

Hi @tomp, the image I pulled was images:centos/7/cloud that came pre-installed with cloud-init.

I’d like to make a minor adjustment to my previous config by adding [ ip, addr, flush, eth0 ] as cloud-init defaults to dhcp:

config:
  boot.autostart: false
  user.network_mode: link-local
  user.user-data: |
    #cloud-config
    packages:
      - openssh-server
    users:
      - name: root
        passwd: $6$H.d4Kr1rXRr.CK4X$dK3Blpq9H2wY0gbI2qRzX5kheaz3C0C1zI2Fx.umTRX/G57ugVF5WXiLyw5ZC6vNYhrUYn49W.taHHB4HeRHe1
    runcmd:
      - [ systemctl, daemon-reload ]
      - [ systemctl, enable, sshd.service ]
      - [ systemctl, start, --no-block, sshd.service ]
      - [ systemctl, stop, network ]
      - [ ip, l, s, eth0, up ]
      - [ ip, addr, flush, eth0 ]
      - [ ip, a, a, 192.168.103.13/24, dev, eth0 ]
      - [ ip, r, a, default, via, 192.168.103.1, dev, eth0 ]
    write_files:
      - content: nameserver 192.168.99.1
        path: /etc/resolv.conf

This accomplishes what I need. Back to @tomp, by default regarding centos 7 cloud images, user.network-config simply doesn’t work. Looking at the docs here

Templates provided with images at cloud-images.ubuntu.com have the following in their metadata.yaml

/var/lib/cloud/seed/nocloud-net/network-config:
  when:
    - create
    - copy
  template: cloud-init-network.tpl

Maybe the missing metadata.yaml is the problem? Which draws me to the conclusion by looking at the log https://l.lhputils.info/GROUJ, the same one in OP, network-config doesn’t get rendered:

Reading from /var/lib/cloud/seed/nocloud-net/network-config (quiet=False)

@monstermunchkin are you able to take a look at this, looks like network config via cloud init doesn’t work in CentOS 7 image. Thanks

May be as simple as that cloud-init version not supporting network configuration. Or more specifically not supporting it as the current network yaml.

@stgraber That might seem reasonable although would that prevent LXD from seeding user.network-config to the container? Because AFAICT, cloud-init still looks for network-config ?

This shows that only CentOS 8 has the network-config enabled, presumably because the cloud-init version in CentOS 7 didn’t support it.

That’s what I believe as well. However, CentOS 7 is now running cloud-init v19.4 which supports network config. I’ll update the yaml file.

Sounds good, I’ll approve the PR then :slight_smile:

@monstermunchkin @stgraber Updating the thread as I’ve recently caught that the fix(es) have been merged: https://github.com/lxc/lxc-ci/pull/259. I assuming the change is to the image itself? And I would have to wait a day or two to test the fix(es) am I right? It isn’t easy to tell when merges get to distribution.

Yes, the change was to the image itself which should be available tomorrow.

While the changes are pending, I like to leave a notation, if anyone lands on this thread and uses my workaround, they are not persistence and only get executed once-per-instance.