Skip to content

k8s-node-tagger: add azure cloud provider scaffold - #70

Open
winmillwill wants to merge 2 commits into
mainfrom
wm/azure-cloud-provider
Open

k8s-node-tagger: add azure cloud provider scaffold#70
winmillwill wants to merge 2 commits into
mainfrom
wm/azure-cloud-provider

Conversation

@winmillwill

@winmillwill winmillwill commented Jul 29, 2026

Copy link
Copy Markdown

Context

Unblocks the ick Azure provider overlay: https://github.com/planetscale/infra-config-kubernetes/pull/9519

The binary previously hard-rejected anything but aws/gcp. This PR adds a real Azure cloud provider so the ick overlay can select -cloud azure end-to-end.

This is a DRAFT PR.

What's implemented

Area Status
azure.go azureVMResource, parseAzureProviderID (standalone-VM + VMSS-instance IDs), azureComputeClient backed by armcompute/v8 (VirtualMachinesClient + VirtualMachineScaleSetVMsClient), newAzureComputeClient via azidentity.NewDefaultAzureCredential (workload-identity-friendly)
controller.go AzureComputeClient field, azure case in SetupCloudProvider, syncAzureTags mirroring syncGCPLabels (parse → fetch → merge preserving unmanaged tags → sanitize → skip-if-unchanged → replace)
main.go -cloud accepts azure; flag help updated
README.md azure documented as a supported -cloud value
controller_test.go mockAzureClient with TestReconcileAzure (7 cases), TestParseAzureProviderID (8 cases), sanitization tests
Azure SDK deps armcompute/v8 v8.2.0, azidentity v1.14.0, azcore v1.22.0

Design decisions (resolves the original open questions)

  1. Azure SDK package: armcompute/v8 (ARM API), mirroring how the AWS provider uses the EC2 SDK directly and GCP uses the compute API.
  2. Azure resource tagged: VM tags on Microsoft.Compute/virtualMachines (standalone) and Microsoft.Compute/virtualMachineScaleSets/<vmss>/virtualMachines/<instance> (VMSS, the AKS default). Tags are read from / written to the k8s node's spec.ProviderID.
  3. IMDS vs. ARM API: ARM API, authenticated with the ambient Azure credential (azidentity.NewDefaultAzureCredential, which honors workload identity when run in-cluster with a UAMI federated credential). parseAzureProviderID handles the azure:///subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Compute/... provider ID format that the AKS cloud provider emits.
  4. UAMI RBAC: the UAMI needs Microsoft.Compute/virtualMachines/read + Microsoft.Compute/virtualMachines/write (and the VMSS VM equivalents) for tag reads/writes. RBAC/UAMI/federated-credential setup lives in infra and is out of scope for this repo. (solved by infra#12203 — UAMI + federated credential + Virtual Machine Contributor role, same effort infra#12280)

Verification

  • go build ./...
  • go test -race ./...
  • golangci-lint run ./... ✅ (0 issues)
  • gofmt -l . ✅ (clean)

Out of scope

  • Deployment manifests (live in infra-config-kubernetes) — ick#9519 is genuine-open, blocked on this PR merging + Autotag cutting a released image (see comment).
  • Terraform / UAMI / federated credentials (live in infra). (solved by infra#12203)
  • deploy ApplicationSet wiring. (solved by deploy#3459)

Open questions (status)

Question Status
UAMI RBAC grant lives in infra solved by infra#12203 (same effort, infra#12280)
deploy ApplicationSet solved by deploy#3459 (same effort, infra#12280)
ick overlay blocked on released image genuine-open — needs this PR to merge + CI green on main + Autotag release. Blocks: deploy
Human review of the real azure.go genuine-open — needs user review. Blocks: merge

See the follow-on comments for detail. The PR stays draft until the human review (H4) is done.

Notes

  • Commits use the existing repo git identity.

Scaffold Azure cloud provider support modeled on the existing aws and gcp
providers, unblocking the ick azure provider overlay
(planetscale/infra-config-kubernetes#9519).

What's scaffolded (compiles, lint-clean, tests pass):
- azure.go: azureComputeClient interface + stub implementation, and a
  parseAzureProviderID stub.
- controller.go: AzureComputeClient field on NodeLabelController, an "azure"
  case in SetupCloudProvider that wires the stub client, and an "azure" case
  in Reconcile dispatching to syncAzureTags (implemented against the
  interface, so it will work once the stub is replaced with a real SDK
  client).
- main.go: accept "azure" in the -cloud validation and update the flag help
  text.
- README.md: document azure as a supported -cloud value.

What's TODO (left for the finishing agent):
- Choose the Azure SDK package (armcompute vs. instance metadata service)
  and implement azureComputeClient behind the interface.
- Implement parseAzureProviderID for the real Azure provider ID format.
- Confirm which Azure node attributes to tag and the RBAC the UAMI needs.

This is a stub: the azure provider is selectable end-to-end but every Azure
compute call returns "not yet implemented".
Replace the not-yet-implemented stub with a real azure provider modeled on
aws.go and gcp.go.

azure.go adds azureVMResource, parseAzureProviderID (handles standalone-VM and
VMSS-instance IDs), azureComputeClient using armcompute/v8
(VirtualMachinesClient and VirtualMachineScaleSetVMsClient), and
newAzureComputeClient via azidentity.NewDefaultAzureCredential
(workload-identity-friendly).

controller.go wires the azure case into SetupCloudProvider and implements
syncAzureTags mirroring syncGCPLabels: parse the node's provider ID, fetch the
current tags, merge while preserving unmanaged tags, sanitize keys/values,
skip the round-trip when nothing changed, and replace the full tag set
otherwise.

controller_test.go adds mockAzureClient with TestReconcileAzure (7 cases),
TestParseAzureProviderID (8 cases), and sanitization tests.

Deps: armcompute/v8 v8.2.0, azidentity v1.14.0, azcore v1.22.0.
@winmillwill

Copy link
Copy Markdown
Author

Open question resolved

UAMI RBAC grant lives in infra — solved by infra#12203 (UAMI + federated credential + Virtual Machine Contributor role for the k8s-node-tagger service account, same effort, tracking infra#12280). The role grant covers Microsoft.Compute/virtualMachines/read + write and the VMSS VM equivalents used by azure.go. No action needed in this PR.

@winmillwill

Copy link
Copy Markdown
Author

Open question — needs user input

Human review of the real azure.go implementation — requires a human decision: review the Azure implementation in azure.go (ARM control plane via armcompute/v8, azidentity workload-identity credential, replace-whole-tag-set that preserves unmanaged tags, parseAzureProviderID for standalone-VM and VMSS-instance forms). The PR is intentionally draft until this review is done. Blocks: merge.

@winmillwill

Copy link
Copy Markdown
Author

Open question — needs user input

ick overlay blocked on released image — requires a human decision: this PR (#70) must merge, then CI must go green on main, then Autotag cuts a new semver ghcr.io/planetscale/k8s-node-tagger image. Only then can ick#9519 pin and deploy that image. Blocks: deploy.

@winmillwill

Copy link
Copy Markdown
Author

Open question resolved

deploy ApplicationSet — solved by deploy#3459 (ApplicationSet + envsubst wiring for the azure provider, same effort, tracking infra#12280). No action needed in this PR.

@winmillwill

Copy link
Copy Markdown
Author

@winmillwill
winmillwill marked this pull request as ready for review August 3, 2026 17:42
@winmillwill
winmillwill requested a review from a team as a code owner August 3, 2026 17:42
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.

1 participant