Environment Considerations
These are the main components and considerations you must be aware before starting this tutorial:
- Docker Desktop for Windows up and running with Linux containers. If not already done, activate Windows Subsystem for Linux (WSL). Otherwise, it will be not possible to run containers in Linux. Here are the steps:
1. Open PowerShell as Administrator and run:
Enable-WindowsOptionalFeature
-Online -FeatureName Microsoft-Windows-Subsystem-Linux
2. Restart your computer when prompted.
- Proxy settings configured properly to let us connect from internal network
Background
The tutorial just follows the original one from Microsoft documentation, firstly to check it works fine and secondly to incorporate some further information in some steps.
Tutorial: Prepare an application for Azure Kubernetes Service (AKS)
Deploying a demo app to Azure Kubernetes Service (AKS)
First of all, download the sample code from GitHub Azure samples:
git clone https://github.com/Azure-Samples/azure-voting-app-redis.git
Docker Compose can be used to automate building container images and the deployment of multi-container applications. Use the sample docker-compose.yaml
file to create the container image, download the Redis image, and start the application:
docker-compose up -d
Once completed the previous step, List images with docker images command:
docker images
List running containers with docker ps command:
docker ps
Access to the application in the browser by launching http://127.0.0.1:8080
Here is how it looks like:
Now we have checked the app is running correctly locally, we are going to start to deploy the app to Azure Kubernetes Services (AKS) via Azure Container Services (ACS).
1. Create a new Resource Group (RG). Replace values as you best think it suits to your concrete scenario:
# Set variables
$subscriptionId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$rg = "jm-in-acraks-poc-rg"
$loc = "westeurope"
# Create Resource Group
az group create -n $rg -l $loc
2. Create an instance of Azure Container Registry (ACR). It will be used to store remotely in Azure the images built from docker locally:
az acr create --name $acrName --resource-group $rg --sku Basic
{
"adminUserEnabled": false,
"creationDate": "2020-05-13T07:52:34.557386+00:00",
"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/jm-in-acraks-poc-rg/providers/Microsoft.ContainerRegistry/registries/jmacrpoc",
"location": "westeurope",
"loginServer": "jmacrpoc.azurecr.io",
"name": "jmacrpoc",
"networkRuleSet": null,
"policies": {
"quarantinePolicy": {
"status": "disabled"
},
"retentionPolicy": {
"days": 7,
"lastUpdatedTime": "2020-05-13T07:52:36.241680+00:00",
"status": "disabled"
},
"trustPolicy": {
"status": "disabled",
"type": "Notary"
}
},
"provisioningState": "Succeeded",
"resourceGroup": "jm-in-acraks-poc-rg",
"sku": {
"name": "Basic",
"tier": "Basic"
},
"status": null,
"storageAccount": null,
"tags": {},
"type": "Microsoft.ContainerRegistry/registries"
}
3. Login in to the ACR and tag the container image by using the login server (in my case jmacrpoc.azurecr.io
). The tag for the first version will be "v1":
# Login in to the Azure Container Registry
az acr login --name $acrName
# Tag the image for demo app with the path to the login server for ACR and tag "v1"
# The login server is jmacrpoc.azure.io
docker tag azure-vote-front "$acrName.azurecr.io/azure-vote-front:v1"
4. Push the image to the ACR:
docker push "$acrName.azurecr.io/azure-vote-front:v1"
As little note, you can retrieve your login server information by means of the following command:
# Get the ACR login server
az acr list --resource-group $rg --query "[].{acrLoginServer:loginServer}" --output table
AcrLoginServer
-------------------
jmacrpoc.azurecr.io
5. List images in the ACR to check previous push
action worked fine:
az acr repository list --name $acrName --output table
6. You can display tags associated to the image by using the following command:
# Display the tags for an image
az acr repository show-tags --name $acrName --repository azure-vote-front --output table
7. Create an Azure Kubernetes cluster with several nodes. When creating a new Azure Kubernetes cluster, a service principal is created in order to allow AKS to access other Azure resources. In any case you can specify a custom principal if needed. For simplicity, I will create an Azure Kubernetes cluster with two instances without specifying custom service principals so that a new default one will be created. Note the parameters in yellow:
$aksName = "jm-AKSCluster"
az aks create --resource-group $rg --name $aksName --node-count 2 --generate-ssh-keys --attach-acr $acrName
Here is a fragment of the new AKS just created:
{
"aadProfile": null,
"addonProfiles": null,
"agentPoolProfiles": [
{
"availabilityZones": null,
"count": 2,
"enableAutoScaling": null,
"enableNodePublicIp": null,
"maxCount": null,
"maxPods": 110,
"minCount": null,
"name": "nodepool1",
"nodeTaints": null,
"orchestratorVersion": "1.15.10",
"osDiskSizeGb": 100,
"osType": "Linux",
"provisioningState": "Succeeded",
"scaleSetEvictionPolicy": null,
"scaleSetPriority": null,
"type": "VirtualMachineScaleSets",
"vmSize": "Standard_DS2_v2",
"vnetSubnetId": null
}
],
"apiServerAccessProfile": null,
"dnsPrefix": "jm-AKSClus-jm-in-acraks-poc-98a87a",
"enablePodSecurityPolicy": null,
"enableRbac": true,
"fqdn": "jm-aksclus-jm-in-acraks-poc-98a87a-23a1dad6.hcp.westeurope.azmk8s.io",
"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/jm-in-acraks-poc-rg/providers/Microsoft.ContainerService/managedClusters/jm-AKSCluster",
"identity": null,
"kubernetesVersion": "1.15.10",
"linuxProfile": {
"adminUsername": "azureuser",
"ssh": {
"publicKeys": [
{
"keyData": "ssh-rsa xxxx"
}
]
}
},
"location": "westeurope",
"maxAgentPools": 10,
"name": "jm-AKSCluster",
"networkProfile": {
"dnsServiceIp": "10.0.0.10",
"dockerBridgeCidr": "172.17.0.1/16",
"loadBalancerProfile": {
"effectiveOutboundIps": [
{
"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/MC_jm-in-acraks-poc-rg_jm-AKSCluster_westeurope/providers/Microsoft.Network/publicIPAddresses/5ea8fa53-a668-43d7-84a6-abe9fcc4e0f0",
"resourceGroup": "MC_jm-in-acraks-poc-rg_jm-AKSCluster_westeurope"
}
],
"managedOutboundIps": {
"count": 1
},
"outboundIpPrefixes": null,
"outboundIps": null
},
"loadBalancerSku": "Standard",
"networkPlugin": "kubenet",
"networkPolicy": null,
"podCidr": "10.244.0.0/16",
"serviceCidr": "10.0.0.0/16"
},
"nodeResourceGroup": "MC_jm-in-acraks-poc-rg_jm-AKSCluster_westeurope",
"provisioningState": "Succeeded",
"resourceGroup": "jm-in-acraks-poc-rg",
"servicePrincipalProfile": {
"clientId": "xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"secret": null
},
"tags": null,
"type": "Microsoft.ContainerService/ManagedClusters",
"windowsProfile": null
}
8. Install the Kubernetes CLI if not done yet:
az aks install-cli
Downloading client to "C:\Users\jmuro\.azure-kubectl\kubectl.exe" from "https://storage.googleapis.com/kubernetes-release/release/v1.18.2/bin/windows/amd64/kubectl.exe"
Please add "C:\Users\jmuro\.azure-kubectl" to your search PATH so the `kubectl.exe` can be found. 2 options:
1. Run "set PATH=%PATH%;C:\Users\jmuro\.azure-kubectl" or "$env:path += 'C:\Users\jmuro\.azure-kubectl'" for PowerShell. This is good for the current command session.
2. Update system PATH environment variable by following "Control Panel->System->Advanced->Environment Variables", and re-open the command window. You only need to do it once
9. Connect to AKS cluster using kubectl. Configure and verify connection:
# Configure kubectl to connect to the AKS cluster
az aks get-credentials --resource-group $rg --name $aksName
# Verify the connection to the cluster
kubectl get nodes
NAME STATUS ROLES AGE VERSION
aks-nodepool1-42719967-vmss000000 Ready agent 9m52s v1.15.10
aks-nodepool1-42719967-vmss000001 Ready agent 9m21s v1.15.10
10. Update the reference to the ACR login server in the azure-vote-all-in-one-redis.yaml
deployment file:
Change image: microsoft/azure-vote-front:v1
text by image: jmacrpoc.azurecr.io/azure-vote-front:v1
11. Move to the folder where the deployment file is present and deploy the application to the AKS cluster:
kubectl apply -f azure-vote-all-in-one-redis.yaml
PS C:\Users\jmuro\Source\Repos\Innovation\AKS\azure-voting-app-redis> kubectl apply -f azure-vote-all-in-one-redis.yaml
deployment.apps/azure-vote-back created
service/azure-vote-back created
deployment.apps/azure-vote-front created
service/azure-vote-front created
12. Monitor deployment progress:
kubectl get service azure-vote-front --watch
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
azure-vote-front LoadBalancer 10.0.235.8 51.138.113.5 80:31765/TCP 4m12s
13. Once deployment is completed, test the application with the public returned public address IP:
14. Get the replicas / pods in the AKS cluster:
kubectl get pods
NAME READY STATUS RESTARTS AGE
azure-vote-back-5775d78ff5-lql4f 1/1 Running 0 19m
azure-vote-front-76f674cbb8-t5vk5 1/1 Running 0 19m
15. Change the number of replicas / pods in the AKS cluster. For instance, run the following command to increment the number of replicas for the azure-vote-front app up to 5:
kubectl scale --replicas=5 deployment/azure-vote-front
NAME READY STATUS RESTARTS AGE
azure-vote-back-5775d78ff5-lql4f 1/1 Running 0 29m
azure-vote-front-76f674cbb8-5zw8p 1/1 Running 0 52s
azure-vote-front-76f674cbb8-64wjw 1/1 Running 0 52s
azure-vote-front-76f674cbb8-pclqf 1/1 Running 0 52s
azure-vote-front-76f674cbb8-t5vk5 1/1 Running 0 29m
azure-vote-front-76f674cbb8-vxpg8 1/1 Running 0 52s
16. Now, change the number of nodes in the AKS cluster. For instance, set three nodes (one more node than previous scenario):
# Change the number of nodes manually
az aks scale --resource-group $rg --name $aksName --node-count 3
"agentPoolProfiles": [
{
"availabilityZones": null,
"count": 3,
"enableAutoScaling": null,
"enableNodePublicIp": null,
"maxCount": null,
"maxPods": 110,
"minCount": null,
"name": "nodepool1",
"nodeTaints": null,
"orchestratorVersion": "1.15.10",
"osDiskSizeGb": 100,
"osType": "Linux",
"provisioningState": "Succeeded",
"scaleSetEvictionPolicy": null,
"scaleSetPriority": null,
"type": "VirtualMachineScaleSets",
"vmSize": "Standard_DS2_v2",
"vnetSubnetId": null
}
]
Update the app, rebuild and redeploy to AKS
1. Change the application code and rebuild the image. I've just updated the content of the buttons:
# Change the application code and rebuild the image
docker-compose up --build -d
Building azure-vote-front
Step 1/3 : FROM tiangolo/uwsgi-nginx-flask:python3.6
---> 915b60fc87c3
Step 2/3 : RUN pip install redis
---> Using cache
---> cdc5282ff6ad
Step 3/3 : ADD /azure-vote /app
---> d066f8f71aa3
Successfully built d066f8f71aa3
Successfully tagged azure-vote-front:latest
Recreating azure-vote-front ...
Recreating azure-vote-front ... done
2. Test the app locally with the new built image:
3. Tag the image again with a different value:
docker tag azure-vote-front "$acrName.azurecr.io/azure-vote-front:v2"
4. Push the image to the ACR again with the new tag:
docker push "$acrName.azurecr.io/azure-vote-front:v2"
5. Optionally, update the number of pods for the azure-vote-front
app:
# Update the number of pods if needed
kubectl scale --replicas=2 deployment/azure-vote-front
NAME READY STATUS RESTARTS AGE
azure-vote-back-5775d78ff5-lql4f 1/1 Running 0 68m
azure-vote-front-76f674cbb8-t5vk5 1/1 Running 0 68m
azure-vote-front-76f674cbb8-vxpg8 1/1 Running 0 40m
6. To update the application in AKS, use the kubectl set command. Update <acrLoginServer>
with the login server or host name of your container registry, and specify the tag "v2" as application version:
kubectl set image deployment azure-vote-front azure-vote-front="$acrName.azurecr.io/azure-vote-front:v2"
deployment.extensions/azure-vote-front image updated
7. Get pods within the AKS cluster:
NAME READY STATUS RESTARTS AGE
azure-vote-back-5775d78ff5-lql4f 1/1 Running 0 73m
azure-vote-front-84bccb944f-7spdc 1/1 Running 0 2m10s
azure-vote-front-84bccb944f-9lh47 1/1 Running 0 2m10s
8. Once deployment is completed, get the external IP address of the application:
# Get the external IP address of the azure-vote-front service
kubectl get service azure-vote-front
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
azure-vote-front LoadBalancer 10.0.235.8 51.138.113.5 80:31765/TCP 73m
9. Test the application directly from AKS:
It works!!
References
Tutorial: Prepare an application for Azure Kubernetes Service (AKS)
Quick Tips for environment variables in Windows