There I certain services, that I typically start together: say zookeeper+kafka+elassandra. Is there a way how to write composite unit: all starts together, all dies together? Meaning if I start this, it will delegate to start all that, and vice versa. What would be proper way of doing that?
One way is to have all three services depend on the remaining two using
- three.service: etc.
This won't create a loop – dependencies are independent from startup ordering.
(That said, you should declare some Before= or After=, e.g. if kafka needs to run after zookeeper.)
The other method is to create a .target unit, have it depend on your three services, and the services be
PartOf= the unit. (Unfortunately it is not yet possible to have ConsistsOf= in the .target itself.)
Requires=one.service two.service three.service
(Again, you should additionally declare dependencies and ordering between the services; don't rely only on the .target starting everything.)
Yes, there are a few ways to accomplish that.
The simplest one (which does some of what uou describe, but not all) is to create a target unit and add dependencies on your service units (for example,
Requires=zookeeper.service kafka.service elassandra.service and also set
After= to the same units.) A target unit is helpful in starting all these units together, but it doesn't really help you stop them all together (using
systemctl stop on the target unit won't stop its dependencies.) There are ways you can stop units, for example
systemctl isolate multi-user.target will stop all units that are not dependencies of that target, which means units started manually will be stopped, but this is much stronger than stopping a small set of units, so probably not a great fit...
A better approach is perhaps using the
PartOf= directive, which does exactly as you describe. You can either create a "dummy" service unit to manage all services together, or pick one of your services and make the others
PartOf that one service.
You need to configure
PartOf= in all the units you want to start and stop together, in your case, zookeeper.service, kafka.service and elassandra.service. But please note you don't necessarily need to modify the service unit files themselves (for example, if they're shipped with the software itself in deb or rpm packages.) You can use override files (which you can create using
systemctl edit) to add a small configuration snippet to an existing unit, which should make it easy for you to define
PartOf= relationships between units even if they're defined in files you would prefer not to modify.