diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox61.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox61.png new file mode 100644 index 000000000..1d61a8401 Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox61.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox610.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox610.png new file mode 100644 index 000000000..351d32dc8 Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox610.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox611.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox611.png new file mode 100644 index 000000000..6e48a0802 Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox611.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox612.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox612.png new file mode 100644 index 000000000..263ab94fb Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox612.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox613.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox613.png new file mode 100644 index 000000000..f785d28b2 Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox613.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox614.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox614.png new file mode 100644 index 000000000..a10f7d6fe Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox614.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox615.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox615.png new file mode 100644 index 000000000..1fe0cc7c1 Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox615.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox616.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox616.png new file mode 100644 index 000000000..7f117435b Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox616.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox62.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox62.png new file mode 100644 index 000000000..360ee1185 Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox62.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox63.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox63.png new file mode 100644 index 000000000..13e812091 Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox63.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox64.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox64.png new file mode 100644 index 000000000..23b7d8bbe Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox64.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox65.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox65.png new file mode 100644 index 000000000..961f623c1 Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox65.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox66.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox66.png new file mode 100644 index 000000000..ce93f6412 Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox66.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox67.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox67.png new file mode 100644 index 000000000..71b5a6b4f Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox67.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox68.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox68.png new file mode 100644 index 000000000..c9cb4c7c5 Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox68.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox69.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox69.png new file mode 100644 index 000000000..b8ecaa2fb Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/images/localbox69.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/manifests/portal-quickstart.yaml b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/manifests/portal-quickstart.yaml new file mode 100644 index 000000000..6ecbe7a63 --- /dev/null +++ b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/manifests/portal-quickstart.yaml @@ -0,0 +1,293 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: aks-container-1-content +data: + health.txt: | + ok + index.html: | + + + + + + AKS Container 1 + + + + + + +
+
+
Running on Kubernetes
+

welcome to AKS container 1 on Azure Local

+

Your container is online and reachable through the cluster load balancer.

+ +
+
+ + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: aks-container-1 + labels: + app.kubernetes.io/name: aks-container-1 +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: aks-container-1 + template: + metadata: + labels: + app.kubernetes.io/name: aks-container-1 + spec: + securityContext: + runAsNonRoot: true + runAsUser: 65532 + runAsGroup: 65532 + fsGroup: 65532 + containers: + - name: web + image: busybox:1.37.0-musl + imagePullPolicy: IfNotPresent + args: + - httpd + - -f + - -p + - "8080" + - -h + - /www + ports: + - name: http + containerPort: 8080 + readinessProbe: + httpGet: + path: /health.txt + port: http + initialDelaySeconds: 1 + periodSeconds: 3 + livenessProbe: + httpGet: + path: /health.txt + port: http + initialDelaySeconds: 3 + periodSeconds: 10 + resources: + requests: + cpu: 5m + memory: 8Mi + limits: + cpu: 50m + memory: 32Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + volumeMounts: + - name: content + mountPath: /www + readOnly: true + volumes: + - name: content + configMap: + name: aks-container-1-content +--- +apiVersion: v1 +kind: Service +metadata: + name: aks-container-1 +spec: + type: LoadBalancer + selector: + app.kubernetes.io/name: aks-container-1 + ports: + - name: http + port: 80 + targetPort: http diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/solution-06.md b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/solution-06.md index 1dedb6ffd..16dc6fa2b 100644 --- a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/solution-06.md +++ b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-06/solution-06.md @@ -296,11 +296,203 @@ This exercise stops at assessment. Leave periodic assessment unchanged; the **En 🔑 **Key insight:** Azure Update Manager provides centralized patch management across Azure VMs and Arc-enabled servers. This is critical for maintaining security compliance in sovereign environments where you need to control when and how updates are applied. + +## Task 5: Deploy a container to the AKS cluster deployed on Azure Local + +### Task 5.1: Verify the AKS Cluster + +The deployed AKS cluster should be setup as **Microsoft Entra authentication with Kubernetes RBAC** in the *Authentication and Authorization* setting + +*Look toward the bottom of the screenshot* + +AKS cluster access configuration using Microsoft Entra authentication and Kubernetes RBAC + +### Task 5.2: Verify Microsoft Entra Authentication + +After the deployment completes: + +1. Open the AKS cluster in the Azure portal. +2. Go to **Kubernetes resources > Workloads**. + +Kubernetes workloads option in the Azure portal + +The cluster system workloads should be visible. + +System workloads running on the AKS cluster + +Seeing these workloads without being asked for a bearer token confirms that: + +- The cluster is configured for Microsoft Entra authentication with Kubernetes RBAC. +- The signed-in user is a member of the assigned `AKSAdmin` group. +- The user has permission to view Kubernetes resources through the Azure portal. + +> **Important:** If the portal requests a bearer token, verify the cluster authentication configuration and confirm that the signed-in user is a direct member of the assigned Microsoft Entra administrator group. + +### Task 5.3 Configure the Load Balancer + +Before deploying the application, configure MetalLB. MetalLB assigns an IP address to Kubernetes Services of type `LoadBalancer`. + +### Task 5.4: Install the MetalLB Extension + +1. Open the AKS cluster. +2. Go to **Settings > Networking**. + +AKS cluster Networking page requesting installation of the MetalLB extension + +3. Select **Install extension**. +4. Select **MetalLB for Azure Arc-enabled Kubernetes**. +5. Wait for the `arcnetworking` extension to report **Succeeded**. + +MetalLB extension installation in the Azure portal + +### Task 5.5: Create the MetalLB Address Pool + +After the extension installation completes, return to **Settings > Networking**. + +AKS Networking page after installing the MetalLB extension + +Select **Add** to create a load-balancer address pool. + +MetalLB address-pool configuration + +Use the following settings: + +| Setting | Value | +|---|---| +| Name | A lowercase name, such as `aks-pool` | +| Advertisement mode | **ARP** | +| IP address range | `10.10.0.150-10.10.0.160` | +| Service selector | Leave blank | + +> **Warning:** The screenshot was captured with `10.10.0.150-10.10.0.160`. It is advisable to not use an overlapping range with the the AKS node allocation pool. + +### Task 5.6: Deploy the Application + +After MetalLB is ready, deploy the application YAML. + +1. Download or open the [`portal-quickstart.yaml`](./manifests/portal-quickstart.yaml) manifest. +2. Go to **Kubernetes resources**. +3. Select **Create from YAML**. + + + +Create from YAML option for the AKS cluster + +YAML editor in the Azure portal + +4. Paste the contents of `portal_quickstart.yaml` into the editor. +5. Select **Apply**. + +The portal first performs a dry run and then creates the Kubernetes resources. + +Successful Kubernetes YAML deployment in the Azure portal + +The deployment should complete quickly. Select the application workload to verify that the pod is running. + +Running application workload on the AKS cluster + +### Task 5.7: Find the Application IP Address + +The application Service receives an external IP address from the MetalLB address pool. + +1. Go to **Kubernetes resources > Services and ingresses**. +2. Open the application Service. +3. Record its **External IP**. + +Kubernetes Service showing its MetalLB external IP address + +> **Note:** The screenshot shows the previously assigned address `10.10.0.150`. With the corrected address pool, the Service will normally receive an address beginning at `10.10.0.50`. Always use the External IP currently displayed for the Service. + +### Task 5.8: Configure Routing on LocalBox-Client + +Before connecting to the application, ensure that `LocalBox-Client` has a route to the AKS network `10.10.0.0/24`. + +#### Review the Azure NIC Effective Routes + +Open the network interface assigned to `LocalBox-Client` and review **Effective routes**. + +Effective routes for the LocalBox-Client Azure network interface + +The Azure NIC effective routes show that the Azure fabric does not provide a usable route to `10.10.0.0/24`. The required route must therefore be configured inside the Windows guest operating system. + +#### Connect to LocalBox-Client + +1. Connect to the `LocalBox-Client` VM using RDP. +2. If required, enable just-in-time access first. +3. Verify that you are using the current public IP address assigned to the VM. + +> **Note:** If you have forgotten the deployment username, check the Bicep parameter file used for the LocalBox deployment. Do not include passwords or secrets in this documentation or commit them to the repository. + +#### Review the Windows Route Table + +Open Command Prompt and run: + +```console +route print +``` + +Windows route table before adding the AKS network route + +The route table does not initially contain a route for the AKS network `10.10.0.0/24`. + +#### Add the Static Route + +Open PowerShell as an administrator and first verify the internal LocalBox adapter and router: + +```powershell +Get-NetIPAddress -AddressFamily IPv4 | + Where-Object IPAddress -eq '192.168.1.20' + +Test-NetConnection 192.168.1.1 +``` + +#### Add the route through the LocalBox router: + +```powershell +$adapter = Get-NetIPAddress -AddressFamily IPv4 | + Where-Object IPAddress -eq '192.168.1.20' + +New-NetRoute ` + -DestinationPrefix '10.10.0.0/24' ` + -InterfaceIndex $adapter.InterfaceIndex ` + -NextHop '192.168.1.1' ` + -RouteMetric 10 +``` + +PowerShell command adding the static route to the AKS network + +#### Verify the new route: + +```powershell +Get-NetRoute -DestinationPrefix '10.10.0.0/24' +``` + +Test connectivity to the External IP currently assigned to the application: + +```powershell +Test-NetConnection 10.10.0.50 -Port 80 +``` + +> **Note:** Replace `10.10.0.50` if the Service displays a different External IP. + +### Task 5.9: Validate the Application + +Open a browser on `LocalBox-Client` and connect to: + +```text +http:// +``` + +The application web page should load. + +Containerized web application reached from LocalBox-Client + + --- -## Task 5: Wrap-up and Discussion +## Task 6: Wrap-up and Discussion -### 5.1 Review Key Learnings +### 6.1 Review Key Learnings After completing this challenge, you should understand: @@ -319,7 +511,16 @@ After completing this challenge, you should understand: - Microsoft Defender for Cloud provides security coverage and recommendations for your VM - Azure Update Manager assesses updates on that same VM without changing shared infrastructure -### 5.2 Real-World Applications +✅ **Deploying a container to your AKS cluster** +- Validated AKS on Azure Local with Microsoft Entra authentication and Kubernetes RBAC +- Installed the MetalLB extension +- Created a MetalLB address pool using ARP advertisement +- Deployed a containerized application from YAML +- Assigned the application an external IP through a Kubernetes `LoadBalancer` Service +- Added the required Windows route on `LocalBox-Client` +- Connected to the application from a browser + +### 6.2 Real-World Applications Consider how these capabilities apply to sovereign cloud scenarios: @@ -331,7 +532,7 @@ Consider how these capabilities apply to sovereign cloud scenarios: | Operational efficiency | Single control plane for hybrid management | | Disaster recovery | Azure Site Recovery integration for failover | -### 5.3 Further Exploration +### 6.3 Further Exploration For additional learning, explore: