diff --git a/scenarios/CreateAKSDeployment/README.md b/scenarios/CreateAKSDeployment/README.md
index c44c30840..c3b52a645 100644
--- a/scenarios/CreateAKSDeployment/README.md
+++ b/scenarios/CreateAKSDeployment/README.md
@@ -4,8 +4,8 @@ description: This tutorial where we will take you step by step in creating an Az
author: mbifeld
ms.author: mbifeld
ms.topic: article
-ms.date: 11/28/2023
-ms.custom: innovation-engine
+ms.date: 04/04/2024
+ms.custom: innovation-engine, linux-related content
---
# Quickstart: Deploy a Scalable & Secure Azure Kubernetes Service cluster using the Azure CLI
@@ -20,18 +20,11 @@ The first step in this tutorial is to define environment variables.
```bash
export RANDOM_ID="$(openssl rand -hex 3)"
-export NETWORK_PREFIX="$(($RANDOM % 254 + 1))"
export SSL_EMAIL_ADDRESS="$(az account show --query user.name --output tsv)"
export MY_RESOURCE_GROUP_NAME="myAKSResourceGroup$RANDOM_ID"
export REGION="westeurope"
export MY_AKS_CLUSTER_NAME="myAKSCluster$RANDOM_ID"
-export MY_PUBLIC_IP_NAME="myPublicIP$RANDOM_ID"
export MY_DNS_LABEL="mydnslabel$RANDOM_ID"
-export MY_VNET_NAME="myVNet$RANDOM_ID"
-export MY_VNET_PREFIX="10.$NETWORK_PREFIX.0.0/16"
-export MY_SN_NAME="mySN$RANDOM_ID"
-export MY_SN_PREFIX="10.$NETWORK_PREFIX.0.0/22"
-export FQDN="${MY_DNS_LABEL}.${REGION}.cloudapp.azure.com"
```
## Create a resource group
@@ -60,96 +53,17 @@ Results:
}
```
-## Create a virtual network and subnet
-
-A virtual network is the fundamental building block for private networks in Azure. Azure Virtual Network enables Azure resources like VMs to securely communicate with each other and the internet.
-
-```bash
-az network vnet create \
- --resource-group $MY_RESOURCE_GROUP_NAME \
- --location $REGION \
- --name $MY_VNET_NAME \
- --address-prefix $MY_VNET_PREFIX \
- --subnet-name $MY_SN_NAME \
- --subnet-prefixes $MY_SN_PREFIX
-```
-
-Results:
-
-
-
-```JSON
-{
- "newVNet": {
- "addressSpace": {
- "addressPrefixes": [
- "10.xxx.0.0/16"
- ]
- },
- "enableDdosProtection": false,
- "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/myAKSResourceGroupxxxxxx/providers/Microsoft.Network/virtualNetworks/myVNetxxx",
- "location": "eastus",
- "name": "myVNetxxx",
- "provisioningState": "Succeeded",
- "resourceGroup": "myAKSResourceGroupxxxxxx",
- "subnets": [
- {
- "addressPrefix": "10.xxx.0.0/22",
- "delegations": [],
- "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/myAKSResourceGroupxxxxxx/providers/Microsoft.Network/virtualNetworks/myVNetxxx/subnets/mySNxxx",
- "name": "mySNxxx",
- "privateEndpointNetworkPolicies": "Disabled",
- "privateLinkServiceNetworkPolicies": "Enabled",
- "provisioningState": "Succeeded",
- "resourceGroup": "myAKSResourceGroupxxxxxx",
- "type": "Microsoft.Network/virtualNetworks/subnets"
- }
- ],
- "type": "Microsoft.Network/virtualNetworks",
- "virtualNetworkPeerings": []
- }
-}
-```
-
-## Register to AKS Azure Resource Providers
-
-Verify Microsoft.OperationsManagement and Microsoft.OperationalInsights providers are registered on your subscription. These are Azure resource providers required to support [Container insights](https://docs.microsoft.com/azure/azure-monitor/containers/container-insights-overview). To check the registration status, run the following commands
-
-```bash
-az provider register --namespace Microsoft.Insights
-az provider register --namespace Microsoft.OperationsManagement
-az provider register --namespace Microsoft.OperationalInsights
-```
-
## Create AKS Cluster
-Create an AKS cluster using the az aks create command with the --enable-addons monitoring parameter to enable Container insights. The following example creates an autoscaling, availability zone enabled cluster.
-
-This will take a few minutes.
+Create an AKS cluster use the az aks create command. The following example creates a cluster named myAKSCluster with one node and enables a system-assigned managed identity. This will take a few minutes.
```bash
-export MY_SN_ID=$(az network vnet subnet list --resource-group $MY_RESOURCE_GROUP_NAME --vnet-name $MY_VNET_NAME --query "[0].id" --output tsv)
-az aks create \
- --resource-group $MY_RESOURCE_GROUP_NAME \
- --name $MY_AKS_CLUSTER_NAME \
- --auto-upgrade-channel stable \
- --enable-cluster-autoscaler \
- --enable-addons monitoring \
- --location $REGION \
- --node-count 1 \
- --min-count 1 \
- --max-count 3 \
- --network-plugin azure \
- --network-policy azure \
- --vnet-subnet-id $MY_SN_ID \
- --no-ssh-key \
- --node-vm-size Standard_DS2_v2 \
- --zones 1 2 3
+az aks create --resource-group $MY_RESOURCE_GROUP_NAME --name $MY_AKS_CLUSTER_NAME --enable-managed-identity --node-count 1 --generate-ssh-keys
```
## Connect to the cluster
-To manage a Kubernetes cluster, use the Kubernetes command-line client, kubectl. kubectl is already installed if you use Azure Cloud Shell.
+To manage a Kubernetes cluster, use the Kubernetes command-line client, kubectl. kubectl is already installed if you use Azure Cloud Shell. To install kubectl locally, call the az aks install-cli command.
1. Install az aks CLI locally using the az aks install-cli command
@@ -175,41 +89,21 @@ To manage a Kubernetes cluster, use the Kubernetes command-line client, kubectl.
kubectl get nodes
```
-## Install NGINX Ingress Controller
-
-```bash
-export MY_STATIC_IP=$(az network public-ip create --resource-group MC_${MY_RESOURCE_GROUP_NAME}_${MY_AKS_CLUSTER_NAME}_${REGION} --location ${REGION} --name ${MY_PUBLIC_IP_NAME} --dns-name ${MY_DNS_LABEL} --sku Standard --allocation-method static --version IPv4 --zone 1 2 3 --query publicIp.ipAddress -o tsv)
-helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
-helm repo update
-helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
- --namespace ingress-nginx \
- --create-namespace \
- --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"=$MY_DNS_LABEL \
- --set controller.service.loadBalancerIP=$MY_STATIC_IP \
- --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
- --wait
-```
-
## Deploy the Application
A Kubernetes manifest file defines a cluster's desired state, such as which container images to run.
-In this quickstart, you will use a manifest to create all objects needed to run the Azure Vote application. This manifest includes two Kubernetes deployments:
-
-- The sample Azure Vote Python applications.
-- A Redis instance.
-
-Two Kubernetes Services are also created:
+In this quickstart, you will use a manifest to create all objects needed to run the AKS Store application. The manifest includes the following Kubernetes deployments and services:
-- An internal service for the Redis instance.
-- An external service to access the Azure Vote application from the internet.
+- **Store front**: Web application for customers to view products and place orders.
+- **Product service**: Shows product information.
+- **Order service**: Places orders.
+- **Rabbit MQ**: Message queue for an order queue.
-Finally, an Ingress resource is created to route traffic to the Azure Vote application.
-
-A test voting app YML file is already prepared. To deploy this app run the following command
+A test store front application YML file is already prepared. To deploy this app run the following command
```bash
-kubectl apply -f azure-vote-start.yml
+kubectl apply -f aks-store-quickstart.yml
```
## Test The Application
@@ -220,20 +114,25 @@ Validate that the application is running by either visiting the public ip or the
> It often takes 2-3 minutes for the PODs to be created and the site to be reachable via HTTP
```bash
-runtime="5 minute";
-endtime=$(date -ud "$runtime" +%s);
-while [[ $(date -u +%s) -le $endtime ]]; do
- STATUS=$(kubectl get pods -l app=azure-vote-front -o 'jsonpath={..status.conditions[?(@.type=="Ready")].status}'); echo $STATUS;
- if [ "$STATUS" == 'True' ]; then
- break;
+runtime="5 minute"
+endtime=$(date -ud "$runtime" +%s)
+while [[ $(date -u +%s) -le $endtime ]]
+do
+ STATUS=$(kubectl get pods -l app=store-front -o 'jsonpath={..status.conditions[?(@.type=="Ready")].status}')
+ echo $STATUS
+ if [ "$STATUS" == 'True' ]
+ then
+ export IP_ADDRESS=$(kubectl get service store-front --output 'jsonpath={..status.loadBalancer.ingress[0].ip}')
+ echo "Service IP Address: $IP_ADDRESS"
+ break
else
- sleep 10;
- fi;
+ sleep 10
+ fi
done
```
```bash
-curl "http://$FQDN"
+curl $IP_ADDRESS
```
Results:
@@ -241,157 +140,26 @@ Results:
```HTML
-
-
-
-
- Azure Voting App
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ store-front
+
+
+
+
+
+
+
```
-## Add HTTPS termination to custom domain
-
-At this point in the tutorial you have an AKS web app with NGINX as the Ingress controller and a custom domain you can use to access your application. The next step is to add an SSL certificate to the domain so that users can reach your application securely via HTTPS.
-
-## Set Up Cert Manager
-
-In order to add HTTPS we are going to use Cert Manager. Cert Manager is an open source tool used to obtain and manage SSL certificate for Kubernetes deployments. Cert Manager will obtain certificates from a variety of Issuers, both popular public Issuers as well as private Issuers, and ensure the certificates are valid and up-to-date, and will attempt to renew certificates at a configured time before expiry.
-
-1. In order to install cert-manager, we must first create a namespace to run it in. This tutorial will install cert-manager into the cert-manager namespace. It is possible to run cert-manager in a different namespace, although you will need to make modifications to the deployment manifests.
-
- ```bash
- kubectl create namespace cert-manager
- ```
-
-2. We can now install cert-manager. All resources are included in a single YAML manifest file. This can be installed by running the following:
-
- ```bash
- kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.7.0/cert-manager.crds.yaml
- ```
-
-3. Add the certmanager.k8s.io/disable-validation: "true" label to the cert-manager namespace by running the following. This will allow the system resources that cert-manager requires to bootstrap TLS to be created in its own namespace.
-
- ```bash
- kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true
- ```
-
-## Obtain certificate via Helm Charts
-
-Helm is a Kubernetes deployment tool for automating creation, packaging, configuration, and deployment of applications and services to Kubernetes clusters.
-
-Cert-manager provides Helm charts as a first-class method of installation on Kubernetes.
-
-1. Add the Jetstack Helm repository
-
- This repository is the only supported source of cert-manager charts. There are some other mirrors and copies across the internet, but those are entirely unofficial and could present a security risk.
-
- ```bash
- helm repo add jetstack https://charts.jetstack.io
- ```
-
-2. Update local Helm Chart repository cache
-
- ```bash
- helm repo update
- ```
-
-3. Install Cert-Manager addon via helm by running the following:
-
- ```bash
- helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.7.0
- ```
-
-4. Apply Certificate Issuer YAML File
-
- ClusterIssuers are Kubernetes resources that represent certificate authorities (CAs) that are able to generate signed certificates by honoring certificate signing requests. All cert-manager certificates require a referenced issuer that is in a ready condition to attempt to honor the request.
- The issuer we are using can be found in the `cluster-issuer-prod.yml file`
-
- ```bash
- cluster_issuer_variables=$(
-
-
-## Browse your AKS Deployment Secured via HTTPS
-
-Run the following command to get the HTTPS endpoint for your application:
-
-> [!Note]
-> It often takes 2-3 minutes for the SSL certificate to propogate and the site to be reachable via HTTPS.
-
-```bash
-runtime="5 minute";
-endtime=$(date -ud "$runtime" +%s);
-while [[ $(date -u +%s) -le $endtime ]]; do
- STATUS=$(kubectl get svc --namespace=ingress-nginx ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}');
- echo $STATUS;
- if [ "$STATUS" == "$MY_STATIC_IP" ]; then
- break;
- else
- sleep 10;
- fi;
-done
-```
-
-```bash
-echo "You can now visit your web server at https://$FQDN"
+echo "You can now visit your web server at $IP_ADDRESS"
```
## Next Steps
diff --git a/scenarios/CreateAKSDeployment/aks-store-quickstart.yml b/scenarios/CreateAKSDeployment/aks-store-quickstart.yml
new file mode 100644
index 000000000..f9cf09662
--- /dev/null
+++ b/scenarios/CreateAKSDeployment/aks-store-quickstart.yml
@@ -0,0 +1,226 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: rabbitmq
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: rabbitmq
+ template:
+ metadata:
+ labels:
+ app: rabbitmq
+ spec:
+ nodeSelector:
+ "kubernetes.io/os": linux
+ containers:
+ - name: rabbitmq
+ image: mcr.microsoft.com/mirror/docker/library/rabbitmq:3.10-management-alpine
+ ports:
+ - containerPort: 5672
+ name: rabbitmq-amqp
+ - containerPort: 15672
+ name: rabbitmq-http
+ env:
+ - name: RABBITMQ_DEFAULT_USER
+ value: "username"
+ - name: RABBITMQ_DEFAULT_PASS
+ value: "password"
+ resources:
+ requests:
+ cpu: 10m
+ memory: 128Mi
+ limits:
+ cpu: 250m
+ memory: 256Mi
+ volumeMounts:
+ - name: rabbitmq-enabled-plugins
+ mountPath: /etc/rabbitmq/enabled_plugins
+ subPath: enabled_plugins
+ volumes:
+ - name: rabbitmq-enabled-plugins
+ configMap:
+ name: rabbitmq-enabled-plugins
+ items:
+ - key: rabbitmq_enabled_plugins
+ path: enabled_plugins
+---
+apiVersion: v1
+data:
+ rabbitmq_enabled_plugins: |
+ [rabbitmq_management,rabbitmq_prometheus,rabbitmq_amqp1_0].
+kind: ConfigMap
+metadata:
+ name: rabbitmq-enabled-plugins
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: rabbitmq
+spec:
+ selector:
+ app: rabbitmq
+ ports:
+ - name: rabbitmq-amqp
+ port: 5672
+ targetPort: 5672
+ - name: rabbitmq-http
+ port: 15672
+ targetPort: 15672
+ type: ClusterIP
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: order-service
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: order-service
+ template:
+ metadata:
+ labels:
+ app: order-service
+ spec:
+ nodeSelector:
+ "kubernetes.io/os": linux
+ containers:
+ - name: order-service
+ image: ghcr.io/azure-samples/aks-store-demo/order-service:latest
+ ports:
+ - containerPort: 3000
+ env:
+ - name: ORDER_QUEUE_HOSTNAME
+ value: "rabbitmq"
+ - name: ORDER_QUEUE_PORT
+ value: "5672"
+ - name: ORDER_QUEUE_USERNAME
+ value: "username"
+ - name: ORDER_QUEUE_PASSWORD
+ value: "password"
+ - name: ORDER_QUEUE_NAME
+ value: "orders"
+ - name: FASTIFY_ADDRESS
+ value: "0.0.0.0"
+ resources:
+ requests:
+ cpu: 1m
+ memory: 50Mi
+ limits:
+ cpu: 75m
+ memory: 128Mi
+ initContainers:
+ - name: wait-for-rabbitmq
+ image: busybox
+ command: ['sh', '-c', 'until nc -zv rabbitmq 5672; do echo waiting for rabbitmq; sleep 2; done;']
+ resources:
+ requests:
+ cpu: 1m
+ memory: 50Mi
+ limits:
+ cpu: 75m
+ memory: 128Mi
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: order-service
+spec:
+ type: ClusterIP
+ ports:
+ - name: http
+ port: 3000
+ targetPort: 3000
+ selector:
+ app: order-service
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: product-service
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: product-service
+ template:
+ metadata:
+ labels:
+ app: product-service
+ spec:
+ nodeSelector:
+ "kubernetes.io/os": linux
+ containers:
+ - name: product-service
+ image: ghcr.io/azure-samples/aks-store-demo/product-service:latest
+ ports:
+ - containerPort: 3002
+ resources:
+ requests:
+ cpu: 1m
+ memory: 1Mi
+ limits:
+ cpu: 1m
+ memory: 7Mi
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: product-service
+spec:
+ type: ClusterIP
+ ports:
+ - name: http
+ port: 3002
+ targetPort: 3002
+ selector:
+ app: product-service
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: store-front
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: store-front
+ template:
+ metadata:
+ labels:
+ app: store-front
+ spec:
+ nodeSelector:
+ "kubernetes.io/os": linux
+ containers:
+ - name: store-front
+ image: ghcr.io/azure-samples/aks-store-demo/store-front:latest
+ ports:
+ - containerPort: 8080
+ name: store-front
+ env:
+ - name: VUE_APP_ORDER_SERVICE_URL
+ value: "http://order-service:3000/"
+ - name: VUE_APP_PRODUCT_SERVICE_URL
+ value: "http://product-service:3002/"
+ resources:
+ requests:
+ cpu: 1m
+ memory: 200Mi
+ limits:
+ cpu: 1000m
+ memory: 512Mi
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: store-front
+spec:
+ ports:
+ - port: 80
+ targetPort: 8080
+ selector:
+ app: store-front
+ type: LoadBalancer
\ No newline at end of file
diff --git a/scenarios/CreateAKSDeployment/azure-vote-nginx-ssl.yml b/scenarios/CreateAKSDeployment/azure-vote-nginx-ssl.yml
deleted file mode 100644
index 070e20148..000000000
--- a/scenarios/CreateAKSDeployment/azure-vote-nginx-ssl.yml
+++ /dev/null
@@ -1,28 +0,0 @@
----
-# INGRESS WITH SSL PROD
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: vote-ingress
- namespace: default
- annotations:
- kubernetes.io/tls-acme: "true"
- nginx.ingress.kubernetes.io/ssl-redirect: "true"
- cert-manager.io/cluster-issuer: letsencrypt-prod
-spec:
- ingressClassName: nginx
- tls:
- - hosts:
- - $FQDN
- secretName: azure-vote-nginx-secret
- rules:
- - host: $FQDN
- http:
- paths:
- - path: /
- pathType: Prefix
- backend:
- service:
- name: azure-vote-front
- port:
- number: 80
diff --git a/scenarios/CreateAKSDeployment/azure-vote-start.yml b/scenarios/CreateAKSDeployment/azure-vote-start.yml
deleted file mode 100644
index 492a394e7..000000000
--- a/scenarios/CreateAKSDeployment/azure-vote-start.yml
+++ /dev/null
@@ -1,106 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: azure-vote-back
- namespace: default
-spec:
- replicas: 1
- selector:
- matchLabels:
- app: azure-vote-back
- template:
- metadata:
- labels:
- app: azure-vote-back
- spec:
- nodeSelector:
- "kubernetes.io/os": linux
- containers:
- - name: azure-vote-back
- image: docker.io/bitnami/redis:6.0.8
- env:
- - name: ALLOW_EMPTY_PASSWORD
- value: "yes"
- resources:
- requests:
- cpu: 100m
- memory: 128Mi
- limits:
- cpu: 250m
- memory: 256Mi
- ports:
- - containerPort: 6379
- name: redis
----
-apiVersion: v1
-kind: Service
-metadata:
- name: azure-vote-back
- namespace: default
-spec:
- ports:
- - port: 6379
- selector:
- app: azure-vote-back
----
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: azure-vote-front
- namespace: default
-spec:
- replicas: 1
- selector:
- matchLabels:
- app: azure-vote-front
- template:
- metadata:
- labels:
- app: azure-vote-front
- spec:
- nodeSelector:
- "kubernetes.io/os": linux
- containers:
- - name: azure-vote-front
- image: mcr.microsoft.com/azuredocs/azure-vote-front:v1
- resources:
- requests:
- cpu: 100m
- memory: 128Mi
- limits:
- cpu: 250m
- memory: 256Mi
- ports:
- - containerPort: 80
- env:
- - name: REDIS
- value: "azure-vote-back"
----
-apiVersion: v1
-kind: Service
-metadata:
- name: azure-vote-front
- namespace: default
-spec:
- ports:
- - port: 80
- selector:
- app: azure-vote-front
----
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: vote-ingress
- namespace: default
-spec:
- ingressClassName: nginx
- rules:
- - http:
- paths:
- - path: /
- pathType: Prefix
- backend:
- service:
- name: azure-vote-front
- port:
- number: 80
\ No newline at end of file
diff --git a/scenarios/CreateAKSDeployment/cluster-issuer-prod.yml b/scenarios/CreateAKSDeployment/cluster-issuer-prod.yml
deleted file mode 100644
index b235bf7e1..000000000
--- a/scenarios/CreateAKSDeployment/cluster-issuer-prod.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/bash
-#kubectl apply -f - <