Skip to content

Repository files navigation

kubectl-upgrade

The missing pre-flight + watch + verify layer that wraps any Kubernetes upgrade.

demo

kubectl-upgrade tells you what will break before you start, generates provider-specific upgrade commands for you to review and run, watches the upgrade in progress for known stuck states, tells you how to unstick common failures, and verifies success after.

It does not run cloud CLIs itself; it emits the provider command or runbook step for an operator to review and execute.

$ kubectl upgrade preflight --target v1.34
$ kubectl upgrade run plan   --target v1.34   # emits the eksctl/gcloud/az command for YOU to run
$ kubectl upgrade run watch --target v1.34     # monitors the in-flight upgrade
$ kubectl upgrade run verify --target v1.34    # post-upgrade smoke
$ kubectl upgrade fleet      --host-target v1.34 --plan   # vCluster Tenant Cluster wave

Why

Most Kubernetes upgrade prechecks focus on API removals found in live cluster state, provider telemetry, or audit-log windows. That is necessary, but it misses important evidence that lives in Helm release history, local manifest files, CRDs, PDBs, PVCs, addon versions, and in-flight upgrade state.

kubectl-upgrade currently scans four workload source families:

  • live cluster objects from the Kubernetes API
  • Helm v3 release secrets stored in the cluster
  • local YAML/JSON manifest files or directories passed with scan --source manifests --path ...
  • local Git/GitOps desired-state inputs passed with scan --source git|argocd|flux

GitOps discovery is local and read-only today: it scans local Git paths, ArgoCD Application/ApplicationSet manifests, and Flux Kustomization/HelmRelease manifests that reference local paths. It does not yet clone remote repositories or call live ArgoCD/Flux APIs.

How it works under the hood

kubectl-upgrade is an evidence collector and finding normalizer. Each command reads one or more sources, turns matching risks into findings, and keeps those findings tied to the source an operator can change.

Evidence sources include:

  • Kubernetes API reads for live objects, server-discovered resources, CRDs, webhooks, storage, pods, PDBs, owners, and server version
  • Helm v3 release secrets, including older release manifests that may still contain removed APIs
  • local YAML/JSON manifests and local Git/GitOps paths for Git, Argo CD, and Flux workflows
  • operator-supplied EKS, GKE, and AKS JSON exports
  • operator-supplied Prometheus API server metrics and Kubernetes audit logs
  • addon controller Deployments and image tags compared with the embedded addon compatibility matrix
  • vCluster Helm release secrets on the Control Plane Cluster, used to identify Tenant Clusters and evaluate vCluster product gates plus host Kubernetes compatibility

The default behavior is read-only. The tool reads the Kubernetes API and local files, imports evidence you provide, and prints provider upgrade commands for human review. It does not run aws, gcloud, az, drain nodes, evict pods, edit webhooks, upgrade addons, mutate vCluster tenants, clone remote repositories, or call live Argo CD/Flux APIs during normal checks.

A finding is intended to move through a lifecycle: discover, triage, assign an owner, fix the source, then rerun the command to confirm the evidence changed. Reports preserve attribution where the detector has it: namespace/name for live objects, Helm release and revision for release history, local file paths for manifests and GitOps inputs, controller Deployment/image for addons, provider export or runtime evidence source for imports, and tenant release/namespace for vCluster.

Validation follows the same model. Use the demo lab, smoke commands, JSON/Markdown/SARIF output, relationship graph output, and --fail-on gates to make checks repeatable in CI and release reviews. Passing output means the current evidence did not trigger configured blockers; it does not replace provider prechecks, addon-specific upgrade guides, vCluster snapshot/backup discipline, or upstream release-note review for the exact versions you run.

kubectl-upgrade covers the whole flow:

Stage What it does Other tools
Source scan Deprecated API scan for live objects, Helm release secrets, local manifest files/directories, and local GitOps source trees API-only tools usually stop at live or audit-observed objects
Pre-flight Live+Helm scan plus CRDs, conversion webhooks, PV/PVCs, addons, PDBs, drain simulation, and vCluster gates provider checks vary by platform
Evidence imports Offline EKS/GKE/AKS insight JSON plus Prometheus metrics and audit-log evidence usually split across provider portals and observability systems
Plan Detect provider, emit provider command/runbook step none
Watch Monitor in-flight upgrade for stuck patterns none
Unstick Detect common stuck states such as PDB-blocked evictions, NotReady nodes, pending Helm releases, webhook failure policies, and namespace finalizers none
Verify Post-upgrade rescan, server version check, smoke none
Fleet vCluster Tenant Cluster wave orchestration none

Install

curl (recommended)

Downloads the latest release archive and drops kubectl-upgrade on your $PATH. Once it's there, kubectl upgrade works automatically — kubectl auto-discovers kubectl-* binaries; no krew required.

curl -sSL https://raw.githubusercontent.com/saiyam1814/upgrade/main/install.sh | sh
kubectl upgrade --help

From source

go install github.com/saiyam1814/upgrade@latest
mv $(go env GOBIN)/upgrade $(go env GOBIN)/kubectl-upgrade

Direct download

Grab a tarball/zip from Releases and place kubectl-upgrade on $PATH.

Coming soon

  • krew — manifest at .krew/upgrade.yaml is ready; PR to kubernetes-sigs/krew-index not yet submitted.
  • Homebrew — formula scaffolded; needs the tap repo + token before re-enabling in GoReleaser.

The day-1 production flow

# 1. Find every workload-side time bomb
kubectl upgrade preflight --target v1.34

# 2. Get the provider command/runbook step for review
kubectl upgrade run plan --target v1.34

# 3. (You manually run the emitted commands.)
#    In a separate terminal, watch for stuck states:
kubectl upgrade run watch --target v1.34

# 4. After the upgrade finishes, verify
kubectl upgrade run verify --target v1.34

# Got stuck? This is the recovery toolkit:
kubectl upgrade unstick

# Have vClusters? Check which tenants are compatible with the
# upcoming host K8s bump BEFORE you bump the host:
kubectl upgrade fleet --host-target v1.34 --plan

Fleet — host × vCluster compat

When you bump a Control Plane Cluster's K8s minor (e.g. EKS 1.32→1.34), not every vCluster version on it will tolerate the new host. fleet runs a per-tenant check and tells you which tenants need to be bumped before the host upgrade and which are safe.

kubectl upgrade fleet --host-target v1.34 --plan

Output for each tenant — three states:

  • ✓ INFO — current vCluster supports the new host K8s. Safe.
  • ⚠ MEDIUM — at the upper edge of the support window. Plan a tenant bump after the host.
  • ✗ BLOCKER — tenant's vCluster version does NOT support the new host. Bump the tenant first; the runbook tells you the minimum vCluster version to bump to.

The compat table is hand-curated from upstream vCluster release notes; PRs welcome to extend it as new releases land.

Visual mode

kubectl upgrade tui --target v1.34

A bubbletea dashboard with steps on the left and findings/commands on the right. Like k9s for upgrades.

Commands

Command Purpose
preflight Aggregate live pre-flight: scan (live + Helm) + simulate + addons + pdb + drain + volumes + crds + vcluster
run plan Emit cloud-CLI commands for control plane + nodes
run watch Monitor in-flight upgrade for stuck states
run verify Post-upgrade verification
fleet vCluster Tenant Cluster wave plus fleet drift/risk scoring
scan Deprecated APIs in live cluster / Helm releases / local manifest files / local GitOps sources
simulate Forward sim: feature gates, default flips, kubelet, kernel
pdb Drain-deadlock detector
drain Read-only node drain simulator
addons Controller compatibility matrix for cert-manager, Istio, Karpenter, ArgoCD, Cilium, Calico, CoreDNS, and more
volumes PV / PVC / CSI / StorageClass safety
crds CRD versions / webhook certs / storedVersions / orphan CRDs
provider-insights Import EKS / GKE / AKS upgrade insight JSON
runtime-evidence Import deprecated API metrics / audit-log evidence
vcluster Per-Tenant-Cluster decision tree
unstick Stuck-state recovery toolkit
plan Chained one-minor-at-a-time path
report Combined report (Markdown / JSON / SARIF / graph JSON)
tui Interactive visual upgrade dashboard

Run kubectl upgrade <cmd> --help for examples and full options.

Safety

kubectl-upgrade is designed for production prechecks with read-only behavior by default. Mutating actions (currently only unstick --auto-fix) require both --execute AND a per-action [y/N] confirmation.

We never:

  • Run cloud CLIs (aws, gcloud, az) for you. We emit the command; you run it.
  • Force-delete stuck Pods, modify webhook failurePolicy, or remove namespace finalizers.
  • Take backups, drain nodes, or pause GitOps reconciliation.
  • Phone home. The binary makes no network calls beyond the Kubernetes API server you point it at.

See SAFETY.md for the full safety contract.

Provider coverage

run plan knows how to talk about (no execution, just emits commands):

Provider Control plane Node pools
AWS EKS / EKS Auto aws eks update-cluster-version aws eks update-nodegroup-version
GKE / GKE Autopilot gcloud container clusters upgrade gcloud container clusters upgrade --node-pool
AKS az aks upgrade az aks nodepool upgrade
OpenShift / ROSA oc adm upgrade (auto via Machine Config Operator)
RKE2 / k3s system-upgrade-controller Plan system-upgrade-controller Plan
Talos talosctl upgrade-k8s (separate talosctl upgrade)
kubeadm kubeadm upgrade plan + apply kubectl drain + apt + restart kubelet
Cluster API (provider-specific) (provider-specific)
vCluster kubectl upgrade vcluster (per-tenant) (n/a)

Rule data

Rule type Source Coverage
Deprecated APIs Vendored snapshot of FairwindsOps/pluto versions.yaml (Apache 2.0) k8s, cert-manager, istio, prom-operator, several others
Feature gates / defaults / kubelet / kernel Hand-curated from upstream Kubernetes release notes 1.25 → 1.36
Addon ↔ K8s compat internal/addons/addons.yaml, hand-curated from upstream docs with confidence and review-date metadata cert-manager, Karpenter, Istio, ArgoCD, Flux, prom-operator, Kyverno, ingress-nginx, Cilium, Calico, CoreDNS, external-secrets, Crossplane, Gatekeeper, KEDA, Linkerd, Velero, AWS EBS CSI, AWS Load Balancer Controller, Envoy Gateway
vCluster decision tree upstream vCluster docs + release notes v0.20 → v0.34

PRs to extend coverage are welcome.

Detailed addon docs: https://saiyam1814.github.io/upgrade/addons.html

Full project guide: https://saiyam1814.github.io/upgrade/guide.html

vCluster guide: https://saiyam1814.github.io/upgrade/vcluster.html

Output formats

kubectl upgrade preflight --target v1.34 --format human      # default, colorized
kubectl upgrade preflight --target v1.34 --format md         # Markdown for PRs
kubectl upgrade preflight --target v1.34 --format json       # CI / scripts
kubectl upgrade preflight --target v1.34 --format sarif      # GitHub code scanning
kubectl upgrade preflight --target v1.34 --format graph      # source/object/owner relationship graph JSON

The docs site includes a browser-based 3D viewer for graph output: https://saiyam1814.github.io/upgrade/graph.html

CI gate:

kubectl upgrade preflight --target v1.34 --fail-on blocker   # exit 2 on any BLOCKER

Build

make build        # ./bin/kubectl-upgrade
make test
make smoke        # all the headless-safe commands
make kind-validate DELETE_CLUSTER=1 # disposable kind demo-lab validation
make addon-docs   # regenerate docs/addons.html coverage table
make refresh-rules # bump pluto's versions.yaml

License

Apache 2.0. The bundled versions.yaml snapshot from FairwindsOps/pluto is also Apache 2.0.

About

The conductor for any Kubernetes upgrade — pre-flight, run, watch, unstick, verify, fleet

Resources

Contributing

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages