Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rolling restart #619

Merged
merged 4 commits into from
Aug 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ var (
notifier *notifications.Notifier
timeout time.Duration
lifecycleHooks bool
scope string
rollingRestart bool
scope string
)

var rootCmd = &cobra.Command{
Expand Down Expand Up @@ -91,6 +92,7 @@ func PreRun(cmd *cobra.Command, args []string) {

enableLabel, _ = f.GetBool("label-enable")
lifecycleHooks, _ = f.GetBool("enable-lifecycle-hooks")
rollingRestart, _ = f.GetBool("rolling-restart")
scope, _ = f.GetString("scope")

log.Debug(scope)
Expand Down Expand Up @@ -211,6 +213,7 @@ func runUpdatesWithNotifications(filter t.Filter) {
Timeout: timeout,
MonitorOnly: monitorOnly,
LifecycleHooks: lifecycleHooks,
RollingRestart: rollingRestart,
}
err := actions.Update(client, updateParams)
if err != nil {
Expand Down
13 changes: 12 additions & 1 deletion docs/arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,18 @@ can be defined, but not both. An example: `--schedule "0 0 4 * * *"`
Environment Variable: WATCHTOWER_SCHEDULE
Type: String
Default: -
```
```

## Rolling restart
Restart one image at time instead of stopping and starting all at once. Useful in conjunction with lifecycle hooks
to implement zero-downtime deploy.

```
Argument: --rolling-restart
Environment Variable: WATCHTOWER_ROLLING_RESTART
Type: Boolean
Default: false
```

## Wait until timeout
Timeout before the container is forcefully stopped. When set, this option will change the default (`10s`) wait time to the given value. An example: `--stop-timeout 30s` will set the timeout to 30 seconds.
Expand Down
37 changes: 30 additions & 7 deletions internal/actions/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,33 @@ func Update(client container.Client, params types.UpdateParams) error {
return nil
}

stopContainersInReversedOrder(containers, client, params)
restartContainersInSortedOrder(containers, client, params)

if params.RollingRestart {
performRollingRestart(containers, client, params)
} else {
stopContainersInReversedOrder(containers, client, params)
restartContainersInSortedOrder(containers, client, params)
}
if params.LifecycleHooks {
lifecycle.ExecutePostChecks(client, params)
}
return nil
}

func performRollingRestart(containers []container.Container, client container.Client, params types.UpdateParams) {
cleanupImageIDs := make(map[string]bool)

for i := len(containers) - 1; i >= 0; i-- {
if containers[i].Stale {
stopStaleContainer(containers[i], client, params)
restartStaleContainer(containers[i], client, params)
}
}

if params.Cleanup {
cleanupImages(client, cleanupImageIDs)
}
}

func stopContainersInReversedOrder(containers []container.Container, client container.Client, params types.UpdateParams) {
for i := len(containers) - 1; i >= 0; i-- {
stopStaleContainer(containers[i], client, params)
Expand Down Expand Up @@ -99,11 +117,16 @@ func restartContainersInSortedOrder(containers []container.Container, client con
restartStaleContainer(staleContainer, client, params)
imageIDs[staleContainer.ImageID()] = true
}

if params.Cleanup {
for imageID := range imageIDs {
if err := client.RemoveImageByID(imageID); err != nil {
log.Error(err)
}
cleanupImages(client, imageIDs)
}
}

func cleanupImages(client container.Client, imageIDs map[string]bool) {
for imageID := range imageIDs {
if err := client.RemoveImageByID(imageID); err != nil {
log.Error(err)
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions internal/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ func RegisterSystemFlags(rootCmd *cobra.Command) {
viper.GetBool("WATCHTOWER_LIFECYCLE_HOOKS"),
"Enable the execution of commands triggered by pre- and post-update lifecycle hooks")

flags.BoolP(
"rolling-restart",
"",
viper.GetBool("WATCHTOWER_ROLLING_RESTART"),
"Restart containers one at a time")

flags.BoolP(
"http-api",
"",
Expand Down
1 change: 1 addition & 0 deletions pkg/types/update_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ type UpdateParams struct {
Timeout time.Duration
MonitorOnly bool
LifecycleHooks bool
RollingRestart bool
}