Skip to content

fix: tolerate transient API latency in leader election - #333

Open
obrienrobert wants to merge 1 commit into
redhat-data-and-ai:mainfrom
obrienrobert:leader-election-fix
Open

fix: tolerate transient API latency in leader election#333
obrienrobert wants to merge 1 commit into
redhat-data-and-ai:mainfrom
obrienrobert:leader-election-fix

Conversation

@obrienrobert

@obrienrobert obrienrobert commented Aug 7, 2026

Copy link
Copy Markdown

Changes

📝 Description

What changed?

Leader election: LeaseDuration=60s, RenewDeadline=40s, RetryPeriod=5s (from defaults 15s/10s/2s)
Probe timeoutSeconds=5 (from default 1s)

Why is this change needed?

Usernaut restarts frequently due to leader election lost after brief API server latency spikes (context deadline exceeded on lease renewal). As a single-replica operator, the aggressive HA defaults provide no failover benefit - they just make the pod crash-prone. Correlated failures across sibling operators on the same node confirm the trigger is cluster-side, but Usernaut's intolerance is the reason it crashes.

Dependencies

  • N/A

🧪 Testing

Test Coverage

Performance Impact

  • N/A

🚀 Deployment

Deploy Steps

  1. N/A

Prerequisites

  • N/A

Post-Deployment Monitoring

  • N/A

Rollback Plan

  • N/A

⚠️ Breaking Changes

  • This PR contains breaking changes
  • Migration guide provided (if applicable)

Details:

  • N/A

⚙️ Configuration Changes

  • N/A

✅ Developer Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added positive and negative tests that prove my fix is effective or that my feature works
  • Relevant documentation (README, tech specs, etc.) has been added or updated
  • All CI/CD checks are passing

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e5e7426e-8140-42d4-b2d2-9052de0e5b26

📥 Commits

Reviewing files that changed from the base of the PR and between 76324fa and 18a297c.

📒 Files selected for processing (1)
  • cmd/main.go

📝 Walkthrough

Summary by CodeRabbit

  • Reliability Improvements
    • Configured explicit leader-election timing to support predictable failover behavior.
    • Added 5-second timeouts to liveness and readiness health checks, helping health monitoring respond promptly.
    • Improved manager configuration handling for more consistent startup and operation.

Walkthrough

The manager now uses stored Kubernetes configuration and explicit leader-election timings. Liveness and readiness probes now have five-second timeouts.

Changes

Manager runtime tuning

Layer / File(s) Summary
Client and leader-election configuration
cmd/main.go
The manager stores Kubernetes configuration and sets leader-election lease, renewal, and retry durations to 60, 40, and 5 seconds.
Health probe timeouts
config/manager/manager.yaml
The liveness and readiness probes now use five-second timeouts.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 18a29

The PR adjusts leader-election timing, client rate limits, and probe timeout to tolerate transient API latency. No actionable merge-blocking risk remains based on the supplied evidence.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly identifies the main change: increasing tolerance for transient API latency during leader election.
Description check ✅ Passed The description explains the change and reason clearly, but it omits test details and incorrectly lists configuration changes as N/A.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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: 13

🧹 Nitpick comments (1)
appconfig/rhplatformtest.yaml (1)

62-67: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the placeholder Snowflake backend.

The entry is disabled and carries an inline dummy pat: "fdfdfs". Other environments reference secrets with the file| prefix. Delete this block, or align it with the rhsandbox naming and the file| secret reference used in appconfig/default.yaml.

🤖 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 `@appconfig/rhplatformtest.yaml` around lines 62 - 67, Remove the disabled
placeholder Snowflake backend named test, including its dummy pat and connection
settings; do not leave the inline secret in rhplatformtest.yaml.
🤖 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 @.gitlab-ci.yml:
- Around line 202-211: Update the image-publishing job rules or push commands so
merge request pipelines never push or overwrite "${IMAGE_URL}:latest". Preserve
latest publishing for the default branch and tag pipelines, while allowing merge
request pipelines to skip that shared-tag push.
- Line 196: Update the buildah login command in the CI configuration to remove
the password command-line argument and pass REGISTRY_PASSWORD through standard
input using --password-stdin, while preserving the existing registry username
and endpoint.
- Around line 251-277: Update the rules for deploy-operator-rhpreprod and
deploy-operator-rhprod so the rule matching CI_COMMIT_TAG explicitly sets when:
manual. Remove the separate job-level when: manual declarations, preserving
manual approval for tagged deployments.

In `@appconfig/rhplatformtest.yaml`:
- Around line 3-4: Update the consolidated Dataverse pattern and output mapping
so the tenant ID is captured and substituted into the group name: either make
the Dataverse-type alternation non-capturing while retaining $1, or keep both
captures and change output to $2_group.

In `@appconfig/rhpreprod.yaml`:
- Line 83: The offboardUserExclusionListConfigPath configuration uses a mutable
main-branch URL in both environments; update appconfig/rhpreprod.yaml lines
83-83 and appconfig/rhprod.yaml lines 101-101 to load from the usernaut-config
ConfigMap or pin the URL to a released tag, applying the same stable source in
both files.

In `@appconfig/rhprod.yaml`:
- Around line 21-25: Update the production Redis configuration under the redis
key so it no longer references the preproduction cache endpoint: replace host
with the correct production endpoint, or remove the entire redis block since the
current driver is memory.
- Around line 97-98: Update the production CORS configuration under
cors.allowed_origins to remove both localhost entries and retain only the
production Route hostname.

In `@config/default/overlays/rhpreprod/patches/manager-deployment-env.yaml`:
- Around line 10-13: Update the base manager Deployment in manager.yaml to set
the container security context field readOnlyRootFilesystem: true, then add
explicit writable volume mounts and corresponding volumes only for runtime paths
the manager requires. Preserve the existing read-only config and secret mounts
and restrictive security settings.

In `@config/manager/manager.yaml`:
- Around line 93-106: Update the manager’s livenessProbe settings to reduce the
failure-recovery window: lower its initialDelaySeconds and/or failureThreshold,
or add a startupProbe to preserve slow-start tolerance while allowing wedged
instances to restart within the availability target. Keep the readinessProbe’s
higher tolerance unchanged unless required otherwise.

In
`@config/mpp-manual/tenant-namespace/overlays/usernaut-rhplatformtest/tenant-egress.yaml`:
- Around line 7-10: Replace the unrestricted cidrSelector in the TenantEgress
egress rule with the specific CIDR ranges required by Usernaut integrations. If
unrestricted access is intentionally allowed for this platform-test environment,
document that exception and scope enforcement exclusively to this environment.

In `@Makefile`:
- Around line 237-240: Update the configure-mpp-all target so its name matches
its behavior: either rename it to configure-mpp-rhprod and update all
references, or make it aggregate the configure-mpp-rhplatformtest,
configure-mpp-rhpreprod, and configure-mpp-rhprod targets so every environment
is configured.
- Around line 248-252: Update the configure-usernaut-rhpreprod target
declaration to include the kustomize prerequisite, matching the prerequisite
pattern used by the configure-mpp-* targets, while leaving its existing recipe
commands unchanged.

In `@scripts/configmap.sh`:
- Line 5: Update the kubectl invocation in the script to quote the
environment-derived --from-file source and -n namespace arguments, preventing
word splitting and glob expansion. Add validation near the script entry point to
reject unset ENVIRONMENT values and unsupported environment names before
constructing the configmap command, while preserving the existing apply flow.

---

Nitpick comments:
In `@appconfig/rhplatformtest.yaml`:
- Around line 62-67: Remove the disabled placeholder Snowflake backend named
test, including its dummy pat and connection settings; do not leave the inline
secret in rhplatformtest.yaml.
🪄 Autofix

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: ebaca8cd-9317-428a-9fc6-b9ff4e12c47d

📥 Commits

Reviewing files that changed from the base of the PR and between edf1baa and fe950ae.

📒 Files selected for processing (41)
  • .gitlab-ci.yml
  • CODEOWNERS
  • Dockerfile.redhat
  • Makefile
  • appconfig/default.yaml
  • appconfig/exclusionlist.yaml
  • appconfig/rhplatformtest.yaml
  • appconfig/rhpreprod.yaml
  • appconfig/rhprod.yaml
  • cmd/main.go
  • config/default/base/kustomization.yaml
  • config/default/overlays/rhpreprod/kustomization.yaml
  • config/default/overlays/rhpreprod/patches/manager-deployment-env.yaml
  • config/default/overlays/rhpreprod/patches/route-env.yaml
  • config/default/overlays/rhprod/kustomization.yaml
  • config/default/overlays/rhprod/patches/route-env.yaml
  • config/groups/dataverse-platform-rhplatformtestaccess.yaml
  • config/manager/kustomization.yaml
  • config/manager/manager.yaml
  • config/manager/route.yaml
  • config/manager/svc.yaml
  • config/manifests/overlays/rhpreprod/kustomization.yaml
  • config/manual-rbac/base/secret.yaml
  • config/manual-rbac/base/serviceaccount.yaml
  • config/manual-rbac/overlays/usernaut-rhplatformtest/admin-rolebinding.yaml
  • config/manual-rbac/overlays/usernaut-rhpreprod/admin-rolebinding.yaml
  • config/manual-rbac/overlays/usernaut-rhpreprod/kustomization.yaml
  • config/manual-rbac/overlays/usernaut-rhprod/admin-rolebinding.yaml
  • config/mpp-manual/tenant-namespace/base/kustomization.yaml
  • config/mpp-manual/tenant-namespace/base/tenant-namespace.yaml
  • config/mpp-manual/tenant-namespace/overlays/usernaut-rhplatformtest/kustomization.yaml
  • config/mpp-manual/tenant-namespace/overlays/usernaut-rhplatformtest/tenant-egress.yaml
  • config/mpp-manual/tenant-namespace/overlays/usernaut-rhpreprod/kustomization.yaml
  • config/mpp-manual/tenant-namespace/overlays/usernaut-rhprod/kustomization.yaml
  • config/rbac-admin-sa/base/rolebinding.yaml
  • config/rbac-admin-sa/overlays/all/patches/usernaut-admin-role-patch.yaml
  • config/redis/kustomization.yaml
  • config/redis/redis.yaml
  • config/redis/service.yaml
  • config/samples/dataverse-platform-preprodusernaut.yaml
  • scripts/configmap.sh
💤 Files with no reviewable changes (5)
  • config/redis/service.yaml
  • config/redis/kustomization.yaml
  • config/redis/redis.yaml
  • config/rbac-admin-sa/overlays/all/patches/usernaut-admin-role-patch.yaml
  • config/default/base/kustomization.yaml

Comment thread .gitlab-ci.yml Outdated
Comment thread .gitlab-ci.yml Outdated
Comment thread .gitlab-ci.yml Outdated
Comment thread appconfig/rhplatformtest.yaml Outdated
Comment thread appconfig/rhpreprod.yaml Outdated
Comment thread config/manager/manager.yaml Outdated
Comment thread Makefile Outdated
Comment thread Makefile Outdated
Comment thread scripts/configmap.sh Outdated
@obrienrobert

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@obrienrobert
obrienrobert force-pushed the leader-election-fix branch 2 times, most recently from 76324fa to 18462d5 Compare August 7, 2026 22:39
@obrienrobert obrienrobert changed the title fix: Leader election fix fix: tolerate transient API latency in leader election Aug 8, 2026
@obrienrobert

Copy link
Copy Markdown
Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
⚠️ Action not completed

No files to review.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Comment thread cmd/main.go Outdated
Usernaut runs as a single replica with --leader-elect, but was using
controller-runtime defaults (15s/10s/2s) designed for fast multi-replica
failover. Brief API server stalls caused lease renewal to timeout,
crashing the manager and triggering daily Gatus alerts.

- Set LeaseDuration=60s, RenewDeadline=40s, RetryPeriod=5s
- Add timeoutSeconds=5 to liveness/readiness probes

Ref: DATA-7347

Signed-off-by: Robert O'Brien <robrien@redhat.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