{"id":38877240,"url":"https://github.com/containerinfra/kube-deployment-coordinator","last_synced_at":"2026-01-17T14:37:07.980Z","repository":{"id":329291293,"uuid":"1118959195","full_name":"containerinfra/kube-deployment-coordinator","owner":"containerinfra","description":"kube-deployment-coordinator","archived":false,"fork":false,"pushed_at":"2026-01-13T04:55:55.000Z","size":135,"stargazers_count":1,"open_issues_count":5,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-13T05:10:45.629Z","etag":null,"topics":["golang","kubebuilder","kubernetes"],"latest_commit_sha":null,"homepage":"https://containerinfra.nl","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/containerinfra.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-18T14:31:24.000Z","updated_at":"2025-12-30T15:01:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/containerinfra/kube-deployment-coordinator","commit_stats":null,"previous_names":["containerinfra/kube-deployment-coordinator"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/containerinfra/kube-deployment-coordinator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/containerinfra%2Fkube-deployment-coordinator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/containerinfra%2Fkube-deployment-coordinator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/containerinfra%2Fkube-deployment-coordinator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/containerinfra%2Fkube-deployment-coordinator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/containerinfra","download_url":"https://codeload.github.com/containerinfra/kube-deployment-coordinator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/containerinfra%2Fkube-deployment-coordinator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28510108,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T13:38:16.342Z","status":"ssl_error","status_checked_at":"2026-01-17T13:37:44.060Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["golang","kubebuilder","kubernetes"],"created_at":"2026-01-17T14:37:07.891Z","updated_at":"2026-01-17T14:37:07.965Z","avatar_url":"https://github.com/containerinfra.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# kube-deployment-coordinator\n\nA Kubernetes controller that coordinates the rollout of multiple deployments to ensure only one deployment rolls out at a time. This prevents resource contention and ensures predictable, sequential rollouts across related deployments.\n\n\u003e **Note:** This project targets a niche coordination problem in Kubernetes: ensuring _sequential rollouts_ across multiple Deployments that _should not_ be updated in parallel. \n\u003e \n\u003e Most users of Kubernetes do **not** need this—native Deployments already support rolling updates, readiness checks, and gradual rollout. If you are not explicitly running multiple Deployments for the same app (for example, with different network or node configurations) and struggling with them being updated at the same time (usually by GitOps tools), you are likely solving the wrong problem, or employing an anti-pattern in your architecture.  \n\u003e \n\u003e If this situation fits your use-case, you'll know; otherwise, consider revisiting your deployment strategy before adopting this solution.\n\n## Overview\n\nThe `kube-deployment-coordinator` is a Kubernetes operator that manages the coordinated rollout of deployments using a Custom Resource Definition (CRD). It ensures that deployments matching a label selector roll out one at a time, preventing simultaneous rollouts that could cause resource contention or service disruption.\n\n### Key Features\n\n- Rolls out deployments one at a time\n- Coordinates deployments using label selectors\n- Waits for deployments to be ready before continuing\n- Tracks rollout progress and status\n- Pauses non-active deployments automatically\n- Records Kubernetes events\n\n## Architecture\n\nThe following diagram illustrates how `kube-deployment-coordinator` operates within a Kubernetes cluster:\n\n```mermaid\ngraph TB\n    subgraph \"Kubernetes API Server\"\n        API[API Server]\n    end\n\n    subgraph \"kube-deployment-coordinator-system namespace\"\n        Controller[Controller Pod\u003cbr/\u003eDeploymentCoordination Controller]\n        Webhook[Webhook Server\u003cbr/\u003ePort 9443]\n    end\n\n    subgraph \"User Namespace\"\n        DC[DeploymentCoordination\u003cbr/\u003eCRD Resource]\n        D1[Deployment 1\u003cbr/\u003eLabels: component=nginx]\n        D2[Deployment 2\u003cbr/\u003eLabels: component=nginx]\n        D3[Deployment 3\u003cbr/\u003eLabels: component=nginx]\n    end\n\n    %% API interactions\n    API --\u003e|\"CREATE/UPDATE\u003cbr/\u003eDeployment\"| Webhook\n    Webhook --\u003e|\"Mutate:\u003cbr/\u003eSet spec.paused=true\u003cbr/\u003e(if not active)\"| API\n\n    %% Controller watching\n    API -.-\u003e|\"Watch DeploymentCoordination\"| Controller\n    API -.-\u003e|\"Watch Deployments\"| Controller\n    Controller --\u003e|\"Update status\"| API\n    Controller --\u003e|\"Unpause active\u003cbr/\u003ePause others\"| API\n\n    %% Coordination resource\n    DC -.-\u003e|\"Defines coordination\u003cbr/\u003evia labelSelector\"| Controller\n\n    %% Deployment matching\n    D1 -.-\u003e|\"Matches selector\"| DC\n    D2 -.-\u003e|\"Matches selector\"| DC\n    D3 -.-\u003e|\"Matches selector\"| DC\n\n    style Controller fill:#e1f5ff\n    style Webhook fill:#fff4e1\n    style DC fill:#e8f5e9\n    style D1 fill:#f3e5f5\n    style D2 fill:#f3e5f5\n    style D3 fill:#f3e5f5\n    style API fill:#ffebee\n```\n\n### Component Interactions\n\n1. **Mutating Webhook**: Intercepts all `Deployment` CREATE and UPDATE operations. If a deployment matches a `DeploymentCoordination` resource's label selector but is not the active deployment, it automatically sets `spec.paused=true`.\n\n2. **Controller**: \n   - Watches `DeploymentCoordination` resources and matching `Deployment` resources\n   - Manages the coordination state by updating the `DeploymentCoordination` status\n   - Activates one deployment at a time by unpausing it\n   - Tracks rollout progress using replica counts\n   - Waits for `MinReadySeconds` before activating the next deployment\n\n3. **DeploymentCoordination CRD**: Defines which deployments should be coordinated using a label selector and optional `minReadySeconds` setting.\n\n4. **Coordinated Deployments**: Deployments with labels matching the `DeploymentCoordination` selector are automatically managed by the controller.\n\n## Use Cases\n\n### Multiple Deployments with Different Pod Configurations\n\nWhen you need to run the same application with different pod configurations (e.g., different network annotations for Multus CNI, different node selectors, or different resource requirements), you typically create separate deployments. However, during upgrades, you want to maintain high availability by ensuring only one deployment rolls out at a time.\n\n**Example Scenario:**\n- Deployment A: Uses static IP annotation for Pod network interface (e.g., `k8s.v1.cni.cncf.io/networks` with a specific static IP)\n- Deployment B: Uses a different static IP annotation or network interface for its Pods\n- Both deployments run the same application but require different network configurations\n- During upgrades, you want to ensure at least one deployment is always available\n\nWhen using GitOps tools (like FluxCD or ArgoCD) combined with automated dependency updates (like Renovate), multiple deployments can receive updates simultaneously. This can cause downtime for the application.\n\nThe `kube-deployment-coordinator` safeguards that when Deployment A is rolling out, Deployment B remains stable, and vice versa, maintaining service availability.\n\n### Alternative Solutions\n\nOther alternatives for coordinating sequential rollouts often involve adopting more complex or heavyweight deployment platforms, such as Argo Rollouts or Spinnaker. These platforms provide advanced deployment strategies and rollout controls, but can introduce significant operational overhead and may require re-architecting existing workflows. \n\nThis approach conflicts with organizations that have already established CI/CD pipelines using tools like FluxCD, ArgoCD, or native Kubernetes deployments, and want to avoid introducing a separate toolchain or controller solely for sequential deployment coordination. In these cases, `kube-deployment-coordinator` offers a lightweight, Kubernetes-native solution focused specifically on this use case with minimal disruption to existing processes.\n\n## How It Works\n\n1. **Webhook**: A mutating webhook automatically pauses deployments that match a `DeploymentCoordination` resource but are not the active deployment\n2. **Controller**: The controller manages the coordination by:\n   - Identifying deployments that match the label selector\n   - Activating one deployment at a time (unpausing it)\n   - Tracking rollout progress using replica counts\n   - Waiting for `MinReadySeconds` after a deployment completes before activating the next one\n   - Updating status with rollout timestamps and deployment states\n\n## Installation\n\n### Using Helm (FluxCD)\n\n```yaml\n---\napiVersion: source.toolkit.fluxcd.io/v1\nkind: OCIRepository\nmetadata:\n  name: kube-deployment-coordinator-crds\n  namespace: kube-system\nspec:\n  interval: 160m\n  url: oci://ghcr.io/containerinfra/charts/kube-deployment-coordinator-crds\n  ref:\n    semver: \"\u003e= 0.0.0\"\n---\napiVersion: helm.toolkit.fluxcd.io/v2\nkind: HelmRelease\nmetadata:\n  name: kube-deployment-coordinator-crds\n  namespace: kube-system\nspec:\n  chartRef:\n    kind: OCIRepository\n    name: kube-deployment-coordinator-crds\n    namespace: kube-system\n  interval: 1h\n  values: {}\n---\napiVersion: source.toolkit.fluxcd.io/v1\nkind: OCIRepository\nmetadata:\n  name: kube-deployment-coordinator\n  namespace: kube-system\nspec:\n  interval: 160m\n  url: oci://ghcr.io/containerinfra/charts/kube-deployment-coordinator\n  ref:\n    semver: \"\u003e= 0.0.0\"\n---\napiVersion: helm.toolkit.fluxcd.io/v2\nkind: HelmRelease\nmetadata:\n  name: kube-deployment-coordinator\n  namespace: kube-system\nspec:\n  chartRef:\n    kind: OCIRepository\n    name: kube-deployment-coordinator\n    namespace: kube-system\n  interval: 1h\n  install:\n    crds: Skip\n  values:\n    enableServiceMonitor: false\n    replicaCount: 1\n    affinity:\n      nodeAffinity:\n        preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 1\n            preference:\n              matchExpressions:\n                - key: node-role.kubernetes.io/control-plane\n                  operator: Exists\n    nodeSelector:\n      kubernetes.io/os: linux\n    tolerations:\n      - key: node-role.kubernetes.io/control-plane\n        effect: NoSchedule\n```\n\n## Usage\n\n### 1. Create a DeploymentCoordination Resource\n\nDefine which deployments should be coordinated using a label selector:\n\n```yaml\napiVersion: apps.containerinfra.nl/v1\nkind: DeploymentCoordination\nmetadata:\n  name: nginx-coordination\n  namespace: default\nspec:\n  labelSelector:\n    matchLabels:\n      component: nginx\n  minReadySeconds: 10\n```\n\n**Fields:**\n- `labelSelector`: Kubernetes label selector to match deployments that should be coordinated\n- `minReadySeconds`: (Optional) Minimum number of seconds the active deployment must be ready before the next one can start. Defaults to 0.\n\n### 2. Label Your Deployments\n\nEnsure your deployments have labels that match the selector:\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: deployment-1\n  labels:\n    component: nginx  # Matches the labelSelector above\nspec:\n  replicas: 1\n  # ... rest of deployment spec\n```\n\n### 3. How Coordination Works\n\nOnce you have a `DeploymentCoordination` resource and matching deployments:\n\n1. **Initial State**: All matching deployments are automatically paused by the webhook or controller\n2. **Activation**: The controller activates the first deployment (in alphabetical order by namespace/name)\n3. **Rollout**: The active deployment rolls out while others remain paused\n4. **Completion**: Once the active deployment finishes rolling out and has been ready for `MinReadySeconds`, it's cleared\n5. **Next Deployment**: The next deployment with pending changes is activated\n6. **Repeat**: This continues until all deployments have finished rolling out\n\n### 4. Checking Status\n\nView the coordination status:\n\n```bash\nkubectl get deploymentcoordination nginx-coordination -o yaml\n```\n\nThe status includes:\n- `activeDeployment`: The currently active deployment (namespace/name format)\n- `deployments`: List of all coordinated deployments\n- `deploymentStates`: Detailed state for each deployment including:\n  - `hasPendingChanges`: Whether the deployment needs rollout\n  - `lastRolloutStarted`: Timestamp when the last rollout started\n  - `lastRolloutFinished`: Timestamp when the last rollout finished\n- `conditions`: Standard Kubernetes conditions (Ready, Progressing, Degraded)\n\nExample status output:\n\n```yaml\nstatus:\n  activeDeployment: default/deployment-1\n  deployments:\n    - default/deployment-1\n    - default/deployment-2\n    - default/deployment-3\n  deploymentStates:\n    - name: default/deployment-1\n      hasPendingChanges: false\n      generation: 2\n      lastRolloutStarted: \"2025-01-20T10:00:00Z\"\n      lastRolloutFinished: \"2025-01-20T10:05:00Z\"\n    - name: default/deployment-2\n      hasPendingChanges: true\n      generation: 1\n  conditions:\n    - type: Ready\n      status: \"False\"\n      reason: DeploymentsInProgress\n    - type: Progressing\n      status: \"True\"\n      reason: DeploymentRollingOut\n```\n\n### 5. Viewing Events\n\nMonitor coordination events:\n\n```bash\nkubectl get events --field-selector involvedObject.name=nginx-coordination --sort-by='.lastTimestamp'\n```\n\nCommon events:\n- `DeploymentActivated`: A deployment was activated for rollout\n- `DeploymentPaused`: A deployment was paused\n- `DeploymentUnpaused`: A deployment was unpaused\n- `ActiveDeploymentReady`: The active deployment finished rolling out\n- `ActiveDeploymentCleared`: The active deployment was cleared\n- `ActiveDeploymentChanged`: The active deployment changed\n\n## Examples\n\n### Example: Coordinating Multiple Nginx Deployments\n\n```yaml\n# 1. Create the coordination resource\napiVersion: apps.containerinfra.nl/v1\nkind: DeploymentCoordination\nmetadata:\n  name: nginx\n  namespace: default\nspec:\n  labelSelector:\n    matchLabels:\n      component: nginx\n  minReadySeconds: 30\n\n---\n# 2. Create multiple deployments with matching labels\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: nginx-frontend\n  labels:\n    component: nginx\nspec:\n  replicas: 3\n  template:\n    metadata:\n      labels:\n        app: nginx-frontend\n    spec:\n      containers:\n      - name: nginx\n        image: nginx:1.21\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: nginx-backend\n  labels:\n    component: nginx\nspec:\n  replicas: 2\n  template:\n    metadata:\n      labels:\n        app: nginx-backend\n    spec:\n      containers:\n      - name: nginx\n        image: nginx:1.21\n```\n\nWhen you update the image in `nginx-frontend`, it will roll out first. Once it completes and has been ready for 30 seconds, `nginx-backend` will automatically start rolling out if it has pending changes.\n\n## Troubleshooting\n\n### Deployments Not Being Coordinated\n\n1. **Check label selector match**: Ensure your deployments have labels that match the `labelSelector` in the `DeploymentCoordination` resource\n2. **Verify webhook is working**: Check if deployments are being paused automatically\n3. **Check controller logs**: \n   ```bash\n   kubectl logs -n kube-deployment-coordinator-system deployment/kube-deployment-coordinator-controller-manager\n   ```\n\n### Deployment Stuck\n\n1. **Check if deployment is paused**: `kubectl get deployment \u003cname\u003e -o jsonpath='{.spec.paused}'`\n2. **Check coordination status**: `kubectl get deploymentcoordination \u003cname\u003e -o yaml`\n3. **Verify active deployment**: Check if another deployment is currently active\n4. **Check events**: Look for error events on the `DeploymentCoordination` resource\n\n### Multiple Deployments Rolling Out Simultaneously\n\nThis should not happen, but if it does:\n1. Check if multiple `DeploymentCoordination` resources match the same deployments\n2. Verify the webhook is enabled and functioning\n3. Check controller logs for errors\n\n## Development\n\n### Building\n\n```bash\nmake build\n```\n\n### Testing\n\n```bash\n# Run unit tests\nmake test\n\n# Run e2e tests (requires Kind cluster)\nmake test-e2e\n```\n\n### Running Locally\n\n```bash\n# Generate webhook certificates (if needed)\n./hack/generate-webhook-certs.sh\n\n# Run the controller\ngo run cmd/main.go --webhook-cert-dir=/tmp/k8s-webhook-server/serving-certs\n```\n\n## License\n\nCopyright 2025 ContainerInfra.\n\nLicensed under the Apache License, Version 2.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontainerinfra%2Fkube-deployment-coordinator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcontainerinfra%2Fkube-deployment-coordinator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontainerinfra%2Fkube-deployment-coordinator/lists"}