Skip to content

fix(etcd): pin tenant etcd to v3.5.31 to restore consistent watches - #3122

Merged
Aleksei Sviridkin (lexfrei) merged 2 commits into
mainfrom
fix/etcd-operator-watch-progress
Jun 29, 2026
Merged

fix(etcd): pin tenant etcd to v3.5.31 to restore consistent watches#3122
Aleksei Sviridkin (lexfrei) merged 2 commits into
mainfrom
fix/etcd-operator-watch-progress

Conversation

@lexfrei

@lexfrei Aleksei Sviridkin (lexfrei) commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Tenant Kubernetes control planes get their etcd from the extra/etcd chart, which creates an EtcdCluster (etcd.aenix.io/v1alpha1) reconciled by etcd-operator v0.4.5. That operator hardcodes the etcd image to quay.io/coreos/etcd:v3.5.12, and the v1alpha1 CRD exposes no version field, so every tenant etcd runs 3.5.12.

kube-apiserver only enables the RequestWatchProgress storage feature on etcd >= 3.5.13 (or >= 3.4.31). Kubernetes >= 1.31 enables ConsistentListFromCache — locked-to-true in 1.35 — which depends on it. On etcd 3.5.12 every consistent watch therefore fails inside the stream with HTTP 500 (the required storage feature RequestWatchProgress is disabled), which breaks watch-based clients of aggregated APIs in modern (k8s 1.35) tenants.

This pins the etcd container image to a >= 3.5.13 patch release (v3.5.31) by setting image on the etcd container in the EtcdCluster's spec.podTemplate.spec. etcd-operator v0.4.5 strategically merges podTemplate.spec over its generated pod spec (matched by container name), so the override takes effect with no operator change — the same mechanism the chart already uses for the metrics port, probes, and resources. It restores consistent watches without waiting on the etcd-operator v1alpha2 migration (#2859), which is the longer-term fix.

A helm-unittest suite asserts the etcd container carries the pinned image and is no longer left on the operator default v3.5.12.

Addresses #3080.

Upgrade impact

On merge, etcd-operator reconciles every existing tenant EtcdCluster and rolls its StatefulSet from 3.5.12 to 3.5.31. This is a safe in-minor rolling patch upgrade (no etcd storage-format change, quorum preserved by the operator's rolling strategy), so expect a brief, sequential etcd pod restart per tenant and no data migration.

Release note

fix(etcd): pin tenant etcd to v3.5.31 so kube-apiserver can enable RequestWatchProgress (consistent watches) on Kubernetes 1.35 tenants

Summary by CodeRabbit

  • Bug Fixes
    • Pinned the bundled etcd image to quay.io/coreos/etcd:v3.5.31 to improve compatibility with Kubernetes watch-related storage behavior.
    • Prevented deployments from reverting to the older default etcd image.
  • Tests
    • Added a new test suite to verify the template uses the expected pinned etcd image and blocks regressions.
  • Chores
    • Updated dependency automation to recognize and manage the pinned etcd image version.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a compatibility issue where tenant Kubernetes control planes running on newer versions (1.31+) were failing to perform consistent watches due to an outdated etcd version (v3.5.12). By strategically overriding the etcd image in the EtcdCluster pod template, the change ensures that the required RequestWatchProgress storage feature is available, restoring stability for watch-based clients without requiring immediate changes to the underlying etcd-operator.

Highlights

  • Etcd Image Pinning: Pinned the etcd container image to v3.5.31 in the EtcdCluster spec to ensure compatibility with modern Kubernetes requirements.
  • Consistent Watch Support: Enabled the RequestWatchProgress storage feature by upgrading the etcd version, resolving HTTP 500 errors during consistent watches in Kubernetes 1.35 tenants.
  • Automated Testing: Added a helm-unittest suite to verify that the etcd container image is correctly overridden and no longer defaults to the outdated v3.5.12 version.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment Gemini (@gemini-code-assist) Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions Bot added size/M This PR changes 30-99 lines, ignoring generated files area/database Issues or PRs related to managed databases (postgres, mariadb, redis, etcd, kafka, clickhouse) kind/bug Categorizes issue or PR as related to a bug labels Jun 28, 2026
@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The etcd cluster template pins the etcd container image to quay.io/coreos/etcd:v3.5.31, a test suite checks the rendered image, and Renovate is configured to track that tag with a custom regex manager.

Changes

etcd image pin and tracking

Layer / File(s) Summary
Image pin in cluster template
packages/extra/etcd/templates/etcd-cluster.yaml
Sets the etcd pod template image to quay.io/coreos/etcd:v3.5.31 with a comment.
Template test suite
packages/extra/etcd/tests/etcd-cluster_test.yaml
Renders the etcd cluster template with an empty _cluster context and asserts the etcd image is pinned above v3.5.13 and not equal to v3.5.12.
Renovate regex manager for etcd image
.github/renovate.json
Enables custom.regex and adds a custom manager that matches the pinned etcd image tag in the cluster template and uses the Docker datasource.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

Suggested reviewers

  • kvaps
  • lllamnyp
  • androndo
  • IvanHunters
  • sircthulhu
  • myasnikovdaniil

Poem

🐇 I nibbled the old tag, now it’s out of sight,
v3.5.31 hops in, all tidy and right.
Watches stay steady, the cluster stays keen,
And Renovate knows where the new tag has been.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately describes the main change: pinning tenant etcd to v3.5.31 to fix watch consistency.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/etcd-operator-watch-progress

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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request overrides the default etcd image in the etcd-cluster template to quay.io/coreos/etcd:v3.5.31 to support consistent watches (which require etcd >= 3.5.13) and adds corresponding unit tests. However, the review feedback correctly points out that v3.5.31 is a non-existent image tag (likely a typo for v3.5.13 or v3.4.31) that will cause image pull failures. The reviewer suggests correcting the image tag to a valid version like v3.5.13 in both the template and the test suite.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

# in 1.35), so on etcd 3.5.12 every consistent watch fails inside the
# stream with "the required storage feature RequestWatchProgress is
# disabled" (HTTP 500). Pinning a >= 3.5.13 patch release restores it.
image: quay.io/coreos/etcd:v3.5.31

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

The etcd image version v3.5.31 does not exist. The etcd 3.5 release branch has not reached .31 (the latest release is around v3.5.17). This is likely a transposition typo of v3.5.13 (the minimum version required for RequestWatchProgress) or a mix-up with v3.4.31. Using a non-existent image tag will cause ErrImagePull / ImagePullBackOff and completely break the tenant etcd cluster. Please use a valid existing version, such as v3.5.13 or a newer stable patch release like v3.5.17.

        image: quay.io/coreos/etcd:v3.5.13

value: etcd
- equal:
path: spec.podTemplate.spec.containers[0].image
value: quay.io/coreos/etcd:v3.5.31

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

Update the expected image value in the test to match the corrected etcd version (e.g., v3.5.13 or v3.5.17) to ensure the test suite passes.

          value: quay.io/coreos/etcd:v3.5.13

@lexfrei
Aleksei Sviridkin (lexfrei) force-pushed the fix/etcd-operator-watch-progress branch from 147fe85 to 78cf9e1 Compare June 28, 2026 00:45
etcd-operator v0.4.5 hardcodes quay.io/coreos/etcd:v3.5.12 and the
v1alpha1 EtcdCluster CRD exposes no version field, so the tenant
control-plane etcd runs 3.5.12. kube-apiserver only enables the
RequestWatchProgress storage feature on etcd >= 3.5.13 / >= 3.4.31, and
Kubernetes >= 1.31 enables ConsistentListFromCache (locked-to-true in
1.35), which depends on it. On etcd 3.5.12 every consistent watch fails
inside the stream with HTTP 500 ("the required storage feature
RequestWatchProgress is disabled"), breaking watch-based clients of
aggregated APIs in modern tenants.

Override the etcd container image through spec.podTemplate.spec, which
the operator strategically merges over its generated pod spec (matched
by container name), pinning a >= 3.5.13 patch release. This restores
consistent watches without waiting on the etcd-operator v1alpha2
migration.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
The etcd image in the extra/etcd EtcdCluster podTemplate is a hardcoded
string that overrides etcd-operator v0.4.5's baked-in default. None of
the enabled managers (gomod, dockerfile, github-actions) can see a
literal image string in a Helm template, so the pin would silently age
- and etcd 3.5.x releases are overwhelmingly security fixes.

Add a custom.regex manager that matches the image line and resolves
updates from the docker datasource, so future etcd patch releases
surface as Renovate PRs like any other tracked dependency.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>

@myasnikovdaniil myasnikovdaniil left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM.

Two notes for anyone weighing the existing bot comments:

  • quay.io/coreos/etcd:v3.5.31 does exist — it is a multi-arch manifest list on quay.io (amd64/arm64/ppc64le/s390x), published 2026-06-01, verified against the registry API. The "version does not exist / latest is ~v3.5.17" comments are out of date and should not block this (see inline).
  • The podTemplate image override actually takes effect with etcd-operator v0.4.5 — it strategic-merges podTemplate.spec over the operator-generated pod spec, matched by container name, so this image wins over the hardcoded default (see inline).

The pinned-floor test (>= 3.5.13, excludes v3.5.12) and the Renovate custom manager are the right shape. The rolling restart of every tenant etcd on merge is documented in the description (safe in-minor, quorum-preserving). No blockers; E2E green.

# in 1.35), so on etcd 3.5.12 every consistent watch fails inside the
# stream with "the required storage feature RequestWatchProgress is
# disabled" (HTTP 500). Pinning a >= 3.5.13 patch release restores it.
image: quay.io/coreos/etcd:v3.5.31

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Confirmed valid — this does not need changing. quay.io/coreos/etcd:v3.5.31 exists on quay.io as a multi-arch manifest list (amd64/arm64/ppc64le/s390x), published 2026-06-01, verified against the registry API. The "tag does not exist / latest is ~v3.5.17" comments predate the release.

The override also takes effect: the v1alpha1 EtcdCluster CRD exposes no spec.image/spec.version, so podTemplate is the only lever. etcd-operator v0.4.5 builds the etcd container with its hardcoded default and then strategic-merges podTemplate.spec over it (matched by container name etcd), so this image wins and the operator does not re-assert its default — the same mechanism already used here for the metrics port, probes, and resources.

@lexfrei
Aleksei Sviridkin (lexfrei) merged commit 4404c5c into main Jun 29, 2026
13 checks passed
@lexfrei
Aleksei Sviridkin (lexfrei) deleted the fix/etcd-operator-watch-progress branch June 29, 2026 12:46
Andrey Kolkov (androndo) added a commit that referenced this pull request Jun 29, 2026
…rsion

Signed-off-by: Andrey Kolkov <androndo@gmail.com>
myasnikovdaniil pushed a commit that referenced this pull request Jun 30, 2026
…rsion

Signed-off-by: Andrey Kolkov <androndo@gmail.com>
myasnikovdaniil pushed a commit that referenced this pull request Jun 30, 2026
…rsion

Signed-off-by: Andrey Kolkov <androndo@gmail.com>
Timofei Larkin (lllamnyp) pushed a commit that referenced this pull request Jul 1, 2026
…rsion

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

Labels

area/database Issues or PRs related to managed databases (postgres, mariadb, redis, etcd, kafka, clickhouse) kind/bug Categorizes issue or PR as related to a bug size/M This PR changes 30-99 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants