[Proposed Specification] Cloud-init service name changes

Status: Review
Proposed upstream release: 24.1
Latest Update: Nov 14, 2023
Implementation: Pull Request

Rational

Cloud-init service names and command line interface is inconsistent and unintuitive. This leads to confusion and wasted effort by users, package maintainers, and developers.

Confusion: Systemd unit name

  • cloud-init.service is ordered before cloud-config.target
  • cloud-config.service is ordered before cloud-init.target
  • when cloud-init.service is complete, cloud-init is not yet complete

This means that an admin might (reasonably) assume that systemctl status cloud-init will inform them whether cloud-init is running or complete. If they make this assumption, they will be misled. These service names is a common point of confusion.

Confusion: Cloud-init commandline

The cloud-init commandline is disjointed and unintuitive. The first stage to run is invoked as cloud-init init --local. If one knows this and attempts to intuit the invocation of other stages, conclusions would be incorrect. The second stage to run is cloud-init init. The remaining two stages use the modules subcommand. Perhaps surprisingly, a third of the configuration modules run in the init stage rather than in the stages invoked by the modules subcommand.

Confusion: Docs

The docs make an attempt to remedy this confusion by calling the second stage the “Network” stage. This vocabulary distinction helps some, but since the implementation is still called the cloud-init.service stage, conversation is muddied as people use synonomous language which is confusing to follow for those without comfort with command names. The “cloud-init” unit calls the “init” subcommand which is also called the “network” stage. Conversation about these stages requires unnecessary cognitive load to map together names that have no reason to be different.

Confusion: Redundant unit

The cloud-config.target target is redundant with cloud-init.service. This unit adds no value, but adds confusion, as mentioned above, due to a partial name collision with cloud-config.service.

 10 # Services that need to start at this point should use the directives           
 11 # "After=cloud-config.target" and "Wants=cloud-config.target" as appropriate.   
 12                                                                                 
 13 # To order services after all cloud-init operations, see cloud-init.target.     
 14        
 15 [Unit]                                                                          
 16 Description=Cloud-config availability                                           
 17 Wants=cloud-init-local.service cloud-init.service                               
 18 After=cloud-init-local.service cloud-init.service

Since cloud-init.service is already ordered:

  7 Wants=cloud-init-local.service                                                                          
    ...                                                              
 10 After=cloud-init-local.service   

Anyone who uses “After=cloud-config.target” and “Wants=cloud-config.target” could just as easily use “After=cloud-init.service” and “Wants=cloud-init.service” (with the updated services as listed above).

Proposal:

Service changes

git mv cloud-init-local.service cloud-local.service
git mv cloud-init.service cloud-network.service
git rm cloud-config.target 

CLI changes

cloud-init init --local          -> cloud-init --stage=local
cloud-init init                  -> cloud-init --stage=network
cloud-init modules --mode=config -> cloud-init --stage=config
cloud-init modules --mode=final  -> cloud-init --stage=final

Unified language

The proposed change would allow services, commands, and documentation to use common language to describe cli invocation, systemd services, and conceptual stages of boot .

Currently state:

+=========+=======================+=================================+
|  Stage  | Service                    | Command                    |
+=========+============================+============================+
| local   | cloud-init-local.service   | cloud-init --local         |
| network | cloud-init.service         | cloud-init                 |
| config  | cloud-config.service       | cloud-init --mode=config   |
| final   | cloud-final.service        | cloud-init --mode=final    |
+---------+----------------------------+----------------------------+

Proposed state:

+=========+=======================+============================+
|  Stage  | Service               | Command                    |
+=========+=======================+============================+
| local   | cloud-local.service   | cloud-init --stage=local   |
| network | cloud-network.service | cloud-init --stage=network |
| config  | cloud-config.service  | cloud-init --stage=config  |
| final   | cloud-final.service   | cloud-init --stage=final   |
+---------+-----------------------+----------------------------+

Downstream Implications

Ubuntu

Ubuntu follows the stable release updates processes to release new versions of cloud-init to existing releases of Ubuntu. However, Ubuntu also expects that existing releases don’t regress current behavior, and would therefore need to patch this change out of pre-existing releases. This patch will increase maintainer burden in the near term, reduce it in the long term.

Cloud-init packaging: In-tree

Distros which use use upstream packaging files automatically get these changes.

Cloud-init packaging: Out-of-tree

Distros which do not keep cloud-init packaging upstream will be forced to update their packaging in the next cycle. If this progresses, I intend to reach out to those communities that I am familiar with to notify them in advance of these required changes.

External Projects

External projects which have dependencies on cloud-init service files should review and update their unit files.

Conclusion

This change is expected to be disruptive in the near term to distro packagers and external project dependencies. However, it is expected to reduce user, maintainer, and developer confusion going forward, if approved.

Review

Please leave your responses below as comment. Your feedback is welcome.

2 Likes

The cloud-config.target target is redundant with cloud-init.service . This unit adds no value, but adds confusion, as mentioned above, due to a partial name collision with cloud-config.service .

All of the cloud-init services are part of cloud-init.target.wants, so in order to enable/disable the services, the generator only touches the target link, rather than all of the relevant services. This could of course be changed too, but the target isn’t currently valueless.

1 Like