Skip to content

feat(redis): add affinity configuration - #2665

Open
Kostiantyn Astakhov (kastakhov) wants to merge 1 commit into
cozystack:mainfrom
kastakhov:redis-affinity
Open

Kostiantyn Astakhov (kastakhov) wants to merge 1 commit into
cozystack:mainfrom
kastakhov:redis-affinity

Conversation

@kastakhov

@kastakhov Kostiantyn Astakhov (kastakhov) commented May 17, 2026 •

Copy link
Copy Markdown

What this PR does

Adds independent Kubernetes affinity configuration for Redis and Sentinel pods through RedisFailover.spec.redis.affinity and spec.sentinel.affinity. Empty or null rules preserve operator defaults. Configured rules replace default soft pod anti-affinity; include podAntiAffinity when replica spreading is required.

Validation

  • All 89 chart tests pass with helm-unittest v1.1.2; affected standalone API package compiles.
  • Package generation with cozyvalues-gen v1.7.0 is repeatable; embedded ApplicationDefinition schema matches the generated values schema.
  • Render checks cover default/null/configured affinity and TLS on/off; Redis checks also cover separate component rules and single-replica Sentinel behavior.
  • Manifest generation and commit trailer checks pass.
  • Root make generate remains blocked by the pinned code-generator parser rejecting Go 1.27's math/rand/v2 generic method. Affected API deepcopy generation passes separately with controller-gen v0.16.4. make show was unavailable because cozyhr is not installed; offline Helm rendering passed.

Screenshots

Not applicable; no UI changes.

Downstream repositories

Release note

feat(redis): add affinity configuration for Redis and Sentinel pods.

@claude claude 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.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

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

coderabbitai Bot commented May 17, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review.

Walkthrough

This PR adds separate Kubernetes affinity settings for Redis and Sentinel pods. It adds API types and deep-copy support, exposes chart values and template rendering, updates schemas and documentation, and tests default and configured values.

Changes: Redis Pod Affinity Support

Layer / File(s) Summary
API contract and deepcopy
api/apps/v1alpha1/redis/types.go, api/apps/v1alpha1/redis/zz_generated.deepcopy.go
Adds Redis and Sentinel raw affinity fields through AffinitySpec, adds the type to ConfigSpec, and updates deep-copy methods.
Helm values and template rendering
packages/apps/redis/values.yaml, packages/apps/redis/values.schema.json, packages/apps/redis/templates/redisfailover.yaml, packages/apps/redis/tests/affinity_test.yaml, packages/apps/redis/README.md
Adds independent Redis and Sentinel affinity values, accepts arbitrary Kubernetes affinity fields, conditionally renders configured values, documents the settings, and tests absent and configured values.
ApplicationDefinition schema
packages/system/redis-rd/cozyrds/redis.yaml
Adds Redis and Sentinel affinity fields to the values schema and dashboard key order.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Merge Risk: Minimal · up to 87234

Unset affinity retains the existing scheduling behavior, while configured Redis and Sentinel affinity can be supplied separately. The change is ready to merge after normal checks.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: adding Redis and Sentinel affinity configuration.
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 unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

ℹ️ Recent review info

⚙️ Run configuration

📥 Commits

Reviewing files that changed from the base of the PR and between 83244b0 and 8723462.

📒 Files selected for processing: 8

  • api/apps/v1alpha1/redis/types.go
  • api/apps/v1alpha1/redis/zz_generated.deepcopy.go
  • packages/apps/redis/README.md
  • packages/apps/redis/templates/redisfailover.yaml
  • packages/apps/redis/tests/affinity_test.yaml
  • packages/apps/redis/values.schema.json
  • packages/apps/redis/values.yaml
  • packages/system/redis-rd/cozyrds/redis.yaml

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.

@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 introduces the ability to define Kubernetes affinity rules for Redis and Sentinel pods within the Redis application configuration. By exposing these settings, users can now exert finer control over pod placement within their clusters, improving workload distribution and scheduling requirements. The changes include necessary updates to the API types, Helm chart values, schema definitions, and the underlying resource templates.

Highlights

  • Affinity Configuration: Added support for configuring Kubernetes affinity for both Redis and Sentinel pods via the application values.
  • Schema and Documentation Updates: Updated the Redis values schema, README, and API types to include the new affinity configuration options.
  • Template Integration: Updated the RedisFailover template to correctly inject the defined affinity rules into the Redis and Sentinel pod specifications.
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.

Ignored Files
  • Ignored by pattern: **/zz_generated.*.go (1)
    • api/apps/v1alpha1/redis/zz_generated.deepcopy.go
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. ↩

@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 introduces Kubernetes affinity configuration for Redis and Sentinel pods by updating the Go API types, Helm templates, JSON schema, and documentation. The review feedback suggests marking the affinity parameter as optional in the values.yaml documentation to ensure consistency and proper Go type generation. Additionally, it is recommended to refine the Helm templates to avoid rendering empty affinity blocks in the resulting manifests, as the current default values in values.yaml cause the templates to always evaluate as true.

Comment thread packages/apps/redis/values.yaml Outdated
## @field {object} [redis] - Affinity rules for Redis pods.
## @field {object} [sentinel] - Affinity rules for Sentinel pods.

## @param {Affinity} affinity - Kubernetes affinity configuration for Redis and Sentinel pods.

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.

low

To maintain consistency with other optional fields like resources, the affinity parameter should be marked as optional in the documentation. This will also ensure that the generated Go type in api/apps/v1alpha1/redis/types.go includes the omitempty JSON tag when you run make generate.

## @param {Affinity} [affinity] - Kubernetes affinity configuration for Redis and Sentinel pods.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

code updated

Comment on lines +29 to +31
{{- with .Values.affinity.sentinel }}
affinity: {{- toYaml . | nindent 6 }}
{{- end }}

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.

low

Since affinity.sentinel defaults to {} in values.yaml, this with block will always evaluate to true and render affinity: {} in the resulting manifest. While valid Kubernetes YAML, it adds unnecessary noise. Consider checking if the object is empty before rendering, or removing the default empty objects from values.yaml if they are not strictly required for the dashboard UI.

@github-actions

Copy link
Copy Markdown

This PR has had no activity for 60 days and was marked lifecycle/stale.
It will be closed in 14 days unless commented or labelled lifecycle/frozen.

@github-actions github-actions Bot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale label Jul 17, 2026

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.

Same feature as your rabbitmq PR and the same verified good news: the affinity does reach the pods (RedisFailover.spec.redis.affinity and spec.sentinel.affinity both exist in the vendored operator CRD, and rendering the branch puts the values at those paths), and the generated artifacts genuinely regenerate byte for byte, so the bot comments claiming they were hand-edited are wrong.

Three things to fix here that do not apply to the rabbitmq one.

The template crashes on an explicit null. helm template --set affinity=null fails with nil pointer evaluating interface {}.sentinel, because packages/apps/redis/templates/redisfailover.yaml:29 does {{- with .Values.affinity.sentinel }} and dereferences the parent before testing it. The rabbitmq chart is immune because its with sits on the parent itself. (.Values.affinity).sentinel fixes it. I agree this is hard to reach through the Application path, since the CRD's own typing should reject an explicit null, but it is one character of parentheses and the failure mode is a render crash.

The fields should be *RawExtension rather than the value form, which is what your rabbitmq PR already does. omitempty is a no-op on a struct, so as written this always emits affinity with two nulls inside instead of omitting it. Your other PR has the right spelling; matching it here also lines this up with the third affinity PR, where I have asked for the same change.

api/apps/v1alpha1/redis/types.go:50 exports a type named Affinity that is not the Kubernetes corev1.Affinity but a two-field wrapper holding the redis and sentinel rules. In a module that gets published and imported by tenants, that name will be read as the Kubernetes one every time. Something like AffinitySpec, or a name mentioning the split, would avoid the collision.

As on the other PR: no Signed-off-by on the commits, which is a hard merge gate, and a mechanical conflict with main that a rebase plus the package's make generate should clear. The field descriptions would also benefit from naming the expected shape, since preserve-unknown-fields gives the dashboard nothing else to show.

On ordering, so you are not blocked by the queue: several other open PRs touch this chart's values.yaml, but every overlap is in artifacts that regenerate deterministically, so it is merge ordering rather than a conflict of intent. Whichever lands first, the rest rebase and regenerate.

And the same note as the other one: lifecycle/stale puts this on a close timer, so it needs a nudge if you still want it.

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.

One more thing worth knowing about this field, which I checked in the operator's source and which belongs in the field description rather than in the code.

The operator does not merge what you pass with its own scheduling rules. Its helper returns the user-supplied affinity verbatim when one is set, and only when none is set does it synthesize a soft pod anti-affinity, weight 100 on kubernetes.io/hostname, that spreads the replicas across nodes.

So a user who sets this field only to express a node preference, which is the most common reason to reach for affinity at all, silently loses replica spreading on what is meant to be a highly available service. Nothing warns them, and the symptom only appears when a node goes down and takes more than one replica with it.

Documenting that in the field description is enough, ideally with the concrete advice that anyone setting this should include a podAntiAffinity themselves unless they specifically want replicas co-located. The rabbitmq PR has no equivalent trap, since that operator passes a nil straight through and adds no default of its own, which is another reason the two field descriptions should not simply be copies of each other.

@kastakhov

Copy link
Copy Markdown
Author

Hi Aleksei Sviridkin (@lexfrei), I updated PR and addressed your concerns

@github-actions github-actions Bot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale label Jul 30, 2026
@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

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.

Kostiantyn Astakhov (@kastakhov) NOT LGTM. Everything from my July reviews is fixed. What is left is a rebase and a test.

The conflict with main is only in the generated packages/system/redis-rd/cozyrds/redis.yaml. Rebase and rerun make generate in packages/apps/redis with cozyvalues-gen v1.7.0, which is what CI uses. On my trial merge that regenerates the RD with affinity in the schema and in keysOrder, and the other generated files come out identical to what git merges on its own. The render is right: spec.redis.affinity and spec.sentinel.affinity get the values, and the default, affinity: null and affinity.redis: null render no affinity key, so the operator keeps its own default spreading.

Since your last push, main added helm-unittest tests for this chart in packages/apps/redis/tests/, and none of them covers affinity. I pointed the redis block at (.Values.affinity).sentinel and all 48 tests still passed, so swapped or dropped wiring would ship unnoticed. One small test file is enough: defaults render no affinity under either spec.redis or spec.sentinel, and each value lands only under its own component.

CI on this head tells nothing yet. The August runs failed before any job started because the branch could not be merged, and E2E Tests never ran. They will run after the rebase.

@lexfrei

Copy link
Copy Markdown
Contributor

Kostiantyn Astakhov (@kastakhov) my change request from 2026-09-29 is still open and there has been no activity here since August. Is this still something you want to finish? If there is no activity in the next two weeks, the stale bot will close it; reopening later is always fine.

@lexfrei Aleksei Sviridkin (lexfrei) added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale label Oct 10, 2026
@kastakhov

Kostiantyn Astakhov (kastakhov) commented Oct 21, 2026 •

Copy link
Copy Markdown
Author

I'd like to close this PR instead as I don't have time to play catch-up with your changes.
I prepared this PR in my free time, and it's not like massive project refactoring, but small improvement, and PR was untouched by Cozy team for a few months. Okay, you reviewed it and I appreciate it, but c'mon, this PR was left behind for another 2 months since I performed requested changes. Now you're asking me again to catch-up your code and wait for another 2-3 months? If feels like contributing is not welcome here.

@kastakhov

Copy link
Copy Markdown
Author

I will rebase the code one more time in this and in the sibling PR this week, hope this time it will be checked not after another 2 months.

@github-actions github-actions Bot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale label Oct 22, 2026
@github-actions github-actions Bot added size/L This PR changes 100-499 lines, ignoring generated files and removed size/M This PR changes 30-99 lines, ignoring generated files labels Oct 22, 2026

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.

Kostiantyn Astakhov (@kastakhov) LGTM. The rebase and affinity tests address my previous change request. I ran the 71 chart tests and checked separate Redis and Sentinel settings, including null values and TLS. Swapping either component's input makes the new test fail.

Functional CI has not run on this head; the passing checks only cover metadata.

Please link a Terraform provider follow-up in the downstream checklist; its schema and mappings do not expose the new affinity fields yet.

Signed-off-by: kastakhov <[email protected]>
Assisted-by: LLM
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/feature Categorizes issue or PR as related to a new feature size/L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants