Skip to content

feat(valkey): add Valkey Sentinel for automatic failover - #234

Open
pat-s wants to merge 5 commits into
valkey-io:mainfrom
pat-s:feat/sentinel-ha
Open

feat(valkey): add Valkey Sentinel for automatic failover#234
pat-s wants to merge 5 commits into
valkey-io:mainfrom
pat-s:feat/sentinel-ha

Conversation

@pat-s

@pat-s pat-s commented Aug 1, 2026

Copy link
Copy Markdown

Supersedes #137, rebased onto current main with the review feedback applied. Sentinel only; the HAProxy front-end follows in a separate PR.

Replication mode cannot recover from a master failure: the master is always pod-0 and clients keep writing to it until someone intervenes. This runs valkey-sentinel next to the server in every pod, so a replica is promoted automatically. Off by default (replica.sentinel.enabled).

Beyond #137:

  • The valkey service no longer pins its selector to pod-0 when Sentinel is enabled, otherwise the write endpoint still points at a demoted replica after a failover.
  • The replication target Sentinel writes via CONFIG REWRITE survives restarts, instead of every pod resetting to "pod-0 is master".
  • Sentinel rediscovers the current master on startup (peers first, local node second), so a restarted Sentinel never tries to demote the real master.
  • A preStop hook fails over before a master pod is terminated, so rolling updates do not strand clients on a dying master.
  • Sentinel's own port and the inter-Sentinel gossip are authenticated whenever auth.enabled is set, with no extra configuration.

Testing

helm lint, 158 unit tests, and rendering against k8s 1.28/1.35/1.36. Verified on a kind cluster with ACL auth using valkey/examples/ha-sentinel.yaml:

  • 3 Sentinels form a quorum and discover both replicas
  • frozen master → replica promoted in 7s, data intact, old master rejoins as replica
  • rolling update of the master → +switch-master before the pod goes away
  • full restart of all 3 pods → topology preserved, master does not reset to pod-0
  • Sentinel port rejects unauthenticated clients

@Bloodraven21 the example values file above is the exact one used for those tests.

One drive-by fix: a stray tab in statefulset.yaml made rendered manifests unparseable for strict YAML parsers.

Credit to @khtee, @jose-10000, @yoannrt, @tkarger, @lazariv and @dmaes, whose work in #137 this builds on.

Replication mode alone cannot recover from a master failure: the master is
always pod-0 and clients keep writing to it until an operator intervenes.

Run a valkey-sentinel container next to the Valkey server in every pod, so
that the Sentinels monitor each other and promote a replica automatically
when the master stops responding. Enabled with replica.sentinel.enabled.

* Stop pinning the valkey service selector to pod-0 when Sentinel is enabled,
  the master can be any pod after a failover.
* Preserve the replication target Sentinel wrote via CONFIG REWRITE across
  restarts, instead of resetting every pod to "pod-0 is master".
* Rediscover the current master on Sentinel startup by asking the running
  peers first and the local Valkey node second, so that a restarted Sentinel
  never tries to demote the real master.
* Ask Sentinel to fail over in a preStop hook when the terminating pod is the
  master, so a rolling update does not leave clients on a dying master.
* Secure the Sentinel port and the Sentinel gossip with the default user
  credentials whenever auth is enabled.
* Drop a stray tab in the statefulset volumeClaimTemplates that made the
  rendered manifests unparseable for strict YAML parsers.

Co-authored-by: KHTee <teekahhui@hotmail.com>
Co-authored-by: Jose Dominguez <jdominguez.ops@gmail.com>
Co-authored-by: yoannrt <yoann.rousseau@gmail.com>
Co-authored-by: Dieter Maes <dieter.maes@dmaes.be>
Co-authored-by: Tim Karger <49390121+tkarger@users.noreply.github.com>
Co-authored-by: lazariv <lazariv.taras@gmail.com>
Signed-off-by: pat-s <patrick.schratz@devxy.io>
@greptile-apps

greptile-apps Bot commented Aug 1, 2026

Copy link
Copy Markdown

Greptile Summary

This change adds optional Valkey Sentinel sidecars for replicated deployments, including Sentinel discovery, topology restoration, authenticated access, client service exposure, persistence, graceful shutdown failover, configuration validation, tests, and an authenticated HA example.

A three-node authenticated Valkey/Sentinel runtime check confirmed that the monitor user does not need direct FAILOVER permission for Sentinel to promote replicas. Both a requested failover and a subsequent automatic failover selected a new master successfully, so the documented monitor ACL does not block Sentinel failover.

T-Rex validation blocked

The executed Sentinel runtime harness and its captured output could not be uploaded because the Greptile artifact-upload service was unavailable in this environment. No secret values were exposed.

Confidence Score: 5/5

The PR is safe to merge; no blocking failure remains.

The final defect set is empty. The authenticated three-node runtime exercise contradicted the investigated failover failure hypothesis: Sentinel successfully promoted a new master for both requested and automatic failover.

T-Rex T-Rex Logs

What T-Rex did

  • The T-Rex harness executed Valkey 9.1.1 with three ACL-authenticated servers and three authenticated Sentinels.
  • The monitoring user reported lacking direct permission to run failover, but failover still proceeded via manual and automatic paths.
  • A manual failover was accepted (MANUAL_FAILOVER_REQUEST=OK) and promoted the master at 127.0.0.1:16380, followed by an automatic failover promoting a new master at 127.0.0.1:16381 with SENTINEL_FLAGS=master.
  • Artifact uploads could not be provided because the artifact-upload service was unavailable.
  • The observed sequence contradicts the claimed failure path that the monitor user lacked failover permissions, since Sentinel performed manual and automatic failovers anyway.

T-Rex Ran code and verified through T-Rex

Reviews (5): Last reviewed commit: "docs(valkey): include sentinel secret cr..." | Re-trigger Greptile

Comment thread valkey/templates/init_config.yaml Outdated
Comment thread valkey/templates/sentinel-configmap.yaml
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@pat-s, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 46 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 50197fcb-65be-4c78-b230-3787b097a934

📥 Commits

Reviewing files that changed from the base of the PR and between b42995d and 5c86403.

📒 Files selected for processing (1)
  • valkey/examples/ha-sentinel.yaml
📝 Walkthrough

Walkthrough

The Helm chart adds Valkey Sentinel high availability with configurable monitoring, authentication, failover, persistence, services, sidecars, validation, bootstrap logic, documentation, examples, and tests.

Changes

Valkey Sentinel high availability

Layer / File(s) Summary
Sentinel configuration and validation
valkey/values.yaml, valkey/values.schema.json, valkey/templates/_helpers.tpl, valkey/templates/deploy_valkey.yaml, valkey/templates/statefulset.yaml, valkey/templates/secret.yaml, valkey/examples/ha-sentinel.yaml, valkey/tests/sentinel_test.yaml, valkey/tests/secret_test.yaml, valkey/README.md, valkey/Chart.yaml, valkey/.helmignore
The chart defines replica.sentinel settings, validates Sentinel requirements, renders the Sentinel password, and adds supporting documentation, examples, tests, chart metadata, and ignore patterns.
Sentinel bootstrap and failover runtime
valkey/templates/init_config.yaml, valkey/templates/sentinel-configmap.yaml, valkey/templates/_helpers.tpl, valkey/tests/sentinel_test.yaml
Initialization preserves Sentinel-selected topology. Sentinel scripts discover the master, generate authenticated and TLS-enabled configuration, check health, and request pre-stop failover.
StatefulSet, services, and rendered guidance
valkey/templates/statefulset.yaml, valkey/templates/service.yaml, valkey/templates/service-headless.yaml, valkey/templates/sentinel-service.yaml, valkey/templates/NOTES.txt, valkey/tests/sentinel_test.yaml
The StatefulSet adds Sentinel sidecars, storage, probes, lifecycle hooks, mounts, and rollout checks. Services and NOTES output expose Sentinel discovery and routing behavior.

Sequence Diagram(s)

sequenceDiagram
  participant StatefulSet
  participant SentinelSidecar
  participant ValkeyInit
  participant ValkeyNode
  participant SentinelPeers
  StatefulSet->>SentinelSidecar: Start Sentinel sidecar
  SentinelSidecar->>SentinelPeers: Discover monitored master
  SentinelSidecar->>ValkeyNode: Generate sentinel.conf
  ValkeyInit->>ValkeyNode: Restore or assign replication target
  SentinelSidecar->>SentinelPeers: Monitor Valkey node
  StatefulSet->>SentinelSidecar: Run pre-stop failover
  SentinelSidecar->>SentinelPeers: Request master failover
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary change: adding Valkey Sentinel support for automatic failover.
Description check ✅ Passed The description directly explains Sentinel failover, configuration changes, review fixes, and testing for the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
valkey/README.md (1)

43-45: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the empty **IMPORTANT** label.

The content that followed this label moved out of the Replication Mode section. The label now renders as a bold word with no body.

📝 Proposed change
-**IMPORTANT**
-
 **Services:**
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@valkey/README.md` around lines 43 - 45, Remove the standalone **IMPORTANT**
label immediately before the Services section in the README, leaving the
Services content and surrounding documentation unchanged.
🧹 Nitpick comments (2)
valkey/examples/ha-sentinel.yaml (1)

29-36: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the on flag from replicator.permissions.

The chart emits the ACL rule as user <name> on >password <permissions>, as shown in valkey/values.yaml line 238. The default user above and the examples in values.yaml omit on. Keep the same form here so users do not copy a duplicated flag.

♻️ Proposed change
       permissions: >-
-        on ~* &* +multi +exec +ping +info +role +subscribe +publish +slaveof
+        ~* &* +multi +exec +ping +info +role +subscribe +publish +slaveof
         +replicaof +config|rewrite +client|setname +client|kill +script|kill
         +psync +replconf
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@valkey/examples/ha-sentinel.yaml` around lines 29 - 36, Remove the leading
“on” token from the replicator.permissions ACL rule while preserving all
existing key patterns and command permissions, matching the format used by the
chart’s ACL rendering and other examples.
valkey/templates/service.yaml (1)

34-38: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The service keeps write semantics that it no longer provides in Sentinel mode.

Removing the pod-0 pin is correct, because the master moves after a failover. The service still carries app.kubernetes.io/component: primary at line 7, and NOTES.txt still presents it under "WRITE Operations". Clients that follow the label or the notes will send writes to replicas and receive -READONLY.

Consider setting a different component label in Sentinel mode, so that consumers of the label do not treat this service as master-only.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@valkey/templates/service.yaml` around lines 34 - 38, Update the service
metadata around the component label and the Sentinel configuration condition so
Sentinel mode no longer advertises the service as primary/master-only. Preserve
the primary component label for non-Sentinel deployments, and align the service
label with the behavior documented for Sentinel consumers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@valkey/README.md`:
- Around line 104-107: Update the fenced code block containing the ACL
permission list in the README to specify the text language, changing the opening
fence to use text while preserving the block contents.

In `@valkey/templates/_helpers.tpl`:
- Around line 219-224: Update the Sentinel monitor-user resolution in the
auth-enabled block around $monitorUser and valkey.validateSentinelConfig so
auth.aclConfig-only configurations do not dereference a missing auth.aclUsers
map. Add the same nil-safe guard before reading auth.aclUsers, or ensure the
validator emits the existing explicit missing-user failure before this lookup,
while preserving the current fallback and fail message for defined ACL users.

In `@valkey/templates/init_config.yaml`:
- Around line 181-196: The sentinel bootstrap decision in init.sh must not let
pod 0 become MASTER solely because local PVC state is missing after failover.
Before the POD_INDEX master branch, reuse sentinel-start.sh’s peer-discovery
mechanism to query a reachable Sentinel and, when it reports a promoted master,
set REPLICATION_TARGET to replicaof that address; only fall back to pod 0 as
MASTER when discovery finds no existing master.
- Around line 169-179: Update the listening-port configuration to use
.Values.service.port instead of a hardcoded 6379, preserving the existing
TLS/non-TLS directive ordering. Apply this in valkey/templates/init_config.yaml
lines 169-179 and update the corresponding hardcoded port references in
valkey/templates/sentinel-configmap.yaml lines 75-81 and 279-285 so Sentinel
uses the same configured port.

In `@valkey/templates/NOTES.txt`:
- Around line 26-32: Update the Sentinel connection examples in NOTES.txt to
branch on .Values.replica.sentinel.service.enabled: use the existing service
hostname and sentinel.service.port when enabled, and use the headless service
hostname with .Values.replica.sentinel.port when disabled. Apply the same
conditional endpoints to both the valkey-cli command and the Python Sentinel
example.

In `@valkey/templates/sentinel-configmap.yaml`:
- Around line 86-101: The master_from_peers function must validate sentinel_cli
output before accepting it: require exactly two stdout lines containing a valid
master host and port, and reject empty, malformed, or error-reply output when
the peer is not configured for MASTER_SET. Only log, echo, and return success
for an unambiguous validated address; otherwise continue checking the remaining
peers.

In `@valkey/templates/sentinel-service.yaml`:
- Around line 21-23: Update the loadBalancerSourceRanges rendering in the
sentinel service template to serialize the list with Helm’s toYaml helper,
preserving valid YAML sequence syntax and the existing conditional block.

In `@valkey/templates/statefulset.yaml`:
- Around line 19-25: Add an upgrade note under the Sentinel section in
valkey/README.md documenting that enabling Sentinel may change immutable
StatefulSet fields, including podManagementPolicy and persistence
volumeClaimTemplates, so users must delete the StatefulSet with --cascade=orphan
before helm upgrade to allow existing pods and PVCs to be re-adopted.

---

Outside diff comments:
In `@valkey/README.md`:
- Around line 43-45: Remove the standalone **IMPORTANT** label immediately
before the Services section in the README, leaving the Services content and
surrounding documentation unchanged.

---

Nitpick comments:
In `@valkey/examples/ha-sentinel.yaml`:
- Around line 29-36: Remove the leading “on” token from the
replicator.permissions ACL rule while preserving all existing key patterns and
command permissions, matching the format used by the chart’s ACL rendering and
other examples.

In `@valkey/templates/service.yaml`:
- Around line 34-38: Update the service metadata around the component label and
the Sentinel configuration condition so Sentinel mode no longer advertises the
service as primary/master-only. Preserve the primary component label for
non-Sentinel deployments, and align the service label with the behavior
documented for Sentinel consumers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c6fd83c9-180e-40e7-9759-3b120b5dc905

📥 Commits

Reviewing files that changed from the base of the PR and between 01b4fa4 and fa6cfb8.

📒 Files selected for processing (16)
  • valkey/.helmignore
  • valkey/Chart.yaml
  • valkey/README.md
  • valkey/examples/ha-sentinel.yaml
  • valkey/templates/NOTES.txt
  • valkey/templates/_helpers.tpl
  • valkey/templates/deploy_valkey.yaml
  • valkey/templates/init_config.yaml
  • valkey/templates/sentinel-configmap.yaml
  • valkey/templates/sentinel-service.yaml
  • valkey/templates/service-headless.yaml
  • valkey/templates/service.yaml
  • valkey/templates/statefulset.yaml
  • valkey/tests/sentinel_test.yaml
  • valkey/values.schema.json
  • valkey/values.yaml

Comment thread valkey/README.md Outdated
Comment thread valkey/templates/_helpers.tpl
Comment thread valkey/templates/init_config.yaml Outdated
Comment thread valkey/templates/init_config.yaml
Comment thread valkey/templates/NOTES.txt Outdated
Comment thread valkey/templates/sentinel-configmap.yaml
Comment thread valkey/templates/sentinel-service.yaml Outdated
Comment thread valkey/templates/statefulset.yaml Outdated
The bootstrap marker was written on every pod, so a pod that lost its
valkey.conf while keeping the marker, for example when the init container was
interrupted between removing the old config and writing the new one, read the
marker as proof that it used to be the master and came back as a second
writable master.

Drop the marker and derive the role from the previous config instead, which
already carries the answer: a config with a replicaof directive means replica,
a complete config without one means master, and no config at all means this is
a first boot that falls back to the pod index. Assemble the config in a
temporary file and move it into place at the end, so a config on disk is
always complete and the distinction holds.

Also only disable protected mode on Sentinel when auth is disabled, where
peers could not connect otherwise, and say so in values.yaml.

Signed-off-by: pat-s <patrick.schratz@devxy.io>
@pat-s

pat-s commented Aug 1, 2026

Copy link
Copy Markdown
Author

Thanks bots. Pushed a fix for two of the three findings:

Bootstrap marker split-brain (Greptile, P1) — real, fixed. The marker is gone. The role now comes from the previous config, which already carries the answer: a replicaof directive means replica, a complete config without one means master, no config means first boot and the pod index decides. The config is assembled in a temp file and moved into place at the end, so a config on disk is always complete and that distinction holds.

Verified on a kind cluster by wiping valkey.conf on a replica and restarting it: it comes back as a replica and Sentinel re-points it at the master. Before the fix that path produced a second writable master.

Unauthenticated Sentinel port (Greptile, P1)protected-mode no is now only emitted when auth.enabled is false, where Sentinel peers could not connect otherwise. Worth noting the exposure is not specific to Sentinel: with auth disabled the Valkey port is equally open. Called out in values.yaml so it is not a surprise.

Nil auth.aclUsers.default with aclConfig only (CodeRabbit) — not reachable. Sentinel requires replica.enabled, and validateReplicaAuth already fails for an aclConfig-only setup, while validateAuthConfig requires default in aclUsers whenever aclUsers is set. Both produce a clear message before the Sentinel templates index the map:

$ helm template t ./valkey --set replica.enabled=true --set replica.sentinel.enabled=true \
    --set auth.enabled=true --set auth.aclConfig="user default on >pw ~* &* +@all" ...
Error: Replication user 'default' (replica.replicationUser) must be defined in auth.aclUsers.

Also took the MD040 suggestion.

Comment thread valkey/templates/sentinel-configmap.yaml
…argv

Review follow-ups on the Sentinel support.

* Ask the running Sentinels for the current master when a pod starts without a
  usable config. A pod that lost its volume previously fell back to the pod
  index, so pod-0 came back as a second writable master after a failover.
* Render the Valkey listen port from service.port instead of a hardcoded 6379,
  which made a custom service.port disagree with the container port.
* Pass credentials to valkey-cli through REDISCLI_AUTH so they no longer show
  up in the process list of the pod.
* Reject an incomplete answer from a peer Sentinel, an error reply would
  otherwise be written into the monitor directive and stop Sentinel from
  starting. Bound the peer queries with a timeout and widen the startup probe
  to cover discovery.
* Set terminationGracePeriodSeconds and refuse a preStop failover timeout that
  would be cut short by SIGKILL.
* Allow replica.podManagementPolicy to be pinned, so an existing release can
  enable Sentinel without recreating the immutable StatefulSet, and document
  the recreate for anyone who takes the default.
* Render loadBalancerSourceRanges as a YAML list, and point the notes at the
  headless service when the Sentinel service is disabled.

Signed-off-by: pat-s <patrick.schratz@devxy.io>
@pat-s

pat-s commented Aug 1, 2026

Copy link
Copy Markdown
Author

Second round of review fixes pushed. Verified on a kind cluster with ACL auth.

Fixed

  • Pod-0 restarts as a second master after losing its volume (CodeRabbit) — real. init.sh now asks the running Sentinels for the current master before falling back to the pod index, the same discovery sentinel-start.sh already did. Reproduced by failing over away from pod-0, deleting pod-0's entire data directory and restarting it. Before: pod-0 came back a writable master. Now:

    Sentinel reports valkey-2.valkey-headless...:6379 as the master, starting as REPLICA
    valkey-0: role:slave  master_host:valkey-2...
    valkey-1: role:slave  master_host:valkey-2...
    valkey-2: role:master
    
  • Hardcoded listen port (CodeRabbit) — real, and pre-existing. init.sh wrote port 6379 while the container port and Services use service.port, so --set service.port=6380 produced a server listening on the wrong port. Now rendered from service.port.

  • Password in argv (CodeRabbit) — all three scripts use REDISCLI_AUTH instead of -a, so credentials are no longer in /proc/<pid>/cmdline.

  • Unvalidated peer answer (CodeRabbit, both comments) — a host/port pair is now required, and the port must be numeric, before it becomes a sentinel monitor directive. Peer queries are bounded with -t 2 and the startup probe budget widened to cover discovery.

  • preStop timeout vs grace period (CodeRabbit) — added replica.terminationGracePeriodSeconds (30) and rendering fails if preStopFailoverTimeoutSeconds is not lower than it.

  • Immutable StatefulSet fields (CodeRabbit) — good catch, this would have bitten every existing replication user. Added replica.podManagementPolicy so a release can enable Sentinel without a recreate, plus the --cascade=orphan procedure in the README for anyone taking the default.

  • loadBalancerSourceRanges (CodeRabbit) — now toYaml. Confirmed the old form rendered [10.0.0.0/8 10.1.0.0/16], which the API server rejects. The same bug exists in service.yaml and service-read.yaml; left alone here since it is unrelated to this feature, happy to send a separate PR.

  • Notes point at a Service that may not exist (CodeRabbit) — guarded on replica.sentinel.service.enabled, with the headless endpoints printed otherwise.

Not changing

  • Unauthenticated Sentinel port with auth.enabled: false (Greptile) — protected-mode no is required here, Sentinel peers connect over the pod network and protected mode rejects them when no password is set. The exposure is not specific to Sentinel: with auth disabled the Valkey port is equally open. protected-mode no is now only emitted in that case, and values.yaml states it plainly. Enabling auth secures both ports.

  • Nil auth.aclUsers.default with aclConfig-only auth (CodeRabbit) — not reachable. Sentinel requires replica.enabled, and the existing validations already stop this before any Sentinel template indexes the map:

    $ helm template t ./valkey --set replica.enabled=true --set replica.sentinel.enabled=true \
        --set auth.enabled=true --set auth.aclConfig="user default on >pw ~* &* +@all" ...
    Error: Replication user 'default' (replica.replicationUser) must be defined in auth.aclUsers.
    

    and with aclUsers set but no default, validateAuthConfig fails first. If either guard is ever relaxed, this becomes reachable and worth revisiting.

  • replicaof could hold an IP (CodeRabbit) — the chart forces sentinel resolve-hostnames yes and announce-hostnames yes and writes replica-announce-ip as the pod FQDN, so Sentinel hands out hostnames. Verified on the cluster: the restored line is replicaof valkey-2.valkey-headless.default.svc.cluster.local 6379.

  • The valkey Service load balances across all pods in Sentinel mode (CodeRabbit) — intentional, and the reason the pod-0 pin had to go: pinning leaves the write endpoint on a demoted replica after a failover. This matches how other Sentinel charts do it; clients resolve the master through Sentinel, or use the HAProxy front-end in feat(valkey): add an optional HAProxy front-end for Sentinel #235. Called out in the notes and the README.

167 unit tests, helm lint, and rendering against 1.28/1.35/1.36 all pass locally. CI is still action_required, it needs a maintainer to approve workflows for a first-time contributor.

Comment thread valkey/templates/sentinel-configmap.yaml Outdated
@Bloodraven21

Copy link
Copy Markdown
Collaborator

thanks @pat-s for the pr can you provide me an example values.yaml for testing

Signed-off-by: pat-s <patrick.schratz@gmail.com>
@pat-s
pat-s force-pushed the feat/sentinel-ha branch from ff19130 to b42995d Compare August 1, 2026 14:46
@pat-s

pat-s commented Aug 1, 2026

Copy link
Copy Markdown
Author

@Bloodraven21 sure — here is a complete example using an existing Secret (recommended):

First create the three credentials. The Sentinel password is deliberately separate from the Valkey application and replication passwords:

kubectl create secret generic valkey-users \
  --from-literal=default='replace-with-a-strong-app-password' \
  --from-literal=replicator='replace-with-a-strong-replication-password' \
  --from-literal=sentinel='replace-with-a-strong-sentinel-password'

Save this as values-sentinel.yaml:

replica:
  enabled: true
  replicas: 2 # 1 master + 2 replicas; minimum for Sentinel quorum
  persistence:
    size: 1Gi

  replicationUser: replicator

  sentinel:
    enabled: true
    quorum: 2
    passwordKey: sentinel

auth:
  enabled: true
  usersExistingSecret: valkey-users
  aclUsers:
    default:
      permissions: "~* &* +@all"
    replicator:
      permissions: >-
        ~* &* +multi +exec +ping +info +role +subscribe +publish +slaveof
        +replicaof +config|rewrite +client|setname +client|kill +script|kill
        +psync +replconf

Install from the PR checkout with:

helm install valkey ./valkey -f values-sentinel.yaml

The chart also contains an inline-password example at valkey/examples/ha-sentinel.yaml. I verified the values above with helm template against the current PR head (b42995d).

Comment thread valkey/examples/ha-sentinel.yaml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@valkey/values.yaml`:
- Around line 356-361: Update the comment beside replica.sentinel.password and
passwordKey to state that the existing secret’s sentinel key takes priority,
while the inline password is used as a fallback when that key is absent. Remove
the wording that claims the inline value is ignored, while preserving the
explanation that Sentinel credentials are independent from Valkey ACLs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ef0b6a6e-2254-4105-875c-464b85033776

📥 Commits

Reviewing files that changed from the base of the PR and between fa6cfb8 and ff19130.

📒 Files selected for processing (13)
  • valkey/README.md
  • valkey/examples/ha-sentinel.yaml
  • valkey/templates/NOTES.txt
  • valkey/templates/_helpers.tpl
  • valkey/templates/init_config.yaml
  • valkey/templates/secret.yaml
  • valkey/templates/sentinel-configmap.yaml
  • valkey/templates/sentinel-service.yaml
  • valkey/templates/statefulset.yaml
  • valkey/tests/secret_test.yaml
  • valkey/tests/sentinel_test.yaml
  • valkey/values.schema.json
  • valkey/values.yaml
🚧 Files skipped from review as they are similar to previous changes (6)
  • valkey/templates/NOTES.txt
  • valkey/templates/statefulset.yaml
  • valkey/templates/sentinel-service.yaml
  • valkey/templates/sentinel-configmap.yaml
  • valkey/values.schema.json
  • valkey/README.md

Comment thread valkey/values.yaml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@valkey/templates/sentinel-configmap.yaml`:
- Line 204: Update the SENTINEL_PASSHASH assignment in the Sentinel
configuration template to use printf with a %s format for SENTINEL_PASSWORD
before piping it to sha256sum, replacing echo -n while preserving the existing
hash extraction.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cd8aa689-6463-4a4e-9d10-97e969d63384

📥 Commits

Reviewing files that changed from the base of the PR and between ff19130 and b42995d.

📒 Files selected for processing (10)
  • valkey/README.md
  • valkey/examples/ha-sentinel.yaml
  • valkey/templates/_helpers.tpl
  • valkey/templates/init_config.yaml
  • valkey/templates/secret.yaml
  • valkey/templates/sentinel-configmap.yaml
  • valkey/tests/secret_test.yaml
  • valkey/tests/sentinel_test.yaml
  • valkey/values.schema.json
  • valkey/values.yaml
🚧 Files skipped from review as they are similar to previous changes (9)
  • valkey/values.schema.json
  • valkey/tests/secret_test.yaml
  • valkey/templates/secret.yaml
  • valkey/values.yaml
  • valkey/examples/ha-sentinel.yaml
  • valkey/tests/sentinel_test.yaml
  • valkey/templates/init_config.yaml
  • valkey/templates/_helpers.tpl
  • valkey/README.md

{{- if .Values.auth.enabled }}
# Sentinel has a dedicated identity. Valkey application credentials must
# never gain Sentinel administration privileges as a side effect.
SENTINEL_PASSHASH=$(echo -n "$SENTINEL_PASSWORD" | sha256sum | cut -f 1 -d " ")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 2 'SENTINEL_PASSHASH=.*echo -n|SENTINEL_PASSHASH=.*printf' \
  valkey/templates/sentinel-configmap.yaml

for password in 'plain-password' '-n' 'pass\word'; do
  expected="$(printf '%s' "$password" | sha256sum | cut -d ' ' -f 1)"
  actual="$(sh -c 'echo -n "$1"' sh "$password" | sha256sum | cut -d ' ' -f 1)"
  printf 'password=%s expected=%s actual=%s\n' "$password" "$expected" "$actual"
done

Repository: valkey-io/valkey-helm

Length of output: 493


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Files with SENTINEL_PASSHASH:\n'
rg -n -C 3 'SENTINEL_PASSHASH|SENTINEL_PASSWORD' valkey/templates/sentinel-configmap.yaml || true

printf '\nChart/base shell availability check (no repo execution):\n'
command -v bash sh awk sed sha256sum || true

python3 - <<'PY'
import hashlib, re
from pathlib import Path
p = Path('valkey/templates/sentinel-configmap.yaml')
text = p.read_text()
print(re.search(r'SENTINEL_PASSHASH=\$\(.*?\| sha256sum', text, re.S))
for line in text.splitlines():
    if 'SENTINEL_PASSHASH=' in line:
        print(line.strip())
PY

Repository: valkey-io/valkey-helm

Length of output: 2479


Hash the Sentinel password with printf.

echo -n can alter password bytes for option-like strings and backslashes, so the Sentinel ACL hash can differ from SENTINEL_PASSWORD. Use printf '%s' before hashing.

Proposed fix
-SENTINEL_PASSHASH=$(echo -n "$SENTINEL_PASSWORD" | sha256sum | cut -f 1 -d " ")
+SENTINEL_PASSHASH=$(printf '%s' "$SENTINEL_PASSWORD" | sha256sum | cut -f 1 -d " ")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
SENTINEL_PASSHASH=$(echo -n "$SENTINEL_PASSWORD" | sha256sum | cut -f 1 -d " ")
SENTINEL_PASSHASH=$(printf '%s' "$SENTINEL_PASSWORD" | sha256sum | cut -f 1 -d " ")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@valkey/templates/sentinel-configmap.yaml` at line 204, Update the
SENTINEL_PASSHASH assignment in the Sentinel configuration template to use
printf with a %s format for SENTINEL_PASSWORD before piping it to sha256sum,
replacing echo -n while preserving the existing hash extraction.

Signed-off-by: pat-s <patrick.schratz@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants