Skip to content

feat(operator): hosting-aks-upgrade — the cluster half of the governed UpgradeCluster action - #5682

Merged
meshweaver-cloud[bot] merged 1 commit into
mainfrom
feat/aks-upgrade-cluster
Sep 25, 2026
Merged

meshweaver-cloud[bot] merged 1 commit into
mainfrom
feat/aks-upgrade-cluster

Conversation

@rbuergi

@rbuergi rbuergi commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

What

The operator half of the governed UpgradeCluster InstanceAction (policy cluster-upgrade-governed, registered here as proposed until the plan half merges): deploy/aks/operator/bin/hosting-aks-upgrade, the only command that upgrades the AKS cluster's Kubernetes version, run by the aks-ops lane from a signed, mesh-approved bundle — never az aks upgrade by hand.

subcommand what it does
facts read-only; everything the plugin's pure plan reads, as one aks_facts=<base64 JSON> line: cluster version/state/tier/support plan, offered upgrades (previews out) + the region's version graph (for chaining minors and the LTS note), pools, nodes, every portal Deployment's template image vs the images its pods serve, /health per host, PDBs, the API server's apiserver_requested_deprecated_apis metric (an unreadable metric is carried as UNREAD, never "none"), and the apiVersion/kind of every scanned manifest (templated ones skipped)
gate [--strict] --strict (the pre-flight) refuses a stuck roll by name — both images — having issued nothing; between pools it waits inside the job budget, pauses there, and FAILS on what Kubernetes gave up on (ProgressDeadlineExceeded, a pod not Ready past its own startup budget, /health failing with every pod Ready > 10 min)
control-plane --version one control-plane-only hop; already there / already PAST (a continuation) → nothing issued, never a downgrade
node-pool --pool --version one pool straight to the version; the pool hosting this job's own runner is issued and NOT waited on (detached → paused)
verify --version aks_upgrade=complete only when the control plane, every pool and every node are at the version and the gate is healthy

Resumability: a wait reaching --budget-seconds (measured from the job's FIRST step) prints aks_upgrade=incomplete, exits 0, and every later step of that run is skipped — the control plane dispatches a continuation of the same plan.

🚨 Why the stuck-roll refusal: measured 2026-09-25 — memex's Deployment template names 3.0.0-ci.9260 (pods of that image deadlock at bake; fixed by #5643) while its serving pods are 3.0.0-ci.9218, alive only because nothing evicts them. A node drain would recreate them from the template and take the control instance down.

The order (one approval; control-plane minors chained one at a time; every pool upgraded ONCE to the final version; the pool hosting the portals last; a gate before each pool) is decided by the Hosting plugin's pure ClusterUpgradePlan — this script decides none of it.

Also

  • check-rbac-coverage.sh learns the pdb alias (the ClusterRole already grants policy poddisruptionbudgets get/list).
  • hosting-operator.yml: floor 31 → 32, the three new stubs in the tracked list, and hosting-aks-upgrade declared not-yet-wired until the Plugins plan step merges (it moves up into the plan list in the change after).
  • Docs: DeploymentAKS.md "Kubernetes version upgrades — the governed UpgradeCluster action"; the register row; the deployment skill's action table.

Verification

  • deploy/aks/operator/test/run-tests.sh: 592 passed, 0 failed locally (19 new hosting-aks-upgrade cases; every waiting call carries a 5 s budget so a regression fails in seconds, never spins the suite for 35 min).
  • shellcheck -S warning clean on the script and stubs; check-rbac-coverage.sh: 44 calls, 0 missing, 0 unknown; check-stderr-discarded.sh: 0 undeclared.
  • dotnet build src/MeshWeaver.Documentation -c Release -warnaserror: 0 warnings, 0 errors.

What this does NOT do

  • Nothing runs against any cluster from this PR. The plan/executor half (MeshWeaver.Plugins) and the UpgradeCluster lane choice + read step (Systemorph/Memex aks-ops.yml) follow.
  • Not established against a live cluster: the exact JSON of az aks get-versions in swedencentral (the parser follows the documented values[].patchVersions shape) and whether hosting-operator already holds the ARM rights the reads/writes need ("Azure Kubernetes Service Contributor Role" on the cluster) — the command refuses a missing grant BY NAME rather than reading it as "nothing to upgrade".

Pairs-with: none — no public .NET surface touched (bash + docs only).

🤖 Generated with Claude Code

…d UpgradeCluster action

The AKS Kubernetes upgrade becomes an operator command the aks-ops lane runs from a signed,
mesh-approved plan (policy `cluster-upgrade-governed`), never an ad-hoc `az aks upgrade`:

- `facts` (read-only): cluster version, offered upgrades + the region's version graph, pools,
  nodes, every portal Deployment's TEMPLATE image against the image its pods SERVE, /health,
  PDBs, the API server's deprecated-API metric (unreadable = UNREAD, never "none") and the
  scanned manifests' apiVersions — one base64 JSON fact for the plugin's pure plan.
- `gate [--strict]`: a stuck roll refuses the pre-flight by name (memex 2026-09-25: template
  3.0.0-ci.9260 over serving 3.0.0-ci.9218); between pools it waits inside the job budget and
  fails on what Kubernetes gave up on.
- `control-plane` / `node-pool` / `verify`: idempotent, resumable hops (already there or already
  past → nothing issued; the runner's own pool detached; a budget pause is aks_upgrade=incomplete
  for the control plane to continue).

The ORDER (one approval, control-plane minors chained, each pool once to the final version,
portals' pool last) is the Hosting plugin's ClusterUpgradePlan; this script decides none of it.
19 behaviour cases against stubs; the RBAC map learns `pdb`; the plan half lands in
MeshWeaver.Plugins, so the command is declared not-yet-wired until then.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 25, 2026 05:40
@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

  1 files    1 suites   2m 43s ⏱️
345 tests 345 ✅ 0 💤 0 ❌
349 runs  349 ✅ 0 💤 0 ❌

Results for commit 33995cb.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

443 tests   443 ✅  1m 1s ⏱️
  3 suites    0 💤
  3 files      0 ❌

Results for commit 33995cb.

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Unresolved critical and moderate findings remain in hosting-aks-upgrade.

Review effort: Lite
Findings: None

What changed in this PR

Adds the operator-side governed AKS UpgradeCluster action with safety gates, resumability, verification, tests, fixtures, RBAC coverage, and documentation.

Changes:

  • Adds hosting-aks-upgrade facts, gates, upgrade, and verification commands.
  • Adds command stubs, AKS fixtures, and behavioral tests.
  • Updates policy, workflow tracking, deployment guidance, and RBAC coverage.

Review found one critical and seven moderate unresolved issues in the upgrade command.

File Description
src/​MeshWeaver.Documentation/​Data/​Architecture/​PolicyNotProse.md Registers the proposed upgrade policy.
src/​MeshWeaver.Documentation/​Data/​Architecture/​DeploymentAKS.md Documents governed AKS upgrades.
deploy/​aks/​operator/​test/​stubs/​aks-upgrade/​kubectl Kubernetes CLI test stub.
deploy/​aks/​operator/​test/​stubs/​aks-upgrade/​curl Health probe test stub.
deploy/​aks/​operator/​test/​stubs/​aks-upgrade/​az Azure CLI test stub.
deploy/​aks/​operator/​test/​run-tests.sh Upgrade behavior tests.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​versions.json Version graph fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​upgrades.json Upgrade offers fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​show.json Cluster state fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​show.after.json Post-upgrade cluster state fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​runner.json Runner pool fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​pools.json Node-pool fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​pools.after.json Post-upgrade node-pool fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​pods-memex.json Portal pod fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​pdbs.json Pod disruption budget fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​nodes.json Node fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​metrics.txt Deprecated API metrics fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​manifests/​pdb.yaml Manifest API fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​manifests/​cron.yml Manifest API fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​ingress-memex.json Ingress fixture.
deploy/​aks/​operator/​test/​fixtures/​aks-upgrade/​deployments.json Deployment fixture.
deploy/​aks/​operator/​test/​check-rbac-coverage.sh Adds PDB RBAC coverage.
deploy/​aks/​operator/​bin/​hosting-aks-upgrade Implements AKS upgrade operations and safety gates.
.github/​workflows/​hosting-operator.yml Tracks the operator command and test stubs.
.claude/​skills/​deployment/​SKILL.md Documents the upgrade action.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

1 652 tests   1 652 ✅  3m 16s ⏱️
    2 suites      0 💤
    2 files        0 ❌

Results for commit 33995cb.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

    3 files      3 suites   6m 16s ⏱️
2 012 tests 2 012 ✅ 0 💤 0 ❌
2 013 runs  2 013 ✅ 0 💤 0 ❌

Results for commit 33995cb.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

749 tests   557 ✅  7m 8s ⏱️
  3 suites  192 💤
  3 files      0 ❌

Results for commit 33995cb.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

    5 files      5 suites   13m 29s ⏱️
4 078 tests 4 076 ✅ 2 💤 0 ❌
4 082 runs  4 080 ✅ 2 💤 0 ❌

Results for commit 33995cb.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results

   17 files     17 suites   33m 56s ⏱️
9 279 tests 9 085 ✅ 194 💤 0 ❌
9 288 runs  9 094 ✅ 194 💤 0 ❌

Results for commit 33995cb.

@meshweaver-cloud
meshweaver-cloud Bot added this pull request to the merge queue Sep 25, 2026
Merged via the queue into main with commit 7516c82 Sep 25, 2026
40 checks passed
@rbuergi
rbuergi deleted the feat/aks-upgrade-cluster branch October 10, 2026 13:10
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