> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formae.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy the bookstore on AKS

> An Azure infrastructure pattern, deployed with formae.

A full-stack bookstore webapp on a managed AKS cluster. This example provisions
the cluster itself, it does not assume one already exists. One forma stands up
the Azure infrastructure (resource group, virtual network, AKS subnet, the AKS
managed cluster, and an Azure RBAC role assignment for the calling user), then
deploys the workload onto it (a namespace, config and secret, a backend service
account, an nginx frontend, and a Node.js backend with their services). It spans
two targets: the Azure subscription that provisions the cluster, and the AKS
cluster itself as a Kubernetes target that the app resources land on. The
bookstore ships with the formae Kubernetes plugin examples, so resolve those as
well with `pkl project resolve /opt/pel/formae/examples/formae-plugin-kubernetes`.

```mermaid theme={"languages":{"custom":["/languages/pkl.json"]}}
flowchart LR
  target["azure-target-bookstore"]:::tgt

  subgraph stack["k8s-bookstore-azure"]
    direction LR
    rg["Resource group"]:::res
    vnet["Virtual network"]:::res
    subnet["AKS subnet"]:::res
    aks["AKS cluster"]:::res
    rbac["RBAC role assignment"]:::res
    k8s["k8s-target-azure-bookstore"]:::tgt
    ns["Namespace"]:::res
    feCfg["Frontend ConfigMap"]:::res
    beCfg["Backend ConfigMap"]:::res
    dbSec["DB credentials Secret"]:::res
    beSa["Backend ServiceAccount"]:::res
    feDep["Frontend Deployment"]:::res
    beDep["Backend Deployment"]:::res
    feSvc["Frontend Service"]:::res
    beSvc["Backend Service"]:::res

    rg --> vnet
    rg --> subnet
    vnet --> subnet
    rg --> aks
    aks --> rbac
    aks --> k8s
    rg --> k8s
    k8s --> ns
    ns --> feCfg
    ns --> beCfg
    ns --> dbSec
    ns --> beSa
    ns --> feDep
    ns --> beDep
    ns --> feSvc
    ns --> beSvc
  end

  target --> stack

  classDef tgt fill:#FF8201,stroke:#B25900,color:#ffffff
  classDef res fill:#FFF3E6,stroke:#FF8201,color:#02024B
  style stack fill:#ffffff,stroke:#02024B,stroke-width:2px,stroke-dasharray:6 4,color:#02024B
```

**Deploy.** The cloud is selected by the entry file you apply. Export
`AZURE_SUBSCRIPTION_ID` and `AZURE_PRINCIPAL_ID` (your Azure AD object id) first,
then apply the Azure entry. formae orders the
resources by their dependencies automatically, so the cluster comes up before
the workload lands on it:

```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
formae apply --mode reconcile \
  /opt/pel/formae/examples/formae-plugin-kubernetes/bookstore/azure.pkl
```

**Verify.** Once the command completes, the AKS cluster and the workload are
under management:

```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
formae inventory resources --query="type:AZURE::ContainerService::ManagedCluster"
```

**Tear down.** Remove the workload and the cluster it runs on:

```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
formae destroy --on-dependents=cascade \
  /opt/pel/formae/examples/formae-plugin-kubernetes/bookstore/azure.pkl
```

The full forma is in the
[bookstore example](https://github.com/platform-engineering-labs/formae-plugin-kubernetes/tree/main/examples/bookstore).
