-
Notifications
You must be signed in to change notification settings - Fork 302
fleet: add replace unit support #1509
fleet: add replace unit support #1509
Conversation
We need further testing for this one. thanks! |
Regarding the test issue: I don't know whether this is a bug or expected behaviour; but there seems to be no guarantee that the units have reached the final states by the time the command returns. That's why all the existing tests use |
According to the commit message of the first commit (and from a quick glance at the code), a command with Slightly less clear is what to do for example if a unit is already |
Without actually digging into the code, I see some formal issues with this PR from looking through the commit messages. Some of the commits are just fixing things introduced in earlier commits of the same PR (such as the gofmt fix) -- these should be squashed into the respective commit(s) that introduced the problematic code in the first place. Also, it looks like the order of the commits is wrong: the commit introducing the |
f2412d0
to
c72428e
Compare
c72428e
to
6d38716
Compare
@antrik yes actually only one commit that gofmt which was fixed, thanks! ok could you please dig then in the code and ping us if we missed something, this is new functionality. On the note on how to replace units, Yes start --replace should overwrite submit and load but not the other way. Later fleet should be enforced to follow up the life cycle and states of units... @jonboulle we have added functional tests to replace many units, etc, the functionality is there... but to be honest the thing that bothers me is the order of systemd directives... but hey it depends also on the units. Since fleet is declarative, putting StopPost directives that are buggy or do not finish and updating is asking for trouble... |
I think we should provide 2 things.
So I think we could use |
Makes sense. So I added such checks to the functional tests. Maybe during the next update, this patch will be included: For now this test seems to work. However, I'm a little careful about adding more tests included in this PR. I'd rather create a new PR afterwards for further comprehensive tests. |
submit is to submit units into the cluster, so the desired state is submit and incative: Now if you add "--replace" into the game, and if I quote you "will automatically reload and restart" here you are mixing submit, load and start desired states. If you want to achieve that then just do "start --replace" why "--submit --replace" ? we should not mix desired states, and we should follow the life cycle of units and services, otherwise we introduce confusion, not to mention that these operations are also handled by systemd... So here just use the appropriate command. |
The way to replace a unit and restart it, is what this PR does! we re-execute systemd directives, could you please try it ? edit your unit, then fleetctl start --replace ? And the second way you mention is also handled and the manager instructs systemd to reload. Now for submit it does not at all involve systemd reload! Thank you! |
@klausenbusk AIUI fleet doesn't presently have any notion of reloading a unit? While IIRC there have been requests for that, I don't think we should try to address this question here. This PR is quite complicated as it is... |
I want a way I can replace a unit without restarting it! But as @antrik said, that should be another pr.
It a rather long process, and it take some time. If I could replace the unit, I could just ssh the every db server and do sudo systemctl restart mariadb-galera (without downtime). |
@klausenbusk ok, could you also explain in more details what are 3), 4), 5) and 6) ? and the content of your units ? It seems you have the case of template units here? actually currently with this PR you could "submit --replace" a template unit, and already started units from the previous template will not be restarted. To do so you have to add an extra "start --replace template@{x..y}", so the question I see here: between this time could you think of a solution for your use case ? "fleetctl start --replace" triggers systemd daemon-reload and all the same processes as "systemctl restart" after that. And a note so we don't forget, we have these transitions: So unless I'm missing something here, if your units are in the launched state and you want to put them in the loaded state it will always involve a stop (Stop and StopPost directives) then daemon-reload, hence a downtime. Perhaps there is a solution for your use case if you could tell us more ? Thank you! |
Note: I have 3 db nodes.
I use a global unit currently, I see a template unit as a stupid workaround. |
@klausenbusk why do you use Using templates you can ask fleet to start unit on corresponding machine, i.e. fleetctl start mariadb-galera-initial@node1
fleetctl start mariadb-galera@node{2..3}
fleetctl stop mariadb-galera-initial@node2
fleetctl start mariadb-galera@node1 These steps could be automated with sidekicks |
@klausenbusk it seems what you are essentially asking for is a way to temporarily inhibit part of fleet's reconciliation logic, so it will submit (and load) the new unit, but ignore the fact that the existing unit doesn't match the new requested state... While I can see the use case for this, I have no idea right now whether this could be done without breaking some fundamental assumptions... |
I don't see any big benefit of using template. I only need to ssh to 1 node instant of 3, that the only benefit, and I can't add a new db node without doing The problem is that I need to stop the whole cluster to change the unit file. What I ask for, is a |
@klausenbusk what is the problem of using current implementation Then you can run This solution doesn't require to stop the cluster. |
@dongsupark if you have test cases in mind further testing the functionality introduced in this PR, they clearly belong here, and not into some followup. |
Oh, I didn't through it worked that way. :) I still prefer a global unit, but template units could be a solution until then. |
A flag which restart a global unit node-by-node could be useful.
@klausenbusk yeah, that has been requested before. However, as I tried
to explain, this doens't really jibe well with fleet's automatic
reconciliation model. Also, AIUI it is considered somewhat out of scope
for fleet...
|
@@ -78,6 +78,7 @@ var ( | |||
Debug bool | |||
Version bool | |||
Help bool | |||
currentCommand string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not really a flag -- and I don't think it's a good idea to treat it as one. While it might look slightly easier than explicitly passing through the command to the functions which need to discriminate on it, it's also harder to follow the code. Such things are generally frowned upon -- for good reason.
cd3a786
to
011a5a3
Compare
@jonboulle it's ready, basically I ended up implementing it in an other way, please see comment: #1509 (comment) and also to make sure that Another advantage we don't add replace target hashes nor wait from the client perspective fleetctl for the hashes to be updated to the new version, we just wait for the new unit (new hash) to reach its own desired state: submitted, loaded or started as it's currently done. The old unit will be stopped or unloaded before that when we set the inactive state. So instead of waiting for the reconcile, we just do what it does but without waiting and without adding so much code. Thank you! |
eb6ef52
to
12b7db5
Compare
For the record, patches 9, 10, 11 lgtm, I just added a complex test to cover what I described in this comment: #1509 (comment) the test is documented and this allows us to make sure that systemd directives are serialized but only in the current replace context, external operations are not our fault. Waiting for some lgtm, then will merge it, we have been rebasing this branch for some time now... Thanks! |
12b7db5
to
b4ee8d5
Compare
|
@tixxdz there is one issue I've just found. When you replace templated unit, updated unit has being scheduled on different machine. Steps to reproduce: fleetct submit [email protected]
fleetct start hello@{1..10}.service Then you'll get the units list:
Then make replace:
And you'll see that unit has been moved from to coreos3 to coreos1:
Should we document that behavior or should we reschedule unit on the same machine it was started before and move it only when there is a explicit need or requirement? Otherwise when you use extra [X-Fleet]
MachineMetadata="hostname=coreos%i" |
@kayrus fleetctl submit; load or start deal with the notion of cluster, and not a single specified machine. If we go that path then IMO we will reduce fleet functionality and further changes. If we schedule on the same machine:
Now if users want to replace on the same machine, there is already the option: This allows us to solve previous points:
Now for the record we have to update fleetctl help message to let users that it replaces a unit in the cluster and not into a specific node, now if you want it to be in node X, then add Will update the "--replace" help message right now. Thanks! |
This patch adds some variables that will be used in the next patch to implement replace units feature. The replace flag and the current command that's being executed.
Add checkUnitCreation() to check if the unit should be created or not. This function handles the new replace logic. Add isLocalUnitDifferent() since we don't really want to warn if the Unit do really differ in case "--replace" switch was set. At the same time factor our unit matching logic. The function handles both cases when '--replace' is set and not.
Just use isLocalUnitDifferent() instead of old warnOnDifferentLocalUnit()
Move MatchUnitFile() to unit package we will use it inside fleetd to check for unit matching.
If there is a unit with the same name, check if the content of both differ if so then we create a new one in the registry.
Since we started to support replacing units and updating their job entries, we instruct etcd driver to allow updating the job object key with the new provided unit, and ignore 'job already exists' errors.
Add new helpers util.CopyFile(), util.GenNewFleetService() to prepare the new functional tests for the replace options. util.CopyFile() is a helper to copy one file to another. util.GenNewFleetService() is a helper to replace a string with a new one. It's necessary for the next functional tests.
TestUnit{Submit,Load,Start}Replace() tests whether a command "fleetctl {submit,load,start} --replace hello.service" works respectively. As most of the test sequences are identical, the common part is split into replaceUnitCommon().
For commands fleetctl {submit,load,start}, also test loading multiple units at the same time, and replacing each of them one after another.
… of systemd directives This tests asserts that systemd directives are serialized when we transit from the old version of the unit to the new one. Make sure that ExecStartPre of the new one are executed after ExecStopPost of the previous one.
b4ee8d5
to
23750a1
Compare
@tixxdz I've tried to not unload units, but just stop them. This doesn't work as expected. Fleet for some reason hangs. Other solution is to implement "desiredMachine/rescheduleOnTheSameMachine" option, which could be ignored in case when unit could not be replaced on the same machine (i.e. |
@kayrus actually yes, we have to unload, free resources, reset status of failed units through systemd manager, and other operations to clean up things. For the Thank you! |
So this one looks good, all tests pass, many comments. I'm merging it now to unblock the situation, so it won't be lost nor the upcoming PRs. For users who want to replace units on the same machine they could use what's already being used: Later one may add @jonboulle in all ways, we have to unload then load, hence the rescheduling. Thank you! |
This PR allows units to be replaced with "submit", "load" and "start" commands. Just add the new "--replace" switch.
The previous discussion was about overwrite in this PR #1295
This PR tries to fix: #760