-
Notifications
You must be signed in to change notification settings - Fork 22
Aks updated doc #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Aks updated doc #60
Changes from 4 commits
515d543
a79b928
3989057
b7e75a5
b1b071b
5e807e1
aa686e5
e0d8abc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,7 @@ author: mbifeld | |
| ms.author: mbifeld | ||
| ms.topic: article | ||
| ms.date: 11/28/2023 | ||
| ms.custom: innovation-engine | ||
| 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 MY_RESOURCE_GROUP_NAME="myResourceGroup$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: | ||
|
|
||
| <!-- expected_similarity=0.3 --> | ||
|
|
||
| ```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,21 +89,6 @@ 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. | ||
|
|
@@ -209,7 +108,7 @@ Finally, an Ingress resource is created to route traffic to the Azure Vote appli | |
| A test voting app 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,180 +119,50 @@ 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: | ||
|
|
||
| <!-- expected_similarity=0.3 --> | ||
|
|
||
| ```HTML | ||
| <!DOCTYPE html> | ||
| <html xmlns="http://www.w3.org/1999/xhtml"> | ||
| <head> | ||
| <link rel="stylesheet" type="text/css" href="/static/default.css"> | ||
| <title>Azure Voting App</title> | ||
|
|
||
| <script language="JavaScript"> | ||
| function send(form){ | ||
| } | ||
| </script> | ||
|
|
||
| </head> | ||
| <body> | ||
| <div id="container"> | ||
| <form id="form" name="form" action="/"" method="post"><center> | ||
| <div id="logo">Azure Voting App</div> | ||
| <div id="space"></div> | ||
| <div id="form"> | ||
| <button name="vote" value="Cats" onclick="send()" class="button button1">Cats</button> | ||
| <button name="vote" value="Dogs" onclick="send()" class="button button2">Dogs</button> | ||
| <button name="vote" value="reset" onclick="send()" class="button button3">Reset</button> | ||
| <div id="space"></div> | ||
| <div id="space"></div> | ||
| <div id="results"> Cats - 0 | Dogs - 0 </div> | ||
| </form> | ||
| </div> | ||
| </div> | ||
| </body> | ||
| <!doctype html> | ||
| <html lang=""> | ||
| <head> | ||
| <meta charset="utf-8"> | ||
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
| <meta name="viewport" content="width=device-width,initial-scale=1"> | ||
| <link rel="icon" href="/favicon.ico"> | ||
| <title>store-front</title> | ||
| <script defer="defer" src="/js/chunk-vendors.df69ae47.js"></script> | ||
| <script defer="defer" src="/js/app.7e8cfbb2.js"></script> | ||
| <link href="/css/app.a5dc49f6.css" rel="stylesheet"> | ||
| </head> | ||
| <body> | ||
| <div id="app"></div> | ||
| </body> | ||
| </html> | ||
| ``` | ||
|
|
||
| ## 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=$(<cluster-issuer-prod.yml) | ||
| echo "${cluster_issuer_variables//\$SSL_EMAIL_ADDRESS/$SSL_EMAIL_ADDRESS}" | kubectl apply -f - | ||
| ``` | ||
|
|
||
| 5. Upate Voting App Application to use Cert-Manager to obtain an SSL Certificate. | ||
|
|
||
| The full YAML file can be found in `azure-vote-nginx-ssl.yml` | ||
|
|
||
| ```bash | ||
| azure_vote_nginx_ssl_variables=$(<azure-vote-nginx-ssl.yml) | ||
| echo "${azure_vote_nginx_ssl_variables//\$FQDN/$FQDN}" | kubectl apply -f - | ||
| ``` | ||
|
|
||
| <!--## Validate application is working | ||
|
|
||
| Wait for the SSL certificate to issue. The following command will query the | ||
| status of the SSL certificate for 3 minutes. In rare occasions it may take up to | ||
| 15 minutes for Lets Encrypt to issue a successful challenge and | ||
| the ready state to be 'True' | ||
|
|
||
| ```bash | ||
| runtime="10 minute"; endtime=$(date -ud "$runtime" +%s); while [[ $(date -u +%s) -le $endtime ]]; do STATUS=$(kubectl get certificate --output jsonpath={..status.conditions[0].status}); echo $STATUS; if [ "$STATUS" = 'True' ]; then break; else sleep 10; fi; done | ||
| ``` | ||
|
|
||
| Validate SSL certificate is True by running the follow command: | ||
|
|
||
| ```bash | ||
| kubectl get certificate --output jsonpath={..status.conditions[0].status} | ||
| ``` | ||
|
|
||
| Results: | ||
|
|
||
| <!-- expected_similarity=0.3 --> | ||
| <!-- | ||
| ```ASCII | ||
| True | ||
| ``` | ||
| --> | ||
|
|
||
| ## 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" | ||
| ``` | ||
|
|
||
| ## Next Steps | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should tell the user to visit the site at the end once it's ready. Like: echo "You can now visit your web server at $IP_ADDRESS"
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
|
||
| - [Azure Kubernetes Service Documentation](https://learn.microsoft.com/azure/aks/) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we remove this and the kubectl file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done