provide networkd as ifupdown replacement on snappy / cloud / server

Registered by Steve Langasek on 2015-05-04

ifupdown is a frequent pain point for cloud integration, due to its lack of apis and its idiosyncratic configuration format. Examine what it would take to replace ifupdown with systemd-networkd for clouds, servers, and ubuntu core by 16.04, since it's reported to be at feature parity for server use cases (i.e. vlans/bridges/bonding, but not vpns/wifi).

Blueprint information

Status:
Started
Approver:
Steve Langasek
Priority:
Medium
Drafter:
Martin Pitt
Direction:
Approved
Assignee:
None
Definition:
Approved
Series goal:
Accepted for wily
Implementation:
Beta Available
Milestone target:
milestone icon ubuntu-15.09
Started by
Martin Pitt on 2015-09-09

Related branches

Sprints

Whiteboard

Requirements for switching to networkd
---------------------------------------------------------
 * networkd is designed and tested upstream with systemd-resolved; for doing the transition in stages we would want to continue resolvconf+dnsmasq for now
 * Support /etc/network/if-up.d/ and related hooks (upstream does not want that right now as it's hard to control and make assumptions about, has to happen downstream)
 * ability to change configuration of an individual interface on a running system (roadmapped upstream) -> not a blocker for cloud, but for classic server and snappy
 * snappy: requires a D-Bus interface for changing config for mediating (no direct file access); that will put configuration overrides into /{etc,run}/systemd/nework (permanent or temporary)

/etc/resolv.conf handling
-----------------------------------
systemd-resolved integrates a mini DNS-server like dnsmasq, picks up the local host name and names of registered containers, and creates a /run/systemd/resolve/resolv.conf; the intention is that /etc/resolv.conf is a symlink to that.

Aside from resolvconf's own /etc/resolvconf/update.d/libc, there are only three packages which ship resolvconf hooks (dnsmasq, pdns, unbound). All of them are in universe and not officially supported (note that NetworkManager and LXC use dnsmasq-base, which is in main; but that doesn't integrate into resolvconf). For scenarios where installation of those is not an option (snappy/Touch) or not supported (cloud?) the most efficient way would be to just enable systemd-resolved and drop resolvconf.

For desktop/upgrades/custom server use cases, we need to add resolvconf compatibility to networkd. We can either create a /etc/resolvconf/update.d/systemd-networkd hook which pulls information out of networkd's D-Bus API or run resolved side by side and make resolvconf merge /run/systemd/resolve/resolv.conf. In both cases we need to trigger a resolvconf update after bringing up an interface as networkd does not use isc-dhcp-client and thus does not call /etc/dhcp/dhclient-enter-hooks.d; see below for running things after an interface is up.

if-*.d/ support
----------------------
We create an udev rule similar to /lib/udev/rules.d/80-networking.rules, like:

  ACTION!="remove", SUBSYSTEM=="net", KERNEL!="lo", ENV{SYSTEMD_WANTS}+="networkd-up@$name.service"
  ACTION="remove", SUBSYSTEM=="net", KERNEL!="lo", RUN+="systemctl stop --no-block networkd-up@$name.service"

networkd-up@.service waits for $name to be configured by networkd (/lib/systemd/systemd-networkd-wait-online -i wlp3s0), runs the if-up.d/ hooks, and terminates again. For stopping it calls the if-post-down.d/ scripts.

This approach avoids a permanently running daemon/service which would only listen to networkd's events through networkd's C library API (such as "interface is up"). We should avoid creating new compiled binaries/helpers for this, but aim to use systemd-networkd-wait-online which already does most (if not all) of what we need for this.

Like NetworkManager, we will *not* support if-pre-up.d and if-down.d/:
  - if-pre-up.d scripts usually have scripts to help ifupdown bring up a particular interface and configure drivers, which is already done by networkd (or NM) itself.
 - if-down.d (which runs *before*) an interface goes down: in a WIFI/mobile/hotplug world this kind of script has never been reliable, as the network can -- and often does -- get unannounced interruptions. This has never been called by NM either (for the same reason), so we don't expect breakage from this. If there is still any, we need to fix software/hooks to gracefully deal with network outages.

if-post-down.d/ will run for a hot-unplugged interface. Note that this does *not* catch manually bringing down an interface (without physically removing it)! Unlike on a desktop with nm-applet this should be less of a concern in a server world, but for catching those we would need to subscribe to down events from networkd for these. This is fairly expensive, and rarely used either.

MAAS/cloud-init
------------------------
These projects (perhaps also snappy) generate ifupdown configuration based on some more abstract YAML. These should start to emit corresponding netword configuration; then MAAS or other image/system builders can decide whether to install ifupdown or enable networkd in the target. For these cases when the network config is abstracted in YAML or similar, ifupdown vs. networkd should be a mere implementation detail.

Roadmap
--------------
Provide networkd as opt-in with the above integration for 15.10. Review the state and whether it has significant benefits at 15.10 and re-discuss for 16.04 LTS.

(?)

Work Items

Work items:
Teach Networkmanager to not auto-connect to ethernet interfaces configured by networkd: TODO
[pitti] verify that udev rules get triggered for virtual interfaces (to avoid a permanent daemon listening to events): DONE
[pitti] fix systemd-networkd-wait-online -i to be suitable for the hook support: DONE
[pitti] create basic autopkgtest for networkd: DONE
[pitti] create udev rules and helper services to run if-*.d/ hooks for networkd interfaces: DONE
[pitti] update resolvconf with DNS servers from networkd interfaces: DONE
add networkd configuration emission to MAAS: TODO
add networkd configuration emission to cloud-init: TODO
[pitti] add README.Debian documentation how to switch to networkd (with necessary commands and pointers to details): DONE