Skip to content

feat: Add NPS/Bootstrap support for Azure Container Linux - #1875

Draft
Kyle Gospodnetich (KyleGospo) wants to merge 12 commits into
Azure:mainfrom
KyleGospo:kylegospo/acl-nps
Draft

feat: Add NPS/Bootstrap support for Azure Container Linux#1875
Kyle Gospodnetich (KyleGospo) wants to merge 12 commits into
Azure:mainfrom
KyleGospo:kylegospo/acl-nps

Conversation

@KyleGospo

@KyleGospo Kyle Gospodnetich (KyleGospo) commented Aug 27, 2026

Copy link
Copy Markdown

This is a continuation of #1841
Add AzureContainerLinux support to the NPS / bootstrapping-client provisioning path.

Design flow

  1. NodeClass selection

    • Users select spec.imageFamily: AzureContainerLinux.
    • Admission validation enforces the 60 GB minimum OS disk, requires Secure Boot and vTPM, and rejects artifactStreaming.enabled=true (ACL's immutable /usr is incompatible with artifact streaming).
    • The validation reconciler rejects the nodeclass with a clear condition when the cluster is on Kubernetes < 1.34 or when the provider is running in aksscriptless mode (which cannot obtain Ignition from AgentBaker).
  2. Image resolution

    • Karpenter selects the Azure Container Linux image definition from the Azure Linux gallery.
    • Architecture and FIPS determine one of four variants: AMD64, ARM64, AMD64 FIPS, or ARM64 FIPS.
    • Non-Trusted-Launch requests return no image (defense-in-depth alongside the CEL rules).
  3. Instance-type filtering

    • Trusted Launch-incompatible SKUs are removed from consideration.
    • ARM64 is restricted to Cobalt v6 (Standard_*p*_v6) SKUs with an NVMe data disk — the only ARM64 SKUs where the ACL Ignition bootstrap has been validated.
    • GPU nodes use the Azure Container Linux compatibility list; supported NVIDIA SKUs remain available while unsupported NVIDIA and AMD SKUs are excluded.
  4. VM creation

    • The VM is created through the Compute API with SecurityType=TrustedLaunch, SecureBootEnabled=true, and VTpmEnabled=true, using the resolved ACL image and bootstrapping via AgentBaker-generated Ignition.
    • The custom-data hydrator walks the Ignition doc and rewrites the {{.TokenID}}.{{.TokenSecret}} placeholder inside gzip-compressed storage.files[] entries so kubelet gets a valid TLS bootstrap token.

How was this change tested?

  • Unit and acceptance suites pass locally on the changed packages (pkg/apis/v1beta1, pkg/providers/imagefamily, pkg/providers/imagefamily/customscriptsbootstrap, pkg/providers/instancetype, pkg/providers/instance, pkg/controllers/nodeclass/status).
  • New reconciler tests cover both provision-mode compatibility (aksscriptless rejected; bootstrappingclient accepted) and Kubernetes version compatibility (1.30–1.33 rejected, 1.34+ accepted).
  • New CEL test covers rejecting artifactStreaming.enabled=true alongside imageFamily=AzureContainerLinux.
  • New unit test covers the nested-Ignition-gzip token replacement.

TO-DO: Additional tests of real deployments

Does this change impact docs?

  • Yes, PR includes docs updates
  • Yes, issue opened: #
  • No

Release Note

Add Azure Container Linux support to AKSNodeClass on the NPS / bootstrapping-client provisioning path.

AgentBaker emits Ignition (not CSE) for AzureContainerLinux. The kubelet bootstrap token placeholder {{.TokenID}}.{{.TokenSecret}} can end up inside a gzip-compressed storage.files[] entry rather than the outer document, so a plain string replace on the base64-decoded custom data leaves the placeholder unhydrated and the node fails to bootstrap.

Extend hydrateBootstrapTokenIfNeeded to parse the Ignition doc, decompress each embedded file, replace the placeholder, and recompress. Covered by a new nested-Ignition-gzip subtest in TestHydrateBootstrapTokenIfNeeded.
AzureContainerLinux bootstraps via Ignition, which is produced only by
AgentBaker (bootstrappingclient path) or by the AKS Machine API. In
aksscriptless mode CSE is generated locally without an AgentBaker call,
so the node would come up without valid bootstrap configuration.

Set ValidationSucceeded=False with reason IncompatibleProvisionMode
when a nodeclass sets imageFamily=AzureContainerLinux while the
provider is running in aksscriptless mode. Cover the four provision
modes in a new DescribeTable in the validation reconciler suite.
ACL is only supported on AKS 1.34+ (per the AKS ACL support matrix). Add a check in the nodeclass validation reconciler that sets ValidationSucceeded=False with reason IncompatibleKubernetesVersion and a specific message when a nodeclass with imageFamily=AzureContainerLinux is reconciled against a cluster on an older Kubernetes minor.

The check runs after the KubernetesVersionReconciler has populated Status.KubernetesVersion. If the version is not yet ready, the reconciler silently skips the check and will re-run once it is.

Drop the equivalent SKU-level useAzureContainerLinux() gate in isInstanceTypeSupportedByAzureContainerLinux (and its now-unused blang/semver import) since the reconciler check surfaces the condition with a clear message, whereas the SKU filter would have silently eliminated every SKU.
@MaximilianoUribe

Copy link
Copy Markdown
Collaborator

did we test this with an actual node being provisioned here Kyle Gospodnetich (@KyleGospo)?

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