AWS vs Azure
Nexa is customer-managed and installs on either AWS or Azure. This page is for DataReadyAI engineers maintaining both paths: it lists what actually differs between the clouds and, just as important, what is intentionally the same on both. The two cloud stacks are deliberately kept as close as possible — same Kubernetes, same ingress, same TLS pattern — so most of the platform is cloud-agnostic and only the substrate changes.
The AWS platform is provisioned by aws-iac; the Azure platform by nexa-azure-app-iac. Both use Terragrunt with per-environment environments/{dev,test,prod}.tfvars (driven by TF_VAR_environment), not Terraform workspaces.
What stays the same
Section titled “What stays the same”Regardless of cloud, the runtime is identical: Kubernetes 1.34 running the same container images, with in-cluster Envoy Gateway (Gateway API) behind a cloud load balancer, TLS from cert-manager via Let’s Encrypt DNS-01, GitOps by ArgoCD, and secrets injected by the Secrets Store CSI driver. There is no cloud-native ingress controller (no ALB, no Application Gateway) and no cloud-native certificate service (no ACM) in the request path — that keeps the deploy manifests in nexa-deployments largely cloud-portable. DNS for the Azure environments is delegated from Route53 (<env>.az.nexa-drai.com).
What differs
Section titled “What differs”| Concern | AWS (aws-iac) |
Azure (nexa-azure-app-iac) |
|---|---|---|
| Kubernetes | EKS 1.34 (aws_eks_cluster, managed node groups) |
AKS 1.34 (azurerm_kubernetes_cluster, overlay CNI, KEDA) |
| Pod → cloud identity | EKS Pod Identity (aws_eks_pod_identity_association) |
Workload Identity (azurerm_federated_identity_credential, OIDC issuer + system:serviceaccount:<ns>:<sa> subject) |
| Container registry | ECR, per-service repos (aws-iac-<service>), GitHub-OIDC push |
single ACR Premium (acrnexadev001), AcrPull role on the kubelet identity |
| App database | RDS PostgreSQL 15 (subnet group + SG on 5432) | PostgreSQL Flexible Server 15 (VNet-delegated subnet + private DNS zone) |
| Secrets store | AWS Secrets Manager | Azure Key Vault |
| Config/params | SSM Parameter Store | Key Vault |
| Network | aws_vpc 10.0.0.0/16, public/private subnets, single NAT |
azurerm_virtual_network 10.1.0.0/16, delegated subnets (aks/pe/postgres/dbx), NAT gateway |
| DNS | Route53 (authoritative zone) | Azure DNS zone <env>.az.nexa-drai.com, delegated from Route53 |
| Terraform state | S3 (aws-iac-terraform-state-*, use_lockfile=true) |
Azure Blob (stnexatfstate001 / tfstate) |
| Region (default) | ap-southeast-1 |
australiaeast |
Identity model
Section titled “Identity model”This is the difference to internalize because it shapes every service’s ServiceAccount wiring.
Workloads assume AWS IAM via EKS Pod Identity. aws-iac associates a ServiceAccount with an IAM role through aws_eks_pod_identity_association — there is a reusable per-service module so nexa-backend, nexa-agents-api, nexa-databricks-api, etc. each get scoped access (typically to their Secrets Manager secret). The same mechanism grants cert-manager Route53 access (DNS-01) and gives argocd-image-updater ECR read. GitHub Actions pushes to ECR via a github-oidc provider role, not static keys.
Workloads use AKS Workload Identity. nexa-azure-app-iac creates an azurerm_user_assigned_identity and an azurerm_federated_identity_credential bound to the AKS OIDC issuer with subject system:serviceaccount:<ns>:<sa> and audience api://AzureADTokenExchange, plus an AcrPull role assignment. GitHub Actions authenticates through an azuread_application federated credential, then az acr login. cert-manager uses the azuredns DNS-01 solver.
Databricks provisioning by cloud
Section titled “Databricks provisioning by cloud”If the customer runs Databricks, where the workspace comes from also depends on the cloud:
- On Azure, the Databricks workspace itself is provisioned by
nexa-azure-app-iac(stacks/06-databricks—azurerm_databricks_workspace, VNet-injected, plus an access connector for Unity Catalog). Workspace-level governance (Unity Catalog, warehouses, clusters) is then applied bynexa-azure-databricks-iac(2 stacks), with storage credentials backed by the Azure access connector → ADLS and secret scopes backed by Key Vault. - On AWS, the whole Databricks E2/MWS workspace is built from scratch by
drai-customer-databricks-iac(6 stacks, based on the Databricks Security Reference Architecture):databricks_mws_*resources, S3 + KMS customer-managed keys, PrivateLink, VPC peering to the app VPC, metastore creation, and an optional security-analysis-tool module. Storage credentials are IAM role ARNs → S3; node types arem5/i3(vs Azure’sStandard_D/E-series).
Delivery differences
Section titled “Delivery differences”Both clouds build the same images in GitHub Actions, but publish through different workflows. build-push-ecr.yml (the fuller pipeline — Gitleaks, Trivy, keyless Cosign, SBOM/provenance) targets AWS; build-push-acr.yml targets Azure and is lighter (Trivy via the action, no Gitleaks/Cosign/SBOM). See CI/CD for the full breakdown, and note that image tags follow the same branch-per-env convention on both.