Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Important
AKS preview features are available on a self-service, opt-in basis. Previews are provided "as is" and "as available," and they're excluded from the service-level agreements and limited warranty. AKS previews are partially covered by customer support on a best-effort basis. As such, these features aren't meant for production use. For more information, see the following support articles:
Before you attach a flex node host to your Azure Kubernetes Service (AKS) cluster, install Unbounded-Net, connect the AKS-managed and flex node network locations, and create a flex node pool. Your infrastructure network provides Layer 3 connectivity between the node networks. Unbounded-Net provides pod networking between the two network locations, which Unbounded-Net calls Sites.
Note
If Layer 3 connectivity isn't available, use the topology-specific public AKS cluster with an Unbounded-Net WireGuard gateway lab. That topology isn't the primary workflow. A private AKS cluster with a WireGuard gateway isn't covered by this documentation.
The same Unbounded-Net configuration applies to the public and private AKS API access paths prepared in the preceding article.
Run the commands in this article in a Linux-compatible Bash environment that has the required tools and network access. This article calls that environment your Bash environment. The separate machine that joins the cluster is the flex node host.
For a private cluster, your Bash environment must resolve and reach the private API endpoint.
For more information about the two networking layers and customer responsibilities, see Networking concepts for flex nodes and Support policy for flex nodes.
In this article, you:
- Install and verify the Unbounded-Net command-line interface (CLI).
- Install Unbounded-Net and connect the two network locations.
- Verify the networking components and AKS-managed nodes.
- Apply the temporary Kubernetes permissions required by the AKS flex daemon.
- Create and record a flex node pool.
Before you begin
- Complete Plan flex nodes for AKS, including the address plan and environment file.
- Complete Prepare an AKS cluster for flex nodes.
- Use the shared environment file and dedicated kubeconfig created in the preceding articles.
- Use the
aks-previewAzure CLI extension installed in the preceding article. - Use a subscription that's approved for the flex nodes preview.
- Use an Azure account that can update the AKS cluster and create an agent pool.
- Ensure that the Kubernetes identity in the dedicated kubeconfig can install the cluster-scoped resources and workloads required by Unbounded-Net.
- Install Azure CLI,
kubectl,curl, andtarin your Bash environment. - Allow outbound HTTPS access to
github.comfrom your Bash environment to download the Unbounded-Net CLI. - Ensure that the Layer 3 path provides bidirectional reachability between the AKS-managed node network and the flex node host network. Unbounded-Net provides pod routing across this underlay.
- Ensure that you can use
sudoto install the Unbounded-Net CLI in/usr/local/bin.
Load the deployment environment
Start a new Bash session, identify the environment file from the planning article, and load it. Replace <deployment-name> with your deployment label.
export FLEXNODE_DEPLOYMENT="<deployment-name>"
export FLEXNODE_ENV_FILE="${HOME}/.config/aks-flexnode/${FLEXNODE_DEPLOYMENT}.env"
test -s "${FLEXNODE_ENV_FILE}"
source "${FLEXNODE_ENV_FILE}"
export KUBECONFIG="${FLEXNODE_KUBECONFIG}"
install -d -m 0700 "${WORK_DIR:?Load the deployment environment first.}"
The environment file supplies the shared deployment values that this article reads, including WORK_DIR, the directory in your Bash environment where this article stores downloads and generated files. By default, WORK_DIR is ~/.local/share/aksflexnode/<deployment-name>. The article derives any other variables that it needs. If you didn't create the environment file yet, complete Plan your flex nodes deployment first. Don't continue past this step if the shell reports an error.
Set the active subscription and display the Azure and Kubernetes targets:
az account set --subscription "${SUBSCRIPTION_ID}"
az aks show \
--resource-group "${RESOURCE_GROUP}" \
--name "${CLUSTER_NAME}" \
--query "{Cluster:name,ResourceId:id,ApiServer:(privateFqdn || fqdn)}" \
--output table
kubectl cluster-info
kubectl get nodes
Confirm that ResourceId matches AKS_RESOURCE_ID and that the Kubernetes control-plane hostname matches ApiServer. If either value doesn't match, stop and reload the environment file and kubeconfig for the intended cluster.
The AKS-managed node can remain NotReady until you install Unbounded-Net. If a private cluster request times out, verify private DNS resolution, routing, and HTTPS access from your Bash environment.
Install and verify the Unbounded-Net CLI
Download the CLI archive from the release selected in the environment file.
Select the CLI architecture for your Bash environment.
case "$(uname -m)" in x86_64) export UNBOUNDED_ARCH="amd64" ;; aarch64|arm64) export UNBOUNDED_ARCH="arm64" ;; *) printf 'Unsupported workstation architecture: %s\n' \ "$(uname -m)" >&2; false ;; esacCreate a protected download directory and set the release file names.
export UNBOUNDED_INSTALL_DIR="${WORK_DIR}/unbounded-cli-${UNBOUNDED_VERSION}-${UNBOUNDED_ARCH}" export UNBOUNDED_ARTIFACT="kubectl-unbounded-linux-${UNBOUNDED_ARCH}.tar.gz" export UNBOUNDED_ARCHIVE="${UNBOUNDED_INSTALL_DIR}/${UNBOUNDED_ARTIFACT}" install -d -m 0700 "${UNBOUNDED_INSTALL_DIR}"Download the CLI archive.
curl --fail --location --silent --show-error \ --proto '=https' \ --tlsv1.2 \ --retry 3 \ "https://github.com/Azure/unbounded/releases/download/${UNBOUNDED_VERSION}/${UNBOUNDED_ARTIFACT}" \ --output "${UNBOUNDED_ARCHIVE}"Extract and install the CLI.
tar -xzf "${UNBOUNDED_ARCHIVE}" -C "${UNBOUNDED_INSTALL_DIR}" sudo install -m 0755 \ "${UNBOUNDED_INSTALL_DIR}/kubectl-unbounded" \ /usr/local/bin/kubectl-unboundedVerify that
kubectlcan run the installed plugin.command -v kubectl-unbounded kubectl unbounded versionContinue when the commands locate the CLI and return its version information.
Install Unbounded-Net and initialize the sites
An Unbounded-Net site represents a network location:
- The primary cluster site, named
cluster, contains the AKS-managed nodes and usesAKS_NODE_CIDRandAKS_POD_CIDR. - The flex site, named
flex-site, contains the external flex node hosts and usesFLEX_NODE_CIDRandFLEX_POD_CIDR.
The site configuration is independent of whether the AKS API endpoint is public or private. The underlying network must already provide Layer 3 reachability between the two node networks.
Install Unbounded-Net.
kubectl unbounded install \ --timeout 5mInitialize the primary cluster site and flex site with the address ranges from the environment file.
kubectl unbounded site init \ --name flex-site \ --cluster-node-cidr "${AKS_NODE_CIDR}" \ --cluster-pod-cidr "${AKS_POD_CIDR}" \ --node-cidr "${FLEX_NODE_CIDR}" \ --pod-cidr "${FLEX_POD_CIDR}"The
--cluster-*values configure the primary site namedcluster. The--nameand remaining CIDR values configure the flex site namedflex-site.Connect the two sites over the existing Layer 3 path.
kubectl apply -f - <<'EOF' apiVersion: net.unbounded-cloud.io/v1alpha1 kind: SitePeering metadata: name: cluster-flex-private-l3 spec: sites: - cluster - flex-site meshNodes: true tunnelProtocol: Auto EOFmeshNodes: trueenables mesh connectivity between nodes in both sites.tunnelProtocol: Autolets Unbounded-Net select its datapath over the existing network.
Verify networking and AKS-managed nodes
Wait for the Unbounded-Net operator to create the Unbounded-Net controller and node component, and then wait for their rollouts. Installation can return before these resources exist.
kubectl -n unbounded-system wait \ --for=create \ deployment/unbounded-net-controller \ --timeout=5m kubectl -n unbounded-system wait \ --for=create \ daemonset/unbounded-net-node \ --timeout=5m kubectl -n unbounded-system rollout status \ deployment/unbounded-net-controller \ --timeout=5m kubectl -n unbounded-system rollout status \ daemonset/unbounded-net-node \ --timeout=5mWait for the current AKS-managed nodes to become ready.
kubectl wait \ --for=condition=Ready \ nodes \ --all \ --timeout=5mIf an AKS-managed node stays
NotReady, verify thatAKS_SUBNET_CIDRis contained withinAKS_NODE_CIDRand that the AKS node, pod, service, and connected-network ranges don't overlap. Correct the address plan before you continue.Inspect the node-to-Site assignment and Site peering.
kubectl get nodes \ -L net.unbounded-cloud.io/site \ -o wide kubectl get sites,sitepeerings \ -o wide
Confirm the following results:
- Every AKS-managed node is
Readyand is assigned to theclusterSite. - The
clusterandflex-siteSites exist. - The
cluster-flex-private-l3peering reports two Sites and mesh nodes enabled. - The
flex-siteSite has no nodes because you didn't attach a flex node host.
Apply the temporary flex daemon RBAC when required
During preview, verify whether the aks-flex-node-daemon ClusterRole and ClusterRoleBinding already exist. Apply the temporary permissions only when either resource is absent.
The ClusterRoleBinding assigns these permissions to the aks-flex-node-daemons Kubernetes group. If you skip this step, the flex node agent can authenticate during host attachment but exits when its MachineOperation controller cache can't synchronize.
if ! kubectl get clusterrole aks-flex-node-daemon >/dev/null 2>&1 ||
! kubectl get clusterrolebinding aks-flex-node-daemon >/dev/null 2>&1; then
kubectl apply -f - <<'EOF'
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: aks-flex-node-daemon
labels:
kubernetes.azure.com/managedby: aks
rules:
- apiGroups:
- unbounded-cloud.io
resources:
- machineoperations
- machines
verbs:
- get
- list
- watch
- apiGroups:
- unbounded-cloud.io
resources:
- machineoperations/status
verbs:
- get
- patch
- update
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: aks-flex-node-daemon
labels:
kubernetes.azure.com/managedby: aks
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: aks-flex-node-daemon
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: aks-flex-node-daemons
EOF
fi
Continue when both the ClusterRole and ClusterRoleBinding exist.
Create a flex node pool
A flex node pool is a logical grouping for customer-provided compute. Don't add standard AKS node pool settings for node count, VM size, operating system type, or subnet configuration. You attach a prepared host in a later article.
The command sets the per-node pod limit and the maximum number of nodes that can be unavailable during an upgrade.
Use the example pool-generation label to tell the starting pool settings apart from the updated settings you apply later. The pool-generation=initial:NoSchedule taint prevents pods without a matching toleration from being scheduled on the flex nodes.
Create the pool by using Azure CLI:
az aks nodepool add \
--resource-group "${RESOURCE_GROUP}" \
--cluster-name "${CLUSTER_NAME}" \
--name "${FLEX_POOL_NAME}" \
--vm-set-type FlexNodes \
--mode User \
--kubernetes-version "${AKS_VERSION}" \
--max-pods 75 \
--max-unavailable 1 \
--labels pool-generation=initial \
--node-taints pool-generation=initial:NoSchedule \
--output none
Verify and record the flex node pool
Calculate the resource ID and retrieve the pool properties.
export FLEX_POOL_RESOURCE_ID="${AKS_RESOURCE_ID}/agentPools/${FLEX_POOL_NAME}"az resource show \ --ids "${FLEX_POOL_RESOURCE_ID}" \ --api-version 2026-05-02-preview \ --query "{Name:name,ProvisioningState:properties.provisioningState,KubernetesVersion:properties.orchestratorVersion,Type:properties.type}" \ --output tableConfirm that ProvisioningState is
Succeeded, KubernetesVersion matchesAKS_VERSION, and Type isFlexNodes.Record the pool resource ID only after the verification succeeds.
set_flexnode_env FLEX_POOL_RESOURCE_ID "${FLEX_POOL_RESOURCE_ID}"
The pool is now ready for the host preparation and attachment steps.
Next step
Next, prepare a Linux host and configure the Azure identity that the flex node agent uses.