Configure HealthCheck with podman update

New flags in a `podman update` can change the configuration of HealthCheck when the container is started, without having to restart or recreate the container.

This can help determine why a given container suddenly started failing HealthCheck without interfering with the services it provides. For example, reconfigure HealthCheck to keep logs longer than the usual last X results, store logs to other destinations, etc.

Fixes: https://issues.redhat.com/browse/RHEL-60561

Signed-off-by: Jan Rodák <hony.com@seznam.cz>
This commit is contained in:
Jan Rodák
2024-10-24 14:01:58 +02:00
parent 77e67e7a54
commit a1249425bd
34 changed files with 958 additions and 198 deletions

View File

@ -116,10 +116,11 @@ func (c *Container) Start(ctx context.Context, recursive bool) (finalErr error)
}
// Update updates the given container.
// Either resource limits or restart policy can be updated.
// Either resources or restartPolicy must not be nil.
// Either resource limits, restart policies, or HealthCheck configuration can be updated.
// Either resources, restartPolicy or changedHealthCheckConfiguration must not be nil.
// If restartRetries is not nil, restartPolicy must be set and must be "on-failure".
func (c *Container) Update(resources *spec.LinuxResources, restartPolicy *string, restartRetries *uint) error {
// Nil values of changedHealthCheckConfiguration are not updated.
func (c *Container) Update(resources *spec.LinuxResources, restartPolicy *string, restartRetries *uint, changedHealthCheckConfiguration *define.UpdateHealthCheckConfig) error {
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()
@ -133,6 +134,41 @@ func (c *Container) Update(resources *spec.LinuxResources, restartPolicy *string
return fmt.Errorf("container %s is being removed, cannot update: %w", c.ID(), define.ErrCtrStateInvalid)
}
healthCheckConfig, changedHealthCheck, err := GetNewHealthCheckConfig(&HealthCheckConfig{Schema2HealthConfig: c.HealthCheckConfig()}, *changedHealthCheckConfiguration)
if err != nil {
return err
}
if changedHealthCheck {
if err := c.updateHealthCheck(
healthCheckConfig,
&HealthCheckConfig{Schema2HealthConfig: c.config.HealthCheckConfig},
); err != nil {
return err
}
}
startupHealthCheckConfig, changedStartupHealthCheck, err := GetNewHealthCheckConfig(&StartupHealthCheckConfig{StartupHealthCheck: c.Config().StartupHealthCheckConfig}, *changedHealthCheckConfiguration)
if err != nil {
return err
}
if changedStartupHealthCheck {
if err := c.updateHealthCheck(
startupHealthCheckConfig,
&StartupHealthCheckConfig{StartupHealthCheck: c.config.StartupHealthCheckConfig},
); err != nil {
return err
}
}
globalHealthCheckOptions, err := changedHealthCheckConfiguration.GetNewGlobalHealthCheck()
if err != nil {
return err
}
if err := c.updateGlobalHealthCheckConfiguration(globalHealthCheckOptions); err != nil {
return err
}
defer c.newContainerEvent(events.Update)
return c.update(resources, restartPolicy, restartRetries)
}