Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions tutorials/keda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,53 @@ Start with [service-bus](service-bus/) if you are new to KEDA: it is the scenari

> **Running on LocalStack?** Install the [lstk CLI](https://docs.localstack.cloud/aws/developer-tools/running-localstack/lstk/) and run `lstk az start-interception` to route Azure CLI calls to the emulator. See [Run against LocalStack](../../README.md#run-against-localstack) for the full setup.

## Architecture

The KEDA add-on and the managed identity exist once per cluster, and each tutorial adds its own namespace, event source and role assignment on top of them:

```mermaid
%%{init: {'themeVariables': {'clusterBkg': 'transparent', 'clusterBorder': '#8c8c8c'}}}%%
flowchart LR
subgraph shared["Shared by all three tutorials"]
uami["local-keda-uami-test<br/>one user-assigned managed identity"]
operator["keda-operator<br/>kube-system, installed by the AKS add-on"]
metrics["keda-metrics-apiserver<br/>kube-system"]
end

subgraph sb["service-bus"]
sbapp["namespace keda-service-bus-sample<br/>sb-producer Job<br/>sb-consumer Deployment, 0 to 4 replicas"]
sbqueue(["work-items<br/>Service Bus queue"])
end

subgraph queue["queue-storage"]
queueapp["namespace keda-queue-storage-sample<br/>queue-producer Job<br/>queue-consumer Deployment, 0 to 4 replicas"]
storagequeue(["jobs<br/>Storage queue"])
end

subgraph eh["event-hubs"]
ehapp["namespace keda-event-hubs-sample<br/>eh-producer Job<br/>eh-consumer Deployment, 0 to 4 replicas"]
hub[["events<br/>event hub and its blob checkpoints"]]
end

uami -.->|"federated to system:serviceaccount:<br/>kube-system:keda-operator"| operator
operator -->|"one external metric per ScaledObject"| metrics

sbapp <-->|"sends and drains 100 messages<br/>connection string"| sbqueue
operator -->|"azure-servicebus, activeMessageCount"| sbqueue
uami -.->|"Azure Service Bus Data Owner"| sbqueue
metrics -->|"keda-hpa-sb-scaler scales sb-consumer"| sbapp

queueapp <-->|"sends and drains 100 messages<br/>workload identity"| storagequeue
operator -->|"azure-queue, approximateMessagesCount"| storagequeue
uami -.->|"Storage Queue Data Contributor"| storagequeue
metrics -->|"keda-hpa-queue-scaler scales queue-consumer"| queueapp

ehapp <-->|"sends 100 events, then checkpoints<br/>connection string"| hub
operator -->|"azure-eventhub, per-partition checkpoint lag"| hub
uami -.->|"Azure Event Hubs Data Owner<br/>Storage Blob Data Contributor"| hub
metrics -->|"keda-hpa-eh-scaler scales eh-consumer"| ehapp
```

## One shared managed identity

The `keda-operator` service account exists once, in `kube-system`, and the annotation that binds it to a managed identity therefore applies cluster-wide. So the three tutorials deliberately share a single user-assigned managed identity, `local-keda-uami-test`, declared in [00-variables.sh](00-variables.sh):
Expand Down
44 changes: 44 additions & 0 deletions tutorials/key-vault-csi-driver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,50 @@ If a secret in an external secrets store is updated after the initial deployment

> **Running on LocalStack?** Install the [lstk CLI](https://docs.localstack.cloud/aws/developer-tools/running-localstack/lstk/) and run `lstk az start-interception` to route Azure CLI calls to the emulator. See [Run against LocalStack](../../README.md#run-against-localstack) for the full setup.

## Architecture

The add-on installs one CSI driver and one Azure provider in `kube-system`, and both samples mount the same two secrets from the same key vault. Only the identity the provider authenticates with differs:

```mermaid
%%{init: {'themeVariables': {'clusterBkg': 'transparent', 'clusterBorder': '#8c8c8c'}}}%%
flowchart LR
subgraph aks["Azure Kubernetes Service cluster"]
subgraph kubesystem["kube-system: Azure Key Vault Secrets Provider add-on"]
driver["secrets-store-csi-driver"]
provider["secrets-store-provider-azure"]
end

subgraph wins["namespace wi-secret-store-test"]
wisa["secret-store-sa<br/>ServiceAccount, annotated with the client id"]
wispc["demo-secret-provider-class<br/>SecretProviderClass, clientID"]
wipod["demo-pod<br/>nginx, label azure.workload.identity/use"]
end

subgraph mins["namespace mi-secret-store-test"]
mispc["demo-secret-provider-class<br/>SecretProviderClass, useVMManagedIdentity"]
mipod["demo-pod<br/>nginx, no service account"]
end
end

subgraph azure["Azure"]
uami["local-identity-test<br/>user-assigned managed identity, customer-created"]
addonid["azureKeyvaultSecretsProvider<br/>add-on identity, node resource group"]
kv[("local-kv-test<br/>key vault: username, password")]
end

wisa -.->|"federated credential<br/>system:serviceaccount:wi-secret-store-test:secret-store-sa"| uami
wisa -.->|"identity used by"| wipod
wispc -.->|"read by"| provider
mispc -.->|"read by"| provider
driver -->|"mounts /mnt/secrets read-only"| wipod
driver -->|"mounts /mnt/secrets read-only"| mipod
driver -.->|"delegates each mount to"| provider
provider -.->|"workload-identity sample: exchanges the pod's projected token for"| uami
provider -.->|"user-assigned-managed-identity sample: authenticates as"| addonid
uami -->|"workload-identity sample: Key Vault Administrator<br/>reads username and password"| kv
addonid -->|"user-assigned-managed-identity sample: Key Vault Administrator<br/>reads username and password"| kv
```

## Identity Access Modes

The Azure Key Vault provider for Secrets Store CSI Driver supports more than one way to authenticate to Azure Key Vault. This folder contains two samples, each demonstrating a different identity access mode. Both samples mount the same `username` and `password` secrets into a demo nginx pod, but they differ in how the CSI driver obtains the credentials used to read the secrets from Key Vault.
Expand Down
38 changes: 38 additions & 0 deletions tutorials/policies/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,44 @@ These tutorials each build a policy scenario step by step and verify, from insid

> **Running on LocalStack?** Install the [lstk CLI](https://docs.localstack.cloud/aws/developer-tools/running-localstack/lstk/) and run `lstk az start-interception` to route Azure CLI calls to the emulator. See [Run against LocalStack](../../README.md#run-against-localstack) for the full setup.

## Architecture

The engine is chosen when the cluster is created and cannot be swapped afterwards, so each tutorial only runs on a cluster built for its engine:

```mermaid
%%{init: {'themeVariables': {'clusterBkg': 'transparent', 'clusterBorder': '#8c8c8c'}}}%%
flowchart LR
create(["scripts/01-user-assigned-managed-identity.sh<br/>picks --network-policy and --network-dataplane"])

subgraph aks["Azure Kubernetes Service cluster, one engine per cluster"]
azure["--network-policy azure<br/>azure data plane<br/>no tutorial in this folder"]
calico["--network-policy calico<br/>azure data plane<br/>calico-system, calico-apiserver"]
cilium["--network-policy cilium<br/>cilium data plane<br/>cilium-agent in kube-system"]
end

k8spol["networking.k8s.io/v1<br/>NetworkPolicy, applied with kubectl"]
calicopol["projectcalico.org/v3<br/>GlobalNetworkPolicy and NetworkPolicy,<br/>applied with calicoctl"]
ciliumpol["cilium.io/v2<br/>CiliumNetworkPolicy, applied with kubectl"]

subgraph tutorials["Tutorials"]
calicotut["calico/calico-policy-tutorial<br/>namespace advanced-policy-demo<br/>cluster-wide default-deny, then selective allow"]
egresstut["cilium/egress-tutorial<br/>namespace starwars<br/>FQDN egress: name, pattern, pattern plus port"]
ingresstut["cilium/ingress-tutorial<br/>namespace starwars<br/>identity-aware ingress at L3/L4, then L7 HTTP"]
end

create -->|"chosen at cluster creation"| azure
create --> calico
create --> cilium
k8spol -.->|"enforced by every engine"| azure
k8spol -.-> calico
k8spol -.-> cilium
calicopol -.->|"enforced by"| calico
ciliumpol -.->|"enforced by"| cilium
calico -->|"required by"| calicotut
cilium -->|"required by"| egresstut
cilium -->|"required by"| ingresstut
```

## Prerequisites

- An AKS cluster reachable through `kubectl`, created with the policy engine that matches the tutorial you want to run (Calico for the Calico tutorial, Cilium for the two Cilium tutorials).
Expand Down
34 changes: 34 additions & 0 deletions tutorials/policies/calico/calico-policy-tutorial/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,40 @@ The demo runs in the `advanced-policy-demo` namespace with an `nginx` Deployment

> **Running on LocalStack?** Install the [lstk CLI](https://docs.localstack.cloud/aws/developer-tools/running-localstack/lstk/) and run `lstk az start-interception` to route Azure CLI calls to the emulator. See [Run against LocalStack](../../../../README.md#run-against-localstack) for the full setup.

## Architecture

The cluster-wide default-deny stays in force for the rest of the tutorial; the two namespaced policies then re-open exactly one path through it, one direction at a time:

```mermaid
%%{init: {'themeVariables': {'clusterBkg': 'transparent', 'clusterBorder': '#8c8c8c'}}}%%
flowchart LR
internet(["public internet<br/>google.com"])

subgraph aks["Azure Kubernetes Service cluster"]
gnp["default-deny<br/>projectcalico.org/v3 GlobalNetworkPolicy,<br/>cluster-wide: every namespace except kube-system,<br/>calico-system and calico-apiserver"]

subgraph kubesystem["kube-system"]
dns["kube-dns<br/>excluded from the default deny"]
end

subgraph demo["namespace advanced-policy-demo"]
access["access<br/>busybox probe pod, run=access"]
svc["nginx<br/>ClusterIP Service, port 80"]
nginx["nginx<br/>Deployment, app=nginx"]
egresspol["allow-busybox-egress<br/>projectcalico.org/v3 NetworkPolicy:<br/>Egress from run=access"]
ingresspol["allow-nginx-ingress<br/>projectcalico.org/v3 NetworkPolicy:<br/>Ingress to app=nginx, source run=access"]
end
end

gnp -.->|"03 denies all ingress and egress"| demo
egresspol -.->|"05 re-opens egress, verified by 06"| access
ingresspol -.->|"07 re-opens ingress, verified by 08"| nginx
access -->|"curl nginx: blocked by 03,<br/>allowed only from 07"| svc
svc --> nginx
access -->|"curl google.com: blocked by 03,<br/>allowed from 05"| internet
access -.->|"DNS resolution: fails under 03,<br/>restored by 05"| dns
```

## Prerequisites

- An AKS cluster reachable through `kubectl`, created with the **Calico** network-policy option of [scripts/01-user-assigned-managed-identity.sh](../../../../scripts/01-user-assigned-managed-identity.sh) (the script's menu offers Azure, Cilium, and Calico network policy; pick Calico).
Expand Down
32 changes: 32 additions & 0 deletions tutorials/policies/cilium/egress-tutorial/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,38 @@ It uses the Cilium [Star Wars demo](https://cilium.io/blog/2017/5/4/demo-may-the

> **Running on LocalStack?** Install the [lstk CLI](https://docs.localstack.cloud/aws/developer-tools/running-localstack/lstk/) and run `lstk az start-interception` to route Azure CLI calls to the emulator. See [Run against LocalStack](../../../../README.md#run-against-localstack) for the full setup.

## Architecture

Because Cilium enforces FQDN rules by watching DNS, the `cilium-agent` learns the addresses behind each hostname from the answers `kube-dns` returns to the pod. That is what lets the same `fqdn` policy be tightened three times without touching `mediabot`:

```mermaid
%%{init: {'themeVariables': {'clusterBkg': 'transparent', 'clusterBorder': '#8c8c8c'}}}%%
flowchart LR
subgraph aks["Azure Kubernetes Service cluster, Cilium data plane"]
subgraph kubesystem["kube-system"]
agent["cilium-agent<br/>DNS proxy and FQDN enforcement"]
dns["kube-dns"]
end

subgraph starwars["namespace starwars"]
mediabot["mediabot<br/>org=empire, class=mediabot"]
policy["fqdn<br/>CiliumNetworkPolicy, one name<br/>reapplied by 03, 05 and 07"]
end
end

api(["api.github.com<br/>allowed by 03 matchName,<br/>and by 05 and 07"])
status(["status.github.com<br/>blocked by 03,<br/>allowed from 05 matchPattern"])
apex(["github.com, the apex domain<br/>never allowed: *.github.com<br/>requires a subdomain label"])

policy -.->|"loaded into"| agent
agent -.->|"enforces every egress connection from"| mediabot
mediabot -->|"DNS to port 53, allowed by every policy"| dns
dns -.->|"answers observed by the DNS proxy,<br/>which maps each FQDN to its addresses"| agent
mediabot -->|"HTTPS on 443, and HTTP on 80 until 07<br/>restricts the pattern to 443/TCP"| api
mediabot --> status
mediabot --> apex
```

## Prerequisites

- An AKS cluster reachable through `kubectl`, created with the **Cilium** network-policy option of [scripts/01-user-assigned-managed-identity.sh](../../../../scripts/01-user-assigned-managed-identity.sh) (the script's menu offers Azure, Cilium, and Calico network policy; pick Cilium).
Expand Down
28 changes: 28 additions & 0 deletions tutorials/policies/cilium/ingress-tutorial/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,34 @@ An L7 policy adds an HTTP filter so even empire ships may only call `POST /v1/re

> **Running on LocalStack?** Install the [lstk CLI](https://docs.localstack.cloud/aws/developer-tools/running-localstack/lstk/) and run `lstk az start-interception` to route Azure CLI calls to the emulator. See [Run against LocalStack](../../../../README.md#run-against-localstack) for the full setup.

## Architecture

In Kubernetes terms, the two policies only ever change what the `deathstar` endpoints accept. The client pods are never modified, and the ships are told apart by their labels rather than by their addresses:

```mermaid
%%{init: {'themeVariables': {'clusterBkg': 'transparent', 'clusterBorder': '#8c8c8c'}}}%%
flowchart LR
subgraph aks["Azure Kubernetes Service cluster, Cilium data plane"]
subgraph kubesystem["kube-system"]
agent["cilium-agent<br/>L3/L4 identity and L7 HTTP enforcement"]
end

subgraph starwars["namespace starwars"]
tie["tiefighter<br/>org=empire, class=tiefighter"]
xwing["xwing<br/>org=alliance, class=xwing"]
svc["deathstar<br/>ClusterIP Service, port 80"]
deathstar["deathstar<br/>Deployment, 2 replicas<br/>org=empire, class=deathstar"]
policy["rule1<br/>CiliumNetworkPolicy, one name<br/>reapplied by 07 and 09"]
end
end

policy -.->|"loaded into"| agent
agent -.->|"enforces ingress to the endpoints matching<br/>org=empire, class=deathstar"| deathstar
tie -->|"POST /v1/request-landing: allowed throughout<br/>PUT /v1/exhaust-port: allowed until 09,<br/>then denied at L7"| svc
xwing -->|"both methods allowed until 07,<br/>then dropped at L3: org=alliance"| svc
svc -->|"port 80/TCP"| deathstar
```

## Prerequisites

- An AKS cluster reachable through `kubectl`, created with the **Cilium** network-policy option of [scripts/01-user-assigned-managed-identity.sh](../../../../scripts/01-user-assigned-managed-identity.sh) (the script's menu offers Azure, Cilium, and Calico network policy; pick Cilium).
Expand Down