diff --git a/tutorials/keda/README.md b/tutorials/keda/README.md index 2b257ec..5809c07 100644 --- a/tutorials/keda/README.md +++ b/tutorials/keda/README.md @@ -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
one user-assigned managed identity"] + operator["keda-operator
kube-system, installed by the AKS add-on"] + metrics["keda-metrics-apiserver
kube-system"] + end + + subgraph sb["service-bus"] + sbapp["namespace keda-service-bus-sample
sb-producer Job
sb-consumer Deployment, 0 to 4 replicas"] + sbqueue(["work-items
Service Bus queue"]) + end + + subgraph queue["queue-storage"] + queueapp["namespace keda-queue-storage-sample
queue-producer Job
queue-consumer Deployment, 0 to 4 replicas"] + storagequeue(["jobs
Storage queue"]) + end + + subgraph eh["event-hubs"] + ehapp["namespace keda-event-hubs-sample
eh-producer Job
eh-consumer Deployment, 0 to 4 replicas"] + hub[["events
event hub and its blob checkpoints"]] + end + + uami -.->|"federated to system:serviceaccount:
kube-system:keda-operator"| operator + operator -->|"one external metric per ScaledObject"| metrics + + sbapp <-->|"sends and drains 100 messages
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
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
connection string"| hub + operator -->|"azure-eventhub, per-partition checkpoint lag"| hub + uami -.->|"Azure Event Hubs Data Owner
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): diff --git a/tutorials/key-vault-csi-driver/README.md b/tutorials/key-vault-csi-driver/README.md index dcff0b3..6431b0b 100644 --- a/tutorials/key-vault-csi-driver/README.md +++ b/tutorials/key-vault-csi-driver/README.md @@ -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
ServiceAccount, annotated with the client id"] + wispc["demo-secret-provider-class
SecretProviderClass, clientID"] + wipod["demo-pod
nginx, label azure.workload.identity/use"] + end + + subgraph mins["namespace mi-secret-store-test"] + mispc["demo-secret-provider-class
SecretProviderClass, useVMManagedIdentity"] + mipod["demo-pod
nginx, no service account"] + end + end + + subgraph azure["Azure"] + uami["local-identity-test
user-assigned managed identity, customer-created"] + addonid["azureKeyvaultSecretsProvider
add-on identity, node resource group"] + kv[("local-kv-test
key vault: username, password")] + end + + wisa -.->|"federated credential
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
reads username and password"| kv + addonid -->|"user-assigned-managed-identity sample: Key Vault Administrator
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. diff --git a/tutorials/policies/README.md b/tutorials/policies/README.md index 6e6e621..c7a71e3 100644 --- a/tutorials/policies/README.md +++ b/tutorials/policies/README.md @@ -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
picks --network-policy and --network-dataplane"]) + + subgraph aks["Azure Kubernetes Service cluster, one engine per cluster"] + azure["--network-policy azure
azure data plane
no tutorial in this folder"] + calico["--network-policy calico
azure data plane
calico-system, calico-apiserver"] + cilium["--network-policy cilium
cilium data plane
cilium-agent in kube-system"] + end + + k8spol["networking.k8s.io/v1
NetworkPolicy, applied with kubectl"] + calicopol["projectcalico.org/v3
GlobalNetworkPolicy and NetworkPolicy,
applied with calicoctl"] + ciliumpol["cilium.io/v2
CiliumNetworkPolicy, applied with kubectl"] + + subgraph tutorials["Tutorials"] + calicotut["calico/calico-policy-tutorial
namespace advanced-policy-demo
cluster-wide default-deny, then selective allow"] + egresstut["cilium/egress-tutorial
namespace starwars
FQDN egress: name, pattern, pattern plus port"] + ingresstut["cilium/ingress-tutorial
namespace starwars
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). diff --git a/tutorials/policies/calico/calico-policy-tutorial/README.md b/tutorials/policies/calico/calico-policy-tutorial/README.md index ef60e42..a2088e2 100644 --- a/tutorials/policies/calico/calico-policy-tutorial/README.md +++ b/tutorials/policies/calico/calico-policy-tutorial/README.md @@ -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
google.com"]) + + subgraph aks["Azure Kubernetes Service cluster"] + gnp["default-deny
projectcalico.org/v3 GlobalNetworkPolicy,
cluster-wide: every namespace except kube-system,
calico-system and calico-apiserver"] + + subgraph kubesystem["kube-system"] + dns["kube-dns
excluded from the default deny"] + end + + subgraph demo["namespace advanced-policy-demo"] + access["access
busybox probe pod, run=access"] + svc["nginx
ClusterIP Service, port 80"] + nginx["nginx
Deployment, app=nginx"] + egresspol["allow-busybox-egress
projectcalico.org/v3 NetworkPolicy:
Egress from run=access"] + ingresspol["allow-nginx-ingress
projectcalico.org/v3 NetworkPolicy:
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,
allowed only from 07"| svc + svc --> nginx + access -->|"curl google.com: blocked by 03,
allowed from 05"| internet + access -.->|"DNS resolution: fails under 03,
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). diff --git a/tutorials/policies/cilium/egress-tutorial/README.md b/tutorials/policies/cilium/egress-tutorial/README.md index 64ae643..ba3db06 100644 --- a/tutorials/policies/cilium/egress-tutorial/README.md +++ b/tutorials/policies/cilium/egress-tutorial/README.md @@ -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
DNS proxy and FQDN enforcement"] + dns["kube-dns"] + end + + subgraph starwars["namespace starwars"] + mediabot["mediabot
org=empire, class=mediabot"] + policy["fqdn
CiliumNetworkPolicy, one name
reapplied by 03, 05 and 07"] + end + end + + api(["api.github.com
allowed by 03 matchName,
and by 05 and 07"]) + status(["status.github.com
blocked by 03,
allowed from 05 matchPattern"]) + apex(["github.com, the apex domain
never allowed: *.github.com
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,
which maps each FQDN to its addresses"| agent + mediabot -->|"HTTPS on 443, and HTTP on 80 until 07
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). diff --git a/tutorials/policies/cilium/ingress-tutorial/README.md b/tutorials/policies/cilium/ingress-tutorial/README.md index 39980c5..d8cbbab 100644 --- a/tutorials/policies/cilium/ingress-tutorial/README.md +++ b/tutorials/policies/cilium/ingress-tutorial/README.md @@ -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
L3/L4 identity and L7 HTTP enforcement"] + end + + subgraph starwars["namespace starwars"] + tie["tiefighter
org=empire, class=tiefighter"] + xwing["xwing
org=alliance, class=xwing"] + svc["deathstar
ClusterIP Service, port 80"] + deathstar["deathstar
Deployment, 2 replicas
org=empire, class=deathstar"] + policy["rule1
CiliumNetworkPolicy, one name
reapplied by 07 and 09"] + end + end + + policy -.->|"loaded into"| agent + agent -.->|"enforces ingress to the endpoints matching
org=empire, class=deathstar"| deathstar + tie -->|"POST /v1/request-landing: allowed throughout
PUT /v1/exhaust-port: allowed until 09,
then denied at L7"| svc + xwing -->|"both methods allowed until 07,
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).