Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
systemd: Add explicit Before=ceph.target #15835
Conversation
tserong
referenced this pull request
in SUSE/ceph
Jun 22, 2017
Closed
[DNM] systemd: Add explicit After= for ceph.target #129
smithfarm
added
the
build/ops
label
Jun 22, 2017
tserong
changed the title from
systemd: flatten target hierarchy
to
[DNM] systemd: flatten target hierarchy
Jun 23, 2017
|
We're only using tracker.ceph.com URLs for Fixes: lines -- at Red Hat we usually end up with tracker tickets that mirror-ish buzilla tickets, and reference the tracker one from the commit. (I came via twitter for the comically long commit message... I don't think anyone would object to some of that text going into doc/ somewhere too for the benefit of sysadmins who are into their systemd stuff) |
|
Can we add the systemd disable/enable calls to the upgrade section of the ceph.spec and debian postinst (or whatever it is) files? |
|
I've got an alternate fix, which adds If we did go with the flattened hierarchy, then yes, we could do the re-enablement on upgrade on %post/postinst. I'm happy to update doc/ too :-) |
|
Some more information (partially cribbed from SUSE#129). To reproduce the problem, you need a node hosting both MON and OSD(s). AFAICT the problem occurs because systemd is confused by the combination of a two-level "hierarchy" of targets, plus a "cross-dependency" between ceph-osd@.service and ceph-mon.target (if ceph-osd@.service didn't specify After=ceph-mon.target, I suspect the problem would go away, but we don't want to remove that, so it's a moot point).
Everything is now disabled. A clean slate. So let's re-enable everything:
Now, check ceph.target:
Restart ceph.target works fine (no output, and everything gets restarted):
Now, disable ceph.target, and check the ordering again:
Suddenly, ceph.target when disabled is Before ceph-mon.target. If we try to use it now, it'll break:
I've done the above on SLES. I would greatly appreciate if someone with access to RHEL/Fedora/Ubuntu could try the same, and see if they have the same problem. I have two proposed fixes:
The behaviour of the various services for users invoking I have mixed feelings about both fixes. Mostly it comes down to:
So, what's the best (or least worst) solution here? (Ping @ddiss and @jan--f, who've commented on SUSE#129 already). |
|
In my mind, this is a workaround for a systemd bug (or odd systemd behavior) and the Also, I wonder what role udev plays in triggering the bug. |
That is indeed the case in my tests. I also found this detail in the systemd documentation:
Would that suggest that ceph-osd.target doesn not pick up the dependency to ceph-mon.target via the ceph-osd@.service files? Though how that creates a cycle is still a bit foggy to me. |
I think it just means that there won't be an ordering dependency created by magic.
My guess is that still won't prevent ceph.target potentially ending up in a weird place. |
My original guess was that udev triggering |
|
Is this fixing the same bug as http://tracker.ceph.com/issues/14839 ? |
|
Also, would it makes sense to keep ceph-*.target as PartOf ceph.target so that they also appear to "stop" when ceph.target is stopped? (So there would be 2 paths by which a single daemon should stop.. both via ceph.target directly and indirectly via ceph.target->ceph-foo.target?) |
|
There is a systemd test that runs on centos/xenial and tests various stop/starts/reboot, If the build is in chacra I would like to run those 2 tests with this wip* branch. |
|
@vasukulkarni Pushed |
|
@smithfarm thanks, will post the results here when it completes. |
b-ranto
self-requested a review
Jun 28, 2017
|
Hmm, ok, this happens because we only define a dependency (WantedBy) and restart/stop behaviour (PartOf), not the order (with Before) in the second level targets. Adding Before=ceph.target to each of the subtargets should help here and should probably be the preferred fix as not all the targets are always installed. You can check e.g. /usr/lib/systemd/system/machines.target which is in a similar situation (it is a target wanted by another target) and needs to have the Before= line defined as well. |
|
I tried adding (Although I don't think having After= for units that aren't installed matters, as that only defines ordering, not a dependency on existence, but I digress). So, now we have three options:
2 and 3 both don't need any service re-enablement on upgrade. Preferences, anyone? |
|
@tserong the option 3 should address your concern of 2 not being clean enough, I thought that 2 will print some warnings in the journal log if the targets are not installed but I am not so sure about it any more. I have a rather bad feeling about the option 1, it looks like it should work but I just think it will have some unexpected consequences that we will hit at some point in the future. |
tserong
changed the title from
[DNM] systemd: flatten target hierarchy
to
systemd: Add explicit Before=ceph.target
Jun 30, 2017
|
OK, I've redone this per option 3. @smithfarm, @jan--f, any objections? |
|
Jenkins re-test this please |
|
yep...lgtm. |
|
|
|
I assume that |
|
Jenkins re-test this please |
tserong commentedJun 22, 2017
The PartOf= and WantedBy= directives in the various systemd
unit files and targets create the following hierarchy:
Additionally, the ceph-{fuse,mds,mon,osd,radosgw,rbd-mirror}
targets have WantedBy=multi-user.target. This gives the
following behaviour:
systemctl {start,stop,restart}of any target will restartall dependent services (e.g.:
systemctl restart ceph.targetwill restart all services;
systemctl restart ceph-mon.targetwill restart all the mons, and so forth).
systemctl {enable,disable}for the second level targets(ceph-mon.target etc.) will cause depenent services to come
up on boot, or not (of course the individual services can
be enabled or disabled as well - for a service to start
on boot, both the service and its target must be enabled;
disabling either will cause the service to be disabled).
systemctl {enable,disable} ceph.targethas no effect onwhether or not services come up at boot; if the second level
targets and services are enabled, they'll start regardless of
whether ceph.target is enabled. This is due to the second
level targets all having WantedBy=multi-user.target.
(unless they are explicitly masked), thanks to udev magic.
So far, so good. Except, several users have encountered
services not starting with the following error:
Failed to start ceph-osd@5.service: Transaction order is
cyclic. See system logs for details.
I've not reproduced this myself, but have inspected systems
with this problem. It seems that somehow systemd gets
confused, and thinks:
i.e. ceph.target has wound up stuck in the middle of a
dependency cycle, rather than being after everything where
it should be. My best guess is that somehow the automatic
enablement and starting of OSDs on boot (thanks to udev
rules) is causing systemd to become confused about what's
meant to happen when.
Like I said, I haven't reproduced this myself, but I do have
a workaround. We can change PartOf= and WantedBy= in the
various service and target files to flatten the hierarchy,
removing all dependencies between the current second level
targets and ceph.target. This gives the following structure:
The behaviour remains the same as described above for the
existing hierarchy (start/stop/restart/enable/disable still
all work the same way), but by splitting ceph.target out, there's
no way for it to end up being stuck at point 3 in the cycle.
There is one caveat: existing systems using the original hierarchy
will have systemd's symlinks set up something like this:
[...]
/etc/systemd/system/ceph.target.wants/ceph-mon.target
/etc/systemd/system/ceph.target.wants/ceph-osd.target
/etc/systemd/system/ceph-mon.target.wants/ceph-mon@ses4-3.service
/etc/systemd/system/ceph-osd.target.wants/ceph-osd@2.service
[...]
But, with this change, the ceph.target.wants symlinks need to point
to services, not the old second level targets, i.e. it needs to
be as follows:
[...]
/etc/systemd/system/ceph.target.wants/ceph-osd@2.service
/etc/systemd/system/ceph.target.wants/ceph-mon@ses4-3.service
/etc/systemd/system/ceph-osd.target.wants/ceph-osd@2.service
/etc/systemd/system/ceph-mon.target.wants/ceph-mon@ses4-3.service
[...]
To fix these symlinks, you need to run
systemctl disablethensystemctl enablefor each of the target files, and each of theindividual services. Until you do this, systemctl start, stop and
restart on ceph.target will have no effect (start, stop and restart
on the other targets will work just fine though).
Fixes: https://bugzilla.suse.com/show_bug.cgi?id=1042973
Signed-off-by: Tim Serong tserong@suse.com