Using model-config key: cloudinit-userdata

Introduction

Note: This is a sharp knife feature - be careful with it. It was added to Juju in version 2.3.1.

Cloudinit-userdata

Allows the user to provide additional cloudinit data to be included in the cloudinit data created by Juju.

Specifying a key will overwrite what juju puts in the cloudinit file with the following caveats:

  1. users and bootcmd keys will cause an error
  2. The packages key will be appended to the packages listed by juju
  3. The runcmds key will cause an error. You can specify preruncmd and postruncmd keys to prepend and append the runcmd created by Juju.

Use cases

  • setting a default locale for deployments that wish to use their own locale settings
  • adding custom CA certificates for models that are sitting behind an HTTPS proxy
  • adding a private apt mirror to enable private packages to be installed
  • blacklist SSH fingerprints from being printed to the console for security-focused deployments

Background

Juju uses cloud-init to customise instances once they have been provisioned by the cloud. The cloudinit-userdata model configuration setting (model config) allows you to tweak what happens to machines when they are created up via the “user data” feature.

From the website:

cinit-logo

Cloud images are operating system templates and every instance starts out as an identical clone of every other instance. It is the user data that gives every cloud instance its personality and cloud-init is the tool that applies user data to your instances automatically.

Using

Providing custom user data to cloudinit

Create a file, cloudinit-userdata.yaml, which starts with the cloudinit-userdata key and data you wish to include in the cloudinit file. Note: juju reads the value as a string, though formatted as YAML.

Template cloudinit-userdata.yaml:

cloudinit-userdata: |
    <key>: <value>
    <key>: <value>

Provide the path your file to the model-config command:

juju model-config cloudinit-userdata.yaml

Reading the current setting

To read the current value, provide the cloudinit-userdata key to the model-config command as a command-line parameter. Adding the --format yaml option ensures that it is properly formatted.

juju model-config cloudinit-userdata --format yaml

Sample output:

cloudinit-userdata: |
  packages:
    - 'python-keystoneclient'
    - 'python-glanceclient'

Clearing the current custom user data

Use the --reset option to the model-config command to clear anything that has been previously set.

juju model-config --reset cloudinit-userdata

Known Issues

Further reading

Model configuration settings are documented as part of Juju’s official docs:

To read more about how various levels of settings inter-operate in the Juju model, read this post in Discourse:

4 Likes

@pmatulis One of the field engineers noted that cloudinit-userdata was lacking in documentation examples today.

His particular case was passing in YAML to the key/value style usage in the CLI, which he could not do successfully.

why don’t we file that as a docs issue @manadart please? https://github.com/juju/docs/issues/new

I’ve done so: https://github.com/juju/docs/issues/3354

Is this model-config feature useful in manual-provider environments where I’m doing juju add-machine ? Or is this only passed to the cloud providers during deployment of new machines via juju deploy/add-unit?

No in general, because juju doesn’t create and configure the machines with a manual-provider. If you’re doing an add-machine of a container on a manually provisioned machine, it’d be used.

It’s used any time juju creates a machine in a model where the config option is defined. The feature is not specific to a cloud, though will only work on ubuntu units.

@hmlanigan I’ve updated some of the text. Could you please take a look and check that I haven’t misunderstood anything?

Looks great @timClicks. Thank you!

I have been hammering at this for some time and this is a working config that also allows you to have a proxy in there and deploy mixed centos/ubuntu:

modelconfig.yaml

cloudinit-userdata: |
  yum_repos:
    epel-release:
      baseurl: http://download.fedoraproject.org/pub/epel/7/$basearch
      enabled: true
      failovermethod: priority
      gpgcheck: true
      gpgkey: http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7
      name: Extra Packages for Enterprise Linux 7 - Release
  preruncmd:
    - yum --setopt=proxy=http://some.proxy.com:8080 -y install epel-release redhat-lsb-core sudo openssh-server python36-virtualenv python36-PyYAML python3 snapd
    - echo "proxy=http://some.proxy.com:8080" >> /etc/yum.conf
  postruncmd:
    - usermod -p '*' ubuntu
    - 'systemctl start sshd'
    - 'systemctl enable snapd'

http-proxy: http://some.proxy.com:8080
https-proxy: http://some.proxy.com:8080
snap-http-proxy: http://some.proxy.com:8080
snap-https-proxy: http://some.proxy.com:8080

This is all from a massive discussion here Charms for centos - lets begin around getting centos to work with juju (which is a horrible situation at the moment):

If you are confused about why yum is called with the --setopt like this instead of just adding in packages, that is because the preruncmd in this case will need to get packages which will be available only after the “epel-release” package is installed (which needs the proxy). The proxy settings are added only AFTER the packages have failed to install at which point its all to late.

In your example:

to provide custom user data to cloudinit
juju model-config cloudinit-userdata.yaml

the cloudinit-userdata: must be followed by a |

1 Like