From 4bd5b1de2d7d9351c8ad66a8fdb5c08ef1866b04 Mon Sep 17 00:00:00 2001 From: Paolo Salvatori Date: Thu, 6 Aug 2026 15:30:34 +0200 Subject: [PATCH] Mermaid diagrams: drop the yellow subgraph fill, add CCM and Gateway API diagrams Every subgraph rendered with mermaid's default cluster fill (#ffffde), a pale yellow that fights the page in both GitHub themes. All five existing diagrams now set clusterBkg to transparent, so a subgraph keeps its border and label and takes the page background in light and dark mode alike. Adds diagrams to the two tutorials that had none: the cloud controller manager reconciling Services into node-resource-group load balancers, public IPs and NSG rules, and the Gateway API tutorial where the managed add-on supplies only the CRDs while NGINX Gateway Fabric claims the GatewayClass and serves the traffic. Every diagram in the repository was rendered with the mermaid CLI before committing: 7 of 7 render, and no rendered SVG carries the yellow any more. Co-Authored-By: Claude Opus 5 --- tutorials/bicep/tags-labels-taints/README.md | 1 + tutorials/ccm/scripts/README.md | 37 +++++++++++++++++++ tutorials/gateway-api/scripts/README.md | 35 ++++++++++++++++++ tutorials/keda/event-hubs/README.md | 1 + tutorials/keda/queue-storage/README.md | 1 + tutorials/keda/service-bus/README.md | 1 + .../terraform/tags-labels-taints/README.md | 1 + 7 files changed, 77 insertions(+) diff --git a/tutorials/bicep/tags-labels-taints/README.md b/tutorials/bicep/tags-labels-taints/README.md index 819ccf0..2649224 100644 --- a/tutorials/bicep/tags-labels-taints/README.md +++ b/tutorials/bicep/tags-labels-taints/README.md @@ -24,6 +24,7 @@ By default the user agent pool carries the `workload=batch` node label, the `ded [main.bicep](main.bicep) is a resource-group-scoped template that composes nine local Bicep modules (`deploy.sh` creates the `local-rg` resource group first): ```mermaid +%%{init: {'themeVariables': {'clusterBkg': 'transparent', 'clusterBorder': '#8c8c8c'}}}%% graph TD LA[module logAnalytics] --> ACR[module containerRegistry] LA --> KV[module keyVault] diff --git a/tutorials/ccm/scripts/README.md b/tutorials/ccm/scripts/README.md index e03f619..b40a3f2 100644 --- a/tutorials/ccm/scripts/README.md +++ b/tutorials/ccm/scripts/README.md @@ -10,6 +10,43 @@ Because the emulated load balancer has no real dataplane, the `EXTERNAL-IP` is a > **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 cloud controller manager turns Kubernetes `Service` objects into Azure load-balancer resources in the node resource group, and writes the assigned address back onto the Service: + +```mermaid +%%{init: {'themeVariables': {'clusterBkg': 'transparent', 'clusterBorder': '#8c8c8c'}}}%% +flowchart LR + subgraph aks["AKS cluster"] + subgraph kubesystem["kube-system"] + ccm["cloud-controller-manager"] + cnm["cloud-node-manager"] + end + subgraph appns["test namespace"] + svcpub["Service
type LoadBalancer"] + svcint["Service
internal annotation"] + backend["backend Deployment"] + end + end + + subgraph noderg["node resource group MC_*"] + lb["kubernetes
load balancer"] + lbint["kubernetes-internal
load balancer"] + pip["public IP address"] + nsg["network security group"] + end + + svcpub -.->|"watched by"| ccm + svcint -.->|"watched by"| ccm + ccm -->|"frontend, rule, backend pool"| lb + ccm -->|"private frontend"| lbint + ccm -->|"allocates"| pip + ccm -->|"Allow rule per loadBalancerSourceRanges"| nsg + ccm -->|"writes EXTERNAL-IP back"| svcpub + cnm -->|"labels and addresses nodes"| aks + lb -.->|"backend pool targets"| backend +``` + ## Prerequisites - An AKS cluster reachable through `kubectl`, created by [scripts/01-user-assigned-managed-identity.sh](../../../scripts/01-user-assigned-managed-identity.sh). The scripts do not create the cluster; they source `./00-variables.sh`, whose values must match it (`local-aks-test` in resource group `local-rg`, location `ItalyNorth`). diff --git a/tutorials/gateway-api/scripts/README.md b/tutorials/gateway-api/scripts/README.md index a8d5493..5edcba1 100644 --- a/tutorials/gateway-api/scripts/README.md +++ b/tutorials/gateway-api/scripts/README.md @@ -18,6 +18,41 @@ This tutorial enables the Managed Gateway API on an AKS cluster (or the [LocalSt The cluster-creation scripts already enable the Managed Gateway API at create time, so `01-enable-gateway-api.sh` is idempotent: on such a cluster it detects the installation and leaves it in place. It still runs cleanly on a cluster created without it, enabling it through the live `az aks update` path. +## Architecture + +The Managed Gateway API add-on installs only the CRDs; NGINX Gateway Fabric is the implementation that claims the `GatewayClass` and serves the traffic: + +```mermaid +%%{init: {'themeVariables': {'clusterBkg': 'transparent', 'clusterBorder': '#8c8c8c'}}}%% +flowchart LR + client(["curl -H 'Host: echo.local'"]) + + subgraph aks["AKS cluster"] + crds["gateway.networking.k8s.io CRDs
installed by the add-on"] + gwclass["GatewayClass nginx"] + + subgraph ngfns["namespace nginx-gateway"] + controller["NGINX Gateway Fabric
controller"] + dataplane["per-Gateway NGINX
data-plane Service and pods"] + end + + subgraph testns["namespace gateway-api-test"] + gw["Gateway
HTTP listener for echo.local"] + route["HTTPRoute
every path of echo.local"] + svc["echo-server
ClusterIP Service"] + deploy["echo-server
Deployment"] + end + end + + crds -.->|"define"| gw + gwclass -.->|"claimed by"| controller + gw -.->|"provisions"| dataplane + route -.->|"attached to"| gw + client -->|"kubectl port-forward"| dataplane + dataplane -->|"routes per HTTPRoute"| svc + svc --> deploy +``` + ## How it works Run the numbered scripts in order. Each one sources [00-variables.sh](00-variables.sh) and is idempotent, so it can be re-run safely. diff --git a/tutorials/keda/event-hubs/README.md b/tutorials/keda/event-hubs/README.md index 4a1bec0..d61c68a 100644 --- a/tutorials/keda/event-hubs/README.md +++ b/tutorials/keda/event-hubs/README.md @@ -13,6 +13,7 @@ This tutorial creates an Event Hubs namespace with one event hub, a dedicated co The producer and the consumer are two workloads in the same Kubernetes namespace inside the AKS cluster. The producer sends events to the event hub, the consumer reads them and records its progress as checkpoints in blob storage, and the KEDA add-on in `kube-system` compares the two to work out the lag that drives the scaling. ```mermaid +%%{init: {'themeVariables': {'clusterBkg': 'transparent', 'clusterBorder': '#8c8c8c'}}}%% flowchart LR subgraph aks["Azure Kubernetes Service cluster"] subgraph kubesystem["kube-system: KEDA add-on"] diff --git a/tutorials/keda/queue-storage/README.md b/tutorials/keda/queue-storage/README.md index ee7e265..0c9414a 100644 --- a/tutorials/keda/queue-storage/README.md +++ b/tutorials/keda/queue-storage/README.md @@ -16,6 +16,7 @@ The KEDA scaler **and** both applications authenticate with the same shared user The producer and the consumer are two workloads in the same Kubernetes namespace inside the AKS cluster, both running as the federated `queue-app` service account. The producer fills the storage queue, the consumer drains it, and the KEDA add-on in `kube-system` reads the queue's depth to decide how many consumer replicas should exist. Every arrow that touches Azure is authenticated with workload identity. ```mermaid +%%{init: {'themeVariables': {'clusterBkg': 'transparent', 'clusterBorder': '#8c8c8c'}}}%% flowchart LR subgraph aks["Azure Kubernetes Service cluster"] subgraph kubesystem["kube-system: KEDA add-on"] diff --git a/tutorials/keda/service-bus/README.md b/tutorials/keda/service-bus/README.md index 1e6ee97..53066a5 100644 --- a/tutorials/keda/service-bus/README.md +++ b/tutorials/keda/service-bus/README.md @@ -15,6 +15,7 @@ The producer and consumer applications themselves use the namespace connection s The producer and the consumer are two workloads in the same Kubernetes namespace inside the AKS cluster. The producer fills the Service Bus queue, the consumer drains it, and the KEDA add-on in `kube-system` reads the queue's depth to decide how many consumer replicas should exist. ```mermaid +%%{init: {'themeVariables': {'clusterBkg': 'transparent', 'clusterBorder': '#8c8c8c'}}}%% flowchart LR subgraph aks["Azure Kubernetes Service cluster"] subgraph kubesystem["kube-system: KEDA add-on"] diff --git a/tutorials/terraform/tags-labels-taints/README.md b/tutorials/terraform/tags-labels-taints/README.md index 01c502d..d7d56fb 100644 --- a/tutorials/terraform/tags-labels-taints/README.md +++ b/tutorials/terraform/tags-labels-taints/README.md @@ -25,6 +25,7 @@ By default the user agent pool carries the `workload=batch` node label, the `ded The root [main.tf](main.tf) composes seven local Terraform modules around a single resource group, then adds the cross-module role assignments and the Managed Gateway API installation that no single module can own: ```mermaid +%%{init: {'themeVariables': {'clusterBkg': 'transparent', 'clusterBorder': '#8c8c8c'}}}%% graph TD RG[azurerm_resource_group] --> LA[module log_analytics] RG --> VNET[module virtual_network]