Artifact Streaming lets an AKS node retrieve the image content needed to start a container before downloading the entire image. The benefit is most visible with large images and node scale-out or bulk Pod startup. This guide retains the source's July 2026 support snapshot: Linux AMD64 availability is described as GA, with Azure CLI 2.87.0 or later required. A locally tested 2.86.0 CLI still printed Preview warnings. Verify the current official support matrix and your installed CLI before rollout; these are documented prerequisites, not measurements performed by this site.

1. Check eligibility and exclusions

ComponentRequirement
Azure CLI2.87.0 or later
AKSKubernetes 1.25 or later
ACRPremium SKU
Node operating systemUbuntu 20.04 or later, or Azure Linux
Image architectureLinux AMD64
AuthenticationAKS–ACR integration using the kubelet identity, normally configured with --attach-acr
Operator permissionsAzure Kubernetes Service Contributor for node-pool configuration; registry operations require their own appropriate permissions
  • Windows and ARM64 images are unsupported; only the AMD64 part of a multi-architecture image is a streaming candidate.
  • Standard and Basic ACR tiers do not expose this feature.
  • The source excludes customer-managed-key encrypted registries and geo-replicated registry artifact generation/synchronization.
  • Pull by tag, not an image digest such as image@sha256:.... GitOps or Flux digest pinning prevents streaming in the documented scenario.
  • Pulls authenticated with imagePullSecrets, non-Entra scope tokens, or ACR admin credentials fall back to a normal pull. A successful pull therefore does not itself prove streaming.
  • Images over 30 GB are not described as technically prohibited, but the source warns that perceived gains diminish. Prefer mounted volumes for very large static data.

Set the following to your own resources. Commands are Bash examples, not commands executed during publication.

export RESOURCE_GROUP="YOUR_RESOURCE_GROUP"
export CLUSTER="YOUR_CLUSTER"
export LOCATION="YOUR_AZURE_REGION"
export ACR_NAME="YOUR_ACR_NAME"
export REPOSITORY="YOUR_REPOSITORY"
export TAG="YOUR_IMAGE_TAG"
export NODEPOOL="YOUR_NODEPOOL"

az --version
# Upgrade when below the required version.
az upgrade
az aks show -g "$RESOURCE_GROUP" -n "$CLUSTER" --query kubernetesVersion -o tsv
az acr show --name "$ACR_NAME" --query sku.name -o tsv
az aks check-acr --resource-group "$RESOURCE_GROUP" --name "$CLUSTER" --acr "$ACR_NAME.azurecr.io"
az aks nodepool list -g "$RESOURCE_GROUP" --cluster-name "$CLUSTER" \
  --query "[].{pool:name, osType:osType, osSKU:osSKU}" -o table
kubectl get deployments -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\t"}{range .spec.template.spec.containers[*]}{.image}{" "}{end}{"\n"}{end}' | grep '@sha256'
# Confirm architecture as well; the source's node-pool query does not show it.
kubectl get nodes -L kubernetes.io/arch,kubernetes.io/os

2. Establish a cold-pull baseline

Measure before enabling streaming. Use the same image and node VM size in both experiments, and use fresh nodes or nodes without the tested image. Reusing cached layers can erase or fabricate the apparent improvement. Repeat at least three times under equivalent cold-cache conditions and average the results; a single observation is sensitive to network variation.

Create an isolated test node pool

az aks nodepool add -g "$RESOURCE_GROUP" --cluster-name "$CLUSTER" \
  --name streamtest --node-count 1 --node-vm-size Standard_D4ds_v5 \
  --mode User --os-sku Ubuntu
# Optional isolation: only Pods with the matching toleration can run here.
az aks nodepool update -g "$RESOURCE_GROUP" --cluster-name "$CLUSTER" \
  --name streamtest --node-taints stream-test=true:NoSchedule

Measure submission, image pull, and readiness separately

# Record the timestamp BEFORE submitting the Pod.
date -u +"%Y-%m-%dT%H:%M:%S.%3NZ"
kubectl run streaming-test --image="$ACR_NAME.azurecr.io/$REPOSITORY:$TAG" \
  --overrides='{"spec":{"tolerations":[{"key":"stream-test","operator":"Equal","value":"true","effect":"NoSchedule"}],"nodeSelector":{"agentpool":"streamtest"}}}' \
  --restart=Never -n default
time kubectl wait --for=condition=Ready pod/streaming-test -n default --timeout=600s
kubectl get events -n default --field-selector involvedObject.name=streaming-test \
  --sort-by=.lastTimestamp \
  -o custom-columns=REASON:.reason,TIME:.lastTimestamp,MESSAGE:.message
az acr repository show --name "$ACR_NAME" --image "$REPOSITORY:$TAG" --query "imageSize" -o tsv
kubectl delete pod streaming-test -n default
MetricHow to record it
Image pull timeDifference between Pulling and Pulled event timestamps
Total time to ReadyPod submission timestamp to successful Ready completion; the duration of kubectl wait alone starts after submission and is not the complete total
Container startStarted event, distinct from application readiness
Image sizeRegistry-reported imageSize in bytes; convert to MB if present. If this query returns no field, inspect supported manifest metadata instead of treating a blank as zero.
Node conditionsVM size, pool, OS, architecture, whether the node is new, and cache state
The source records the submission timestamp after creating the Pod. The sequence above moves it before creation to avoid understating time to Ready. Event timestamps and aggregation may be coarse; preserve raw timing evidence and use consistent measurement methods.

3. Prepare the registry artifact

Create resources only if they do not exist. The default registry setting changes the CLI configuration for subsequent commands. Import or push an image, create its streaming artifact, and inspect referrers. Repository-level automatic artifact generation is optional.

az group create --name "$RESOURCE_GROUP" --location "$LOCATION"
az acr create --resource-group "$RESOURCE_GROUP" --name "$ACR_NAME" --sku Premium
az configure --defaults acr="$ACR_NAME"
# Skip import if the target image already exists.
az acr import --source "docker.io/YOUR_SOURCE_REPOSITORY:YOUR_SOURCE_TAG" --image "$REPOSITORY:$TAG"
az acr artifact-streaming create --image "$REPOSITORY:$TAG"
# Optional: generate streaming artifacts for future images in this repository.
az acr artifact-streaming update --name "$ACR_NAME" --repository "$REPOSITORY" --enable-streaming true
az acr manifest list-referrers --name "$REPOSITORY:$TAG" --registry "$ACR_NAME"

4. Enable a node pool and verify the profile

Choose either new-pool creation or update of an existing pool; do not run both indiscriminately. Ensure the workload is actually scheduled onto the enabled pool.

# New pool:
az aks nodepool add --resource-group "$RESOURCE_GROUP" \
  --cluster-name "$CLUSTER" --name "$NODEPOOL" --enable-artifact-streaming

# OR an existing pool:
az aks nodepool update --resource-group "$RESOURCE_GROUP" \
  --cluster-name "$CLUSTER" --name "$NODEPOOL" --enable-artifact-streaming

az aks nodepool show --resource-group "$RESOURCE_GROUP" \
  --cluster-name "$CLUSTER" --name "$NODEPOOL" --query artifactStreamingProfile
# Expected profile: enabled is true.

5. Repeat the experiment after enablement

Use the identical image, VM size, timing procedure, and number of repetitions on uncached streaming-enabled nodes. If the pool has the test taint, retain its toleration as shown. Deleting only the Pod does not remove cached image layers.

date -u +"%Y-%m-%dT%H:%M:%S.%3NZ"
kubectl run streaming-test-after --image="$ACR_NAME.azurecr.io/$REPOSITORY:$TAG" \
  --overrides="{\"spec\":{\"tolerations\":[{\"key\":\"stream-test\",\"operator\":\"Equal\",\"value\":\"true\",\"effect\":\"NoSchedule\"}],\"nodeSelector\":{\"agentpool\":\"$NODEPOOL\"}}}" \
  --restart=Never -n default
time kubectl wait --for=condition=Ready pod/streaming-test-after -n default --timeout=600s
kubectl get events -n default --field-selector involvedObject.name=streaming-test-after \
  --sort-by=.lastTimestamp \
  -o custom-columns=REASON:.reason,TIME:.lastTimestamp,MESSAGE:.message
kubectl delete pod streaming-test-after -n default
MetricBefore: average of at least three cold runsAfter: average of at least three cold runsImprovement
Pulling to PulledRecord measurementRecord measurement(Before − After) / Before × 100%
Submission to ReadyRecord measurementRecord measurement(Before − After) / Before × 100%

No numerical speed-up was supplied in the source: this is a benchmark template, not a claim of measured performance. Large images of hundreds of MB to several GB are more likely to show a benefit than images of only tens of MB. Recheck tag-based deployment and kubelet identity authentication before interpreting an unexpectedly small gain.

6. Roll back and remove test resources

az aks nodepool update --resource-group "$RESOURCE_GROUP" \
  --cluster-name "$CLUSTER" --name "$NODEPOOL" --disable-artifact-streaming
# Optional and destructive: remove only the dedicated test pool after confirming it has no needed workloads.
az aks nodepool delete -g "$RESOURCE_GROUP" --cluster-name "$CLUSTER" --name streamtest --no-wait

Disabling the node-pool feature is the documented rollback. This is separate from removing registry referrers or changing repository automatic-generation settings; the source does not provide a registry cleanup procedure.

References and source boundary

The article preserves the source's feature restrictions and version requirements. Reconfirm them against the service and CLI version you deploy; no Azure resources or source commands were run to verify this publication.

Resources

No standalone companion files are distributed for this topic. Use the in-page examples and review the editorial notes below for source availability.

Editorial notes

This page consolidates the following source documents into an English technical guide:

  • AKS Artifact Streaming (Linux) Deployment Guide
  • Private environment identifiers are replaced with input variables; no original environment values or private source links are published.
  • The repository root README is only an index and adds no technical procedure.
  • No standalone YAML resource exists in this source folder, so no download has been invented.

No original credentials or private repository links are included. Do not put populated configuration files or copied production outputs back into this public site.