Deploy through Azure Marketplace into buyer-owned AKS
The Bounded Agentic AI Workflow Engine is delivered as an Azure Kubernetes Application extension. It runs inside the buyer’s Azure subscription and AKS cluster, using buyer-controlled networking, PostgreSQL, Blob Storage, identities, secrets and exposure policies.
Azure-native deployment with buyer-controlled state
Marketplace extension, not an entire Azure landing zone
Managed by the offer
The Kubernetes application extension, namespaced workloads, services, model job orchestration and configured runtime bindings.
Prepared by the buyer
AKS, node pools, PostgreSQL, Blob Storage, networking, identity governance, DNS, certificates and external access.
The package uses a system node pool for control-plane workloads and a GPU node pool labelled sku=gpu and tainted sku=gpu:NoSchedule. The buyer selects a supported GPU VM family and ensures that the required capacity and quota are available.
Prepare the Azure landing zone
- Azure subscription with access to the published Marketplace offer
- Existing AKS cluster with appropriate API access and network controls
- System node pool and supported GPU node pool
- Azure Database for PostgreSQL reachable from AKS
- Blob Storage account and required containers
- Azure Workload Identity enabled for the cluster deployment path
- Azure Monitor configuration appropriate to buyer operations
- Permissions to deploy and manage Kubernetes extensions
Connect to the intended buyer cluster
Set only buyer-owned identifiers. Run the remaining command blocks in the same shell so the exported values remain available.
set -euo pipefail
for tool in az kubectl jq curl python3; do
command -v "$tool" >/dev/null 2>&1 || {
echo "Missing required tool: $tool" >&2
exit 1
}
done
read -r -p "Azure subscription ID: " SUBSCRIPTION_ID
read -r -p "AKS resource group: " AKS_RESOURCE_GROUP
read -r -p "AKS cluster name: " AKS_CLUSTER_NAME
read -r -p "Extension resource name [tacr-workflow-mvp]: " EXTENSION_NAME
EXTENSION_NAME="${EXTENSION_NAME:-tacr-workflow-mvp}"
read -r -p "Release namespace [tacr]: " K8S_NAMESPACE
K8S_NAMESPACE="${K8S_NAMESPACE:-tacr}"
export SUBSCRIPTION_ID AKS_RESOURCE_GROUP AKS_CLUSTER_NAME
export EXTENSION_NAME K8S_NAMESPACE
export EXTENSION_TYPE="GolemTech.TacrWorkflowMVP"
export HELM_RELEASE="tacr"
export API_DEPLOYMENT="${HELM_RELEASE}-tacr-platform-api"
export API_SERVICE="${HELM_RELEASE}-tacr-platform-api"
export WORKLOAD_SERVICE_ACCOUNT="${EXTENSION_NAME}-workload"
az login
az account set --subscription "$SUBSCRIPTION_ID"
az account show \
--query '{subscription:name,id:id,tenant:tenantId}' \
--output table
az aks get-credentials \
--resource-group "$AKS_RESOURCE_GROUP" \
--name "$AKS_CLUSTER_NAME" \
--overwrite-existing
kubectl cluster-infoConfirm the package label and taint contract
Before deployment, verify that the selected node pool carries the label and taint expected by the Marketplace package.
set -euo pipefail
read -r -p "GPU node pool name: " GPU_NODEPOOL_NAME
export GPU_NODEPOOL_NAME
az aks nodepool show \
--resource-group "$AKS_RESOURCE_GROUP" \
--cluster-name "$AKS_CLUSTER_NAME" \
--name "$GPU_NODEPOOL_NAME" \
--query '{name:name,vmSize:vmSize,count:count,nodeLabels:nodeLabels,nodeTaints:nodeTaints,provisioningState:provisioningState}' \
--output yaml
kubectl get nodes \
-l "kubernetes.azure.com/agentpool=$GPU_NODEPOOL_NAME" \
-L sku
gpu_nodes="$(mktemp)"
kubectl get nodes \
-l "kubernetes.azure.com/agentpool=$GPU_NODEPOOL_NAME" \
-o json > "$gpu_nodes"
jq -e '.items | length > 0' "$gpu_nodes" >/dev/null
jq -e 'all(.items[]; .metadata.labels.sku == "gpu")' "$gpu_nodes" >/dev/null
jq -e 'all(.items[]; any(.spec.taints[]?; .key == "sku" and .value == "gpu" and .effect == "NoSchedule"))' "$gpu_nodes" >/dev/null
rm -f "$gpu_nodes"Deploy from the published Azure offer
- Open the Azure Marketplace offer and select the intended subscription and deployment resource group.
- Select the existing AKS cluster and use the same extension resource name entered in the terminal context. The default is tacr-workflow-mvp.
- Use the same release namespace entered in the terminal context, then provide the PostgreSQL host, database and user, Blob Storage resource ID and container names.
- Enter the database password and API authentication key only in the protected Marketplace fields.
- Use the configuration fields presented by the offer to select the system and GPU node pools, the supported GPU option and the API exposure mode.
- Review the Azure deployment summary, then create the extension and wait for reconciliation to complete.
Verify extension reconciliation and AKS workloads
After the portal deployment completes, inspect the extension state and wait for the API deployment to become ready.
set -euo pipefail
if az extension show --name k8s-extension >/dev/null 2>&1; then
az extension update --name k8s-extension
else
az extension add --name k8s-extension
fi
az k8s-extension show \
--cluster-type managedClusters \
--cluster-name "$AKS_CLUSTER_NAME" \
--resource-group "$AKS_RESOURCE_GROUP" \
--name "$EXTENSION_NAME" \
--query '{name:name,extensionType:extensionType,version:version,provisioningState:provisioningState,releaseNamespace:releaseNamespace}' \
--output table
kubectl -n "$K8S_NAMESPACE" get deploy,pods,jobs,svc -o wide
kubectl -n "$K8S_NAMESPACE" rollout status \
deployment/"$API_DEPLOYMENT" \
--timeout=15mConfirm GPU resources after extension deployment
The package may install or reconcile the supported GPU stack. Confirm that the selected nodes advertise GPU resources before launching model training.
set -euo pipefail
kubectl get nodes \
-l "kubernetes.azure.com/agentpool=$GPU_NODEPOOL_NAME" \
-o custom-columns='NAME:.metadata.name,POOL:.metadata.labels.kubernetes\.azure\.com/agentpool,SKU:.metadata.labels.sku,GPU:.status.allocatable.nvidia\.com/gpu,TAINTS:.spec.taints[*].key'
kubectl get daemonset -A \
-o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,DESIRED:.status.desiredNumberScheduled,READY:.status.numberReady' \
| grep -Ei 'nvidia|gpu' || trueConfirm the runtime service-account binding
The Marketplace lifecycle binds the application service account to a buyer-controlled Azure identity. Inspect the service account and pod binding without printing credentials.
set -euo pipefail
kubectl -n "$K8S_NAMESPACE" get serviceaccount "$WORKLOAD_SERVICE_ACCOUNT" \
-o json | jq '{name:.metadata.name,labels:.metadata.labels,annotations:.metadata.annotations}'
kubectl -n "$K8S_NAMESPACE" get deployment "$API_DEPLOYMENT" \
-o jsonpath='{.spec.template.spec.serviceAccountName}{"\n"}'
kubectl -n "$K8S_NAMESPACE" get pods \
-l app.kubernetes.io/component=api \
-o custom-columns='NAME:.metadata.name,SERVICE_ACCOUNT:.spec.serviceAccountName,NODE:.spec.nodeName'Verify the internal service on port 8080
The service remains internal unless the buyer explicitly configures ingress. Use a local port-forward to check /healthz and /readyz.
set -euo pipefail
export LOCAL_PORT="$(
python3 - <<'PYPORT'
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind(("127.0.0.1", 0))
print(sock.getsockname()[1])
PYPORT
)"
kubectl -n "$K8S_NAMESPACE" port-forward \
service/"$API_SERVICE" \
"$LOCAL_PORT:8080" > "${TMPDIR:-/tmp}/tacr-port-forward.log" 2>&1 &
PORT_FORWARD_PID=$!
trap 'kill "$PORT_FORWARD_PID" 2>/dev/null || true' EXIT
for attempt in $(seq 1 30); do
if curl -fsS "http://127.0.0.1:$LOCAL_PORT/healthz" >/dev/null; then
break
fi
sleep 2
done
curl -fsS "http://127.0.0.1:$LOCAL_PORT/healthz"
curl -fsS "http://127.0.0.1:$LOCAL_PORT/readyz"From executable workflow topology to governed inference
The approved customer workflow topology is incorporated into model adaptation, producing a policy-bound model artifact with a structurally bounded workflow action space. The artifact must complete mandatory qualification before it can be deployed for governed inference.
Policy and topology
Customer-defined states, admissible transitions and evidence requirements become executable workflow topology.
Policy-constrained model adaptation
The managed GPU job creates an artifact specific to the approved workflow inside the buyer environment.
Qualification before deployment
A trained artifact cannot create a production inference deployment until the complete policy-bound model is qualified.
Governed inference
The qualified artifact performs inference within the bounded action space. Governance is embedded in model adaptation, not applied after generation.
Update or remove the Kubernetes application extension
Update to a published extension version
Use only a version published for the Marketplace offer. Azure reconciles the managed extension after the update.
set -euo pipefail
read -r -p "Published extension version to install: " TARGET_EXTENSION_VERSION
az k8s-extension update \
--cluster-type managedClusters \
--cluster-name "$AKS_CLUSTER_NAME" \
--resource-group "$AKS_RESOURCE_GROUP" \
--name "$EXTENSION_NAME" \
--version "$TARGET_EXTENSION_VERSION" \
--auto-upgrade-minor-version false
az k8s-extension show \
--cluster-type managedClusters \
--cluster-name "$AKS_CLUSTER_NAME" \
--resource-group "$AKS_RESOURCE_GROUP" \
--name "$EXTENSION_NAME" \
--query '{version:version,provisioningState:provisioningState}' \
--output tableRemove the extension
This removes extension-managed Kubernetes workloads. PostgreSQL, Blob Storage, identities, networking and other buyer resources are not deleted.
set -euo pipefail
read -r -p "Type REMOVE to delete the Kubernetes application extension: " CONFIRM
if [ "$CONFIRM" != "REMOVE" ]; then
echo "Removal cancelled."
exit 1
fi
az k8s-extension delete \
--cluster-type managedClusters \
--cluster-name "$AKS_CLUSTER_NAME" \
--resource-group "$AKS_RESOURCE_GROUP" \
--name "$EXTENSION_NAME"
kubectl -n "$K8S_NAMESPACE" get allControls retained by the buyer
| Control | Buyer responsibility | Runtime behavior |
|---|---|---|
| Identity | Managed identities, federated credentials, Azure RBAC and Kubernetes RBAC | Workloads use the bound Azure Workload Identity |
| Secrets | Protected Marketplace settings, Key Vault integration where selected and Kubernetes secret policy | Sensitive values are not required in public Helm values |
| Networking | AKS API access, private endpoints, NSGs, DNS, certificates and ingress | The Kubernetes service remains internal by default |
| Data | Policies, workflow state, training inputs, model artifacts and operational records | PostgreSQL and Blob Storage remain in the buyer subscription |
Escalate with sanitized operational context
For product deployment issues, provide the offer version, Azure Region, AKS version, extension provisioning state, failing command, sanitized Kubernetes events and UTC timestamps. Remove subscription IDs, tenant IDs, identity client IDs, private endpoints, tokens, passwords, request data and customer information before sharing logs.
Use Azure Support for underlying Azure service or Marketplace entitlement issues. Contact Golem Technologies for extension behavior, training, qualification, inference or application support.