canonical / cloud-init

Official upstream for the cloud-init: cloud instance initialization
https://cloud-init.io/
Other
2.89k stars 861 forks source link

[docs]: the page "Configuration sources" does not include environment configuration source #5742

Open eprigorodov opened 5 days ago

eprigorodov commented 5 days ago

Documentation request

The current implementation incloudinit.helpers.ConfigMerger._read_cfg() also loads configuration from file specified in environment variable CLOUD_CFG:

https://github.com/canonical/cloud-init/blob/6725c0f896e0c55176dd0674668b527a3b2cbed9/cloudinit/helpers.py#L253

By the code, this environment configuration has higher priority than anything else but kernel parameters.

That is used in Microsoft Azure cloud data source. By default it creates a single partition on the Azure VM ephemeral disk. It also has higher priority than cloud.cfg.d/ directory, so the only way to override it is supplying configuration via environment. That is also reflected in the Microsoft documentation (options 2 and 3).

FIX: document loading environment configuration in the list "Base configuration".


Reported from: https://cloudinit.readthedocs.io/en/latest/explanation/configuration.html

holmanb commented 5 days ago

Documentation request

The current implementation incloudinit.helpers.ConfigMerger._read_cfg() also loads configuration from file specified in environment variable CLOUD_CFG:

https://github.com/canonical/cloud-init/blob/6725c0f896e0c55176dd0674668b527a3b2cbed9/cloudinit/helpers.py#L253

By the code, this environment configuration has higher priority than anything else but kernel parameters.

Thanks for the report @eprigorodov! This should maybe be documented. However, modifying the systemd environment variables usually shouldn't be required (there are simpler ways to accomplish the same thing), so I'm not sure if we really want to document this.

That is used in Microsoft Azure cloud data source. By default it creates a single partition on the Azure VM ephemeral disk. It also has higher priority than cloud.cfg.d/ directory, so the only way to override it is supplying configuration via environment. That is also reflected in the Microsoft documentation (options 2 and 3).

@cjp256 do you know why the docs recommend setting DefaultEnvironment here? The file location is already in the drop-in directory so I don't understand why using this undocumented option is required (and recommended).

eprigorodov commented 4 days ago

Thank you for the quick response, @holmanb,

The file location is already in the drop-in directory so I don't understand why using this undocumented option is required (and recommended).

I debugged that a bit (still don't have full understanding), this is what I found:

Also, while researching this I lacked a lot a command which dumps effective config and explains where it comes from.

holmanb commented 4 days ago

at some /unknown for me/ moment cloud-init writes that data source into /run/cloud-init/cloud.cfg, so it becames a runtime config,

This happens as a systemd generator. It ends up being a no-op when a single datasource is defined in datasource_list, but when images aren't custom built for a specific cloud this is how cloud-init identifies which cloud it is running on. That allows the same cloud-init package to work everywhere.

* runtime config has higher priority than `/etc/cloud/cloud.cfg.d/`,

* Azure cloud data source plugin brings in some default configuration for ephemeral disk,
  https://github.com/canonical/cloud-init/blob/6725c0f896e0c55176dd0674668b527a3b2cbed9/cloudinit/sources/DataSourceAzure.py#L293-L302

* that goes into `utli.mergemanydict()` before the basic configuration, so it overrides settings from `/etc/cloud/cloud.cfg.d/00-azure-swap.cfg`,

If a default configuration from the source is overriding an on-disk configuration, that sounds like a bug to me. Are you referring to this line? Or a different call to util.mergemanydict()?

eprigorodov commented 4 days ago

nope, the line in Azure data source just returns its default (hard-coded) disk config, (maybe if there is user data containing disk config, then it can be passed via crawled_data["cfg"] and thus become effective, but its just a guess, I didn't read the code that deep)

the actual override happens in helpers.ConfigMerger._read_cfg(), when data source config gets taken before the base config:

https://github.com/canonical/cloud-init/blob/c9dce94d316028b15d9f2781fee959da745aea52/cloudinit/helpers.py#L255-L258