fix: sentinel pdbspec by Flo4604 · Pull Request #5375 · unkeyed/unkey

@Flo4604

What does this PR do?

Improves PodDisruptionBudget configuration for sentinel deployments by implementing replica-aware disruption policies. Single-replica sentinels now use MinAvailable=1 to prevent eviction of the last pod during voluntary disruptions like node drains, while multi-replica sentinels use MaxUnavailable=1 to allow rolling disruptions while maintaining majority availability.

Fixes #4873

If there is not an issue for this, please create one first. This is used to tracking purposes and also helps us understand why this PR exists

Type of change

  • Enhancement (small improvements)
  • Bug fix (non-breaking change which fixes an issue)
  • Chore (refactoring code, technical debt, workflow improvements)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How should this be tested?

  • Deploy a single-replica sentinel and verify PDB uses MinAvailable=1
  • Deploy a multi-replica sentinel and verify PDB uses MaxUnavailable=1
  • Test node drain scenarios to ensure single-replica sentinels are protected from eviction
  • Test rolling updates on multi-replica sentinels to ensure proper disruption handling

Checklist

Required

  • Filled out the "How to test" section in this PR
  • Read Contributing Guide
  • Self-reviewed my own code
  • Commented on my code in hard-to-understand areas
  • Ran pnpm build
  • Ran pnpm fmt
  • Ran make fmt on /go directory
  • Checked for warnings, there are none
  • Removed all console.logs
  • Merged the latest changes from main onto my branch with git pull origin main
  • My changes don't cause any responsiveness issues

Appreciated

  • If a UI change was made: Added a screen recording or screenshots to this PR
  • Updated the Unkey Docs if changes were necessary

@Flo4604

@Flo4604 Graphite App

@vercel

@Flo4604 Flo4604 marked this pull request as ready for review

March 18, 2026 16:04

@coderabbitai

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: dfd928ea-4649-4dad-a754-a0ce051ab441

📥 Commits

Reviewing files that changed from the base of the PR and between d6e820c and f82a9a6.

📒 Files selected for processing (1)
  • svc/krane/internal/sentinel/apply.go

📝 Walkthrough

Walkthrough

Modifies PodDisruptionBudget creation in ensurePDBExists to choose a PDB spec based on replica count: use MinAvailable: 1 for replicas ≤ 1, and MaxUnavailable: 1 for replicas > 1, selecting sentinel pods via label selector.

Changes

Cohort / File(s) Summary
PodDisruptionBudget Logic
svc/krane/internal/sentinel/apply.go
Replaces hardcoded PDB spec with conditional pdbSpec: if replicas ≤ 1 the desired PDB uses MinAvailable: 1; if replicas > 1 it uses MaxUnavailable: 1. Selector remains targeted at sentinel pods.

Sequence Diagram(s)

sequenceDiagram
    participant Controller as Controller\n(sentinel apply)
    participant K8sAPI as Kubernetes API
    participant PDB as PodDisruptionBudget

    Controller->>Controller: read desired replica count
    alt replicas ≤ 1
        Controller->>Controller: construct PDB with MinAvailable: 1 + selector
    else replicas > 1
        Controller->>Controller: construct PDB with MaxUnavailable: 1 + selector
    end
    Controller->>K8sAPI: apply desired PDB
    K8sAPI->>PDB: create/update PDB resource
    K8sAPI-->>Controller: response (created/updated)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'fix: sentinel pdbspec' is vague and uses abbreviations ('pdbspec') that lack clarity about the actual change. Consider a more descriptive title like 'fix: sentinel PodDisruptionBudget configuration for replica-aware policies' to better convey the actual change.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The PR description is mostly complete with all required sections filled: What does this PR do, Type of change marked appropriately, testing instructions provided, and checklist items included.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 03-18-fix_sentinel_pdbspec
📝 Coding Plan
  • Generate coding plan for human review comments

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.11.3)

Command failed


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

ogzhanolguncu

chronark

coderabbitai[bot]

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 the current code and only fix it if needed.

Inline comments:
In `@svc/krane/internal/sentinel/apply.go`:
- Around line 386-401: The PodDisruptionBudgetSpec literals in the Apply flow
are non-exhaustive; ensure you build a single policyv1.PodDisruptionBudgetSpec
with all required fields (explicitly set UnhealthyPodEvictionPolicy and both
MinAvailable/MaxUnavailable pointers) and then conditionally set the
availability constraint based on sentinel.GetReplicas()—for example, create
pdbSpec with Selector and UnhealthyPodEvictionPolicy initialized, set
MinAvailable = nil and MaxUnavailable = nil initially, then if
sentinel.GetReplicas() <= 1 assign MinAvailable = ptr.P(intstr.FromInt(1)) else
assign MaxUnavailable = ptr.P(intstr.FromInt(1)); keep using
labels.New().SentinelID(sentinel.GetSentinelId()) for the Selector so
exhaustruct is satisfied and the downstream desired variable can still use
//nolint:exhaustruct.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d57485d0-391e-47d5-aa0a-cbe5de7f233a

📥 Commits

Reviewing files that changed from the base of the PR and between 707ec8e and d6e820c.

📒 Files selected for processing (1)
  • svc/krane/internal/sentinel/apply.go

@chronark

@chronark

@chronark

@Flo4604

@chronark chronark deleted the 03-18-fix_sentinel_pdbspec branch

March 18, 2026 18:49