InfernoSIM Azure

On this page

Run repeatable incident, contract, workflow and agent reliability checks inside your AKS cluster.

The Azure extension operates the open-source InfernoSIM engine through Kubernetes resources. A SimulationRun creates one isolated Job; a SimulationSchedule schedules recurring runs. Input and retained evidence stay in storage you control.

Marketplace certification is in progress. Public purchase access is not yet confirmed. Marketplace availability is determined by the offer shown in Microsoft Marketplace. Documentation and release artifacts alone do not mean that a plan is available for purchase. Compare plans and contact us about availability.

Plans and charges#

PlanCapabilitiesSubmitted USD rate
ProOne-off and scheduled runs, Blob/PVC evidence, Workload Identity and evidence verification.$0.41 per installed cluster-hour
EnterprisePro plus multiple operator replicas, disruption budget, namespace governance, Entra group access and configurable network controls.$2.05 per installed cluster-hour

At 730 installed hours, the rates correspond to $299.30 and $1,496.50. Actual charges depend on billable hours and the currency and price shown at checkout. Azure compute, storage, networking, taxes and any external model/API usage are additional. Billing is tied to the installed extension, not the number of tests executed.

1. Prepare and install#

Prerequisites#

Use a supported AKS cluster with Linux AMD64 nodes, OIDC issuer and Workload Identity enabled. You need permission to install an extension and configure the runner identity and storage. Begin with synthetic incidents in a test namespace. Select the InfernoSIM Azure plan in Marketplace and follow its deployment form when your subscription has access.

The extension uses namespace infernosim-system and runner service account infernosim-azure-runner. Choose one plan per cluster; Pro and Enterprise have distinct extension types and must not be co-installed. A purchase-plan switch is not currently a supported migration procedure.

2. Configure storage and identity#

Provide a user-assigned managed identity, an input Blob container and a separate evidence container. Enable versioning and configure retention according to your requirements. Enabling immutable-storage support alone does not apply a retention policy. Locked retention can prevent deletion until it expires.

Set these values for your environment, then configure a federated identity and container-scoped roles. These commands grant the runner read access to incidents and write access to evidence.

AKS_RG=your-aks-resource-group
AKS_NAME=your-aks-cluster
IDENTITY_RG=your-identity-resource-group
IDENTITY_NAME=your-runner-identity
STORAGE_RG=your-storage-resource-group
STORAGE_ACCOUNT=yourstorageaccount

RUNNER_CLIENT_ID=$(az identity show -g "$IDENTITY_RG" -n "$IDENTITY_NAME" --query clientId -o tsv)
RUNNER_PRINCIPAL_ID=$(az identity show -g "$IDENTITY_RG" -n "$IDENTITY_NAME" --query principalId -o tsv)
OIDC_ISSUER=$(az aks show -g "$AKS_RG" -n "$AKS_NAME" --query oidcIssuerProfile.issuerUrl -o tsv)
STORAGE_ID=$(az storage account show -g "$STORAGE_RG" -n "$STORAGE_ACCOUNT" --query id -o tsv)

az identity federated-credential create \
  -g "$IDENTITY_RG" --identity-name "$IDENTITY_NAME" \
  --name infernosim-runner --issuer "$OIDC_ISSUER" \
  --subject system:serviceaccount:infernosim-system:infernosim-azure-runner \
  --audiences api://AzureADTokenExchange

kubectl annotate serviceaccount infernosim-azure-runner \
  -n infernosim-system azure.workload.identity/client-id="$RUNNER_CLIENT_ID" --overwrite

az role assignment create --assignee-object-id "$RUNNER_PRINCIPAL_ID" \
  --assignee-principal-type ServicePrincipal --role 'Storage Blob Data Reader' \
  --scope "$STORAGE_ID/blobServices/default/containers/incidents"
az role assignment create --assignee-object-id "$RUNNER_PRINCIPAL_ID" \
  --assignee-principal-type ServicePrincipal --role 'Storage Blob Data Contributor' \
  --scope "$STORAGE_ID/blobServices/default/containers/evidence"

Use the same client ID in the extension's Workload Identity setting so future reconciliation preserves it. A different run namespace requires a service account and federation subject for that namespace. Blob URLs must use HTTPS and must not contain SAS tokens, credentials or query strings. PVC input/output is available for workflows that do not use Blob.

3. Prepare an encrypted incident#

Start with our synthetic health-check fixture: one recorded GET /health response on the reserved example.test domain. It contains no customer data and verification makes no live request. Install the public InfernoSIM v4.0.1 engine, then download and inspect the fixture:

mkdir -p ./fixture
curl -fsS https://tryinferno.space/docs/infernosim-azure/fixtures/v1/incident.json -o ./fixture/incident.json
curl -fsS https://tryinferno.space/docs/infernosim-azure/fixtures/v1/inbound.log -o ./fixture/inbound.log
curl -fsS https://tryinferno.space/docs/infernosim-azure/fixtures/v1/openapi.yaml -o ./fixture/openapi.yaml
infernosim verify ./fixture
Expected result

Expect exit code 0 and replay readiness 100% for this fixture. That is a static safety inspection, not a production-system guarantee. For real incidents, follow the engine's capture and sanitization guide first.

Create a protected local passphrase file through your approved secret workflow. It must contain the exact passphrase bytes with no trailing newline. Seal the fixture and create its Kubernetes Secret without putting the passphrase in command arguments:

PASSPHRASE_FILE=/secure/path/incident-passphrase
export INFERNOSIM_BUNDLE_PASSPHRASE="$(< "$PASSPHRASE_FILE")"
infernosim bundle seal --out certification.inferno ./fixture
unset INFERNOSIM_BUNDLE_PASSPHRASE
kubectl create secret generic incident-passphrase \
  --namespace infernosim-system \
  --from-file=passphrase="$PASSPHRASE_FILE"
az storage blob upload --auth-mode login --account-name "$STORAGE_ACCOUNT" \
  --container-name incidents --name certification.inferno \
  --file ./certification.inferno --overwrite false

The signed-in upload identity needs its own write permission on the input container; the runner's Reader role intentionally does not grant that permission. Use certification.inferno as the filename in the run below. Do not enable shell tracing while handling the passphrase.

Protect the passphrase and decrypted incident.

A trailing newline changes the passphrase. Do not place it in committed YAML, command arguments or support logs. Decrypted content is stored in the Job's ephemeral volume during execution.

4. Run a verification#

Save the following as first-verification.yaml, replace YOUR_ACCOUNT and the incident filename, and set edition: enterprise for an Enterprise installation.

apiVersion: azure.infernosim.dev/v1alpha1
kind: SimulationRun
metadata:
  name: first-verification
  namespace: infernosim-system
spec:
  edition: pro
  mode: verify
  incident:
    blob:
      url: https://YOUR_ACCOUNT.blob.core.windows.net/incidents/example.inferno
  evidence:
    blob:
      containerURL: https://YOUR_ACCOUNT.blob.core.windows.net/evidence
      prefix: first-verification
    retentionDays: 90
  timeout: 10m
  security:
    bundlePassphraseSecretRef:
      name: incident-passphrase
      key: passphrase
kubectl apply -f first-verification.yaml
kubectl wait --for=jsonpath='{.status.phase}'=Succeeded \
  simulationrun/first-verification -n infernosim-system --timeout=12m
kubectl describe simulationrun first-verification -n infernosim-system

verify inspects replay safety; it is not a full target-system replay. Other modes are contract (OpenAPI validation), workflow (causal workflows) and agent-stress (tool and monitor fault cases). Each needs its corresponding specification or command inputs. Inspect the installed resource schema with kubectl explain simulationrun.spec --recursive and use a known synthetic fixture before connecting real dependencies.

5. Inspect results#

A run finishes as Succeeded or Failed. Runs reaching engine execution and successfully uploading evidence produce logs, a run summary, a SHA-256 evidence manifest and the selected mode's reports. Contract, workflow and agent stress modes support JUnit, SARIF and HTML outputs.

For this verify-mode example, expect three evidence files plus the manifest. To produce HTML, JUnit and SARIF reports, create a new run name, set mode: contract and add contractSpecPath: openapi.yaml under spec. Use the same encrypted fixture. If a run fails, inspect its conditions and logs; the success wait above otherwise times out.

Read the actual run ID, then download every file in its prefix using your own storage permissions:

RUN_ID=$(kubectl get simulationrun first-verification -n infernosim-system -o jsonpath='{.status.runID}')
test -n "$RUN_ID"
mkdir -p ./downloaded-evidence
az storage blob download-batch --auth-mode login \
  --account-name "$STORAGE_ACCOUNT" --source evidence \
  --destination ./downloaded-evidence --pattern "first-verification/$RUN_ID/*"
test -f "./downloaded-evidence/first-verification/$RUN_ID/evidence-manifest.json"

Use the bundled evidence verifier#

The verifier is included in the installed runner image; a separate proprietary CLI download is not required. Copy the complete downloaded run directory to run/ on a customer-owned PVC in infernosim-system, preserving subdirectories. Files must be readable by UID/GID 65532. Use your approved storage-copy workflow and detach any uploader before using a single-writer volume.

Download and review the verifier Job script. It reuses the installed synthetic verification Job's runner image, service account and image-pull references, mounts the evidence read-only, and disables service-account token mounting. It does not need your bundle passphrase. The source Job and Pod must still exist; if their one-hour cleanup has expired, create a fresh synthetic verification.

curl -fsS https://tryinferno.space/docs/infernosim-azure/fixtures/v1/verify-evidence-job.sh -o ./verify-evidence-job.sh
# Review the script before executing it. Requires kubectl and jq.
EVIDENCE_PVC=your-evidence-claim EVIDENCE_SUBPATH=run \
  bash ./verify-evidence-job.sh
Expected result

Expected verifier output: Verified 3 evidence files for run .... The script and generated Job have been inspected and tested locally; image acquisition through Marketplace still requires validation. If the cluster cannot pull the installed image, contact support. Never use or request the publisher's registry credentials.

The verifier detects added, removed or modified files relative to the manifest. Protect the manifest and storage with your access and retention controls. Hashes alone are not a digital signature or a compliance certification.

Troubleshooting#

kubectl get simulationruns,simulationschedules,infernopolicies -A
kubectl describe simulationrun RUN -n NAMESPACE
kubectl logs job/JOB -n NAMESPACE
kubectl get events -n NAMESPACE --sort-by=.lastTimestamp

Enterprise controls and limits#

Namespace policies can require approved identities, Blob hosts, encryption and retention declarations. Private Endpoint and customer-managed-key settings are attestations supplied by the operator of the environment. They do not provision or independently verify Azure networking, key rotation or locked storage retention. Configure and validate those controls in Azure.

Multiple operator replicas and a disruption budget improve resilience when the cluster can place them across suitable nodes. They do not by themselves establish zone-failure tolerance. No uptime or regulatory compliance guarantee is implied.

Upgrade and removal#

Use Azure's extension lifecycle for Marketplace installations. Preserve the current version and evidence before an upgrade, then run synthetic acceptance checks. The removal hook stops reconciliation and removes owned executable Jobs and CronJobs. Historical custom resources and external evidence are retained for your retention policy. Resolve a failed cleanup hook before retrying removal.

See release notes and validation scope, or contact support for configuration examples and product help.

Known limitations#