az), kubectl, and Helm.
Part 1 provisions Azure infrastructure (run once per cluster). Part 2 installs the Kubernetes platform components (also once per cluster). Per-workspace deployment is covered on the next page, Deploy workspace and e6data.
Infrastructure requirements
Review these before you begin. They apply whether you create a new VNet (Part 1, Step 1) or reuse an existing one.VNet options
VNet and subnet sizing
With Azure CNI overlay (used here), pods get IPs from the pod CIDR (10.244.0.0/16), not the subnet - so the AKS subnet only needs addresses for nodes, not pods.
Availability zones
e6data spreads workloads across zones for high availability - the engine NodePool lists zones
1, 2, and 3.
Azure quotas (vCPU)
Quota is per VM family, per region. Check and request increases before deploying - increases can take 24–48 hours.
Sponsorship and free subscriptions often start with 0 quota for ARM families - request an increase first if
az aks create fails with a quota or SKU-not-available error.
VM families
The e6data engine is optimized for ARM64 for price-performance. Confirm your region has the chosen families available.
Existing VNet checklist
If you reuse an existing VNet, confirm:- No CIDR overlap between the VNet, pod CIDR (
10.244.0.0/16), service CIDR (172.20.0.0/16), or any peered network. - The AKS subnet has room for your node count (with CNI overlay, pods don’t consume subnet IPs).
- Nodes have outbound internet (a NAT Gateway is recommended).
-
Microsoft.StorageandMicrosoft.ContainerRegistryservice endpoints are enabled on the subnet.
Existing AKS cluster checklist
If you already have an AKS cluster, skip Part 1 Steps 1–3 and verify the cluster meets the requirements below first:
Then skip to Step 4 (cluster identity) and continue through Parts 1 and 2 as written.
Steps 1 and 3 also export variables that later steps use. Run Step 0, then set these for your existing VNet and cluster before continuing:Step 6C.2 also reads the VNet by
${PREFIX}-vnet; substitute your VNet name there if it differs.Part 1 - Azure infrastructure
By the end of this part you will have a VNet with a NAT Gateway, an AKS cluster with OIDC issuer and Workload Identity enabled, a system node pool and an engine node pool strategy, an ADLS Gen2 storage account, and a workspace Managed Identity federated to the e6data service accounts.Step 0: Set variables
Step 1: Create the resource group, VNet, and NAT Gateway
Step 2: Create the AKS cluster
Create the cluster with OIDC issuer and Workload Identity enabled, Azure CNI overlay with Cilium, and an ARM64 system pool taintedCriticalAddonsOnly:
Standard_D2ps_v6is ARM64. All e6data system images are multi-arch; for x86 useStandard_D4as_v5.- The NAT Gateway on the subnet takes precedence for egress even with
--outbound-type loadBalancer. - To use Entra ID (Azure AD) RBAC for cluster auth, append
--enable-aad --enable-azure-rbac --disable-local-accounts --aad-admin-group-object-ids <group-object-id>.
Step 3: Connect and capture cluster outputs
Step 4: Grant the cluster identity network access
The cluster’s control-plane identity needs Network Contributor on the VNet so the Azure cloud provider can manage load balancer backend pools for nodes in your subnet:Step 5: Container registry access
e6data images are pulled frome6labs.azurecr.io. Choose one option and confirm it with your onboarding engineer (they configure the matching side).
Option A - AcrPull role (if e6data grants your kubelet identity access, or you mirror images to your own ACR):
e6operator namespace and the workspace namespace before components install, so create the namespaces now:
e6data-acr-pull wherever the guide notes imagePullSecrets (operator values in Step 2.4, NamespaceConfig in the next page).
Step 6: Engine node pool
Engine pods need a user node pool to scale on. Pick one provisioner. Theworkspace-name label and taint are mandatory - engine pods schedule onto nodes by exactly this label/taint pair.
Option A - Static user node pool (simplest):
6C.1 - Karpenter Managed Identity and roles
6C.2 - Gather cluster values
6C.3 - Bootstrap token
New nodes use this token to join the cluster. It must be in<6-char-id>.<16-char-secret> format:
6C.4 - Install Karpenter
Createkarpenter-values.yaml, substituting the variables set above:
6C.5 - AKSNodeClass and NodePool for engine nodes
The taintworkspace-name=<workspace> is what the e6data engine pods tolerate, so nodes are dedicated to the workspace:
kubernetes.io/arch: arm64with sku-familiesD/E/F/Lmakes Karpenter pick ARM variants. For x86, change arch toamd64.capacity-typeincludesspot; remove it for on-demand only.- A
Warning: use v1beta1.AKSNodeClass insteadmessage is a Karpenter 1.7.x deprecation notice -v1alpha2still works and matches the e6data production templates. Safe to ignore.
Step 7: Create the metadata storage (ADLS Gen2)
e6data stores workspace metadata in an ADLS Gen2 account (hierarchical namespace enabled) with one private container per workspace:abfss://${WORKSPACE_NAME}-metadata@${STORAGE_ACCOUNT}.dfs.core.windows.net/.
Step 8: Create the workspace Managed Identity and federated credentials
All e6data workspace components share one user-assigned Managed Identity, with one federated credential per e6data service account that needs Azure access. The core components are engine and console:When you later enable add-ons (Laminar, Copilot, Metriq), add a federated credential for each of their service accounts against this same identity. The monitoring service account intentionally has no identity binding - it pushes to GreptimeDB with username and password.
Step 9: Role assignments for storage access
Part 1 verification
AKS_OIDC_ISSUER, NODE_RESOURCE_GROUP, ENGINE_IDENTITY_CLIENT_ID, STORAGE_ACCOUNT, and the storage backend URI - the workspace deployment uses them.
Part 2 - Kubernetes platform components
This part installs the cluster-level components: ane6operator NodePool, cert-manager, the e6-operator CRDs, the e6-operator controller, and the service-token verifier secret. Karpenter itself was installed in Part 1 Step 6C. e6data provides the operator chart and CRDs during onboarding.
The recommended layout pins cert-manager and the operator onto dedicated
e6operator nodes (label app: e6operator, taint workload=e6operator). Step 2.1 creates that NodePool if you run Karpenter. If you use static or NAP node pools instead, omit the nodeSelector/tolerations blocks in Steps 2.2 and 2.4 and let the components run on the system pool.Step 2.1: e6-operator NodePool (Karpenter only)
Step 2.2: Install cert-manager
The operator’s admission webhooks get their serving certificates from cert-manager, so it is required:Step 2.3: Install the e6-operator CRDs
The CRDs are applied withkubectl, not Helm, because the combined payload exceeds Helm’s 1 MB release-secret limit. --server-side is required because client-side apply hits the 256 KB annotation limit:
namespaceconfigs, queryrouters, monitoringservices, metadataservices, queryservices, accesstokens, e6catalogs, governances.
Step 2.4: Install the e6-operator controller
Step 2.5: Create the service-token verifier secret
The console authenticatese6_svc_ service tokens against the e6data control plane using a shared verifier secret. The e6-operator reflects this secret into every workspace namespace as <workspace>-cp-verifier.