Updates and restarts

Kubernetes (Helm chart). Seamless restarts and automatic image updates.

Seamless restarts

A restart or update starts the new pod, waits for it to be Ready, then stops the old one. Readings, MQTT publishing and the GUI continue through the rollout.

Enable

On by default in the Helm chart:

gracefulRollout:
  enabled: true     # default
valkey:
  enabled: true     # default; or config.Cache.Enabled with your own Valkey/Redis
Condition Deployment strategy
gracefulRollout.enabled and a cache (valkey.enabled or config.Cache.Enabled) RollingUpdate, maxSurge: 1, maxUnavailable: 0
No cache, or a ReadWriteOncePod history or floor plan volume Recreate

With a ReadWriteOnce history or floor plan volume, both pods are scheduled on the same node (a podAffinity, unless affinity is set).

Rollout sequence

sequenceDiagram
    participant Old as Old pod (leader)
    participant Lease as Leader lease (Valkey)
    participant New as New pod
    participant K8s as Kubernetes
    K8s->>New: start
    New->>New: connect to MQTT, standby
    New-->>K8s: Ready
    K8s->>Old: SIGTERM
    Old->>Lease: release
    New->>Lease: take lease
    New->>New: poll PDUs, publish, record history
    Old->>Old: disconnect MQTT, serve GUI/API for 10 s (/readyz failing)
    Old-->>K8s: exit
  • Only the lease holder polls, publishes, accumulates energy and writes history.
  • A standby takes the lease only while connected to MQTT.
  • The old pod disconnects from MQTT cleanly once the new pod holds the lease, so Home Assistant entities stay available.
  • A pod that is killed holds the lease for at most 15 s.
Variable Default
RPDU2MQTT_SHUTDOWN_DRAIN_SECONDS 10 Seconds the old pod keeps serving after SIGTERM
RPDU2MQTT_LEADER_LEASE_SECONDS 15 Lease length

The chart sets terminationGracePeriodSeconds: 45 on the pod.

What rolls the Deployment

Action Where
Restart Diagnostics page
Switch, Force update Operator page, Deployed version
Automatic update Auto Update
Config change helm upgrade with a changed config:
Scheduled restart autoRestart.enabled (Helm)

In the GUI

After Restart, Switch, Force update or an automatic update, the Live badge shows Updating and the page shows Waiting for the bridge to come back until the new pod answers. Dismiss appears after 30 s.

After any restart the page reconnects on its own. When the new pod runs a different version, the page reloads; with unsaved edits it asks you to save or discard first.

Without Helm

On every instance:

Setting Value
RPDU2MQTT_LEADER_LEASE true
Cache.Enabled true (the lease is kept in the cache)
RPDU2MQTT_DEPLOYMENT Deployment name, so Restart rolls it instead of deleting the pod
Deployment strategy RollingUpdate, maxSurge: 1, maxUnavailable: 0

Automatic updates

The app checks the container registry for a newer image and can roll its own Deployment to it.

Enable

Needs the Kubernetes CRD config source. Turn the feature on in the chart values:

kubernetesConfigSource:
  enabled: true
config:
  Operator:
    Enabled: true

The Operator page then appears in the GUI.

Without Helm, also set RPDU2MQTT_IMAGE to the deployed image and RPDU2MQTT_POD_NAME to the pod name (fieldRef: metadata.name).

Settings

Operator page:

Operator settings

Setting Default Values
Check For Updates On Check the registry on a schedule. Reports only
Check Interval Hours 6 Hours between checks. Minimum 1
Policy Minor How far an update may move the version (below)
Auto Update Off Roll the Deployment to the newest eligible image
Registry registry of the deployed image e.g. ghcr.io
Repository repository of the deployed image e.g. xtremeownage/rpdu2mqtt

Press Save. All keys: Operator settings.

Policy

Applies to version tags (2.0.1, v2.0.1).

Policy Deployed 2.1.3 may move to
Patch 2.1.x
Minor 2.x.y
Major any newer release

Pre-release tags (2.2.0-beta.1) are never selected.

Channel tags

For a moving tag (unstable, dev, edge, main, latest, stable) the check compares the tag's digest in the registry with the digest the pod is running. Policy does not apply. With Auto Update on, a newer build is pulled under the same tag, pinned by digest.

Update check

Operator › Update check › Check now runs a check immediately. It does not change the Deployment.

Deployed version

Operator › Deployed version:

Control Action
Switch Roll the Deployment to the selected channel or release
Force update Re-pull the deployed tag now, pinned by digest

Header badge

Header badges

Badge Meaning
↑ 2.1.4 (amber) Newer release available. On a channel tag, shows the channel (↑ unstable): a newer build of it is available
✓ 2.1.3 (green) Up to date
Check updates No result yet, or the check could not run. Hover for the reason

Click the badge to check now. Hidden without the Kubernetes config source.

When Auto Update rolls the Deployment, the GUI shows Update applied — rolling to … and waits for the new pod (In the GUI).

What is updated

Every Deployment in the release that runs the app image: the container image and RPDU2MQTT_IMAGE. The Valkey Deployment is not changed. Each Deployment rolls with its own strategy, so the update is seamless when that is enabled.

Status

The result is written to the RpduConfig status:

kubectl get rpduconfig rpdu2mqtt -n rpdu2mqtt -o jsonpath='{.status.update}'
Field
available Newer eligible image exists
current, latest Deployed and newest eligible tag
policy, autoUpdate Settings used
applied, appliedAt Tag and time of the last automatic roll
checkedAt Time of the last check
message Result text

Schedule

First check 20 s after start. Checks then run every Check Interval Hours.