A short lab for getting an application up and running using Azure Container Service (AKS).
The specific code and commands are collapsed. The intent of this lab is for you to use the "Ref" section to figure out how to do the steps. You can use the collapsed segments AFTER you review the documentation if you get stuck or to verify you did it correctly.
If you do not want to install these tools locally, you could also install them on a Linux or Windows VM in Azure.
You will need to install Docker Community Edition:
It is not required to have any of these tools installed, but you could install them if you want to run some of this locally:
- Azure CLI 2.0: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest
- Node.js: https://nodejs.org/en/
- kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/
Azure CLI 2.0 and kubectl are already installed in Cloud Shell (https://azure.microsoft.com/en-us/features/cloud-shell/) so you could use that.
Provision an "Azure Container Service (AKS)" cluster in Azure using the default parameters:
- Node count: 3
- Node virtual machine size: 3x Standard D2 v2
While the resource provisions, you may move on to provisioning the Azure Container Registry.
Ref:
- https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough-portal
- https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough
- https://docs.microsoft.com/en-us/azure/virtual-machines/linux/mac-create-ssh-keys
- https://docs.microsoft.com/en-us/azure/virtual-machines/linux/ssh-from-windows
- https://docs.microsoft.com/en-us/azure/container-service/kubernetes/container-service-kubernetes-service-principal
Provision an "Azure Container Registry" in Azure using the default parameters:
- Admin user: Enable
- SKU: Standard
Ref:
- https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-portal
- https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-azure-cli
- https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-powershell
Perform the following steps to deploy a simple "Hello World" application:
- Write a Hello World Node.js application that will expose an HTTP endpoint on port 80.
Ref:
Node.js Hello World Code Sample
If you have Node installed, you can provision a new app and install Express:
npm init
npm install express --save
Alternatively, you can simply create the package.json file manually:
{
"name": "hello",
"version": "1.0.0",
"description": "",
"main": "server.js",
"dependencies": {
"express": "^4.16.3"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"author": "",
"license": "ISC"
}
The server.js file could look something like this:
const express = require("express");
const app = express();
app.get("/", (req, res) => {
res.send("Hello World!\n");
});
const port = process.env.PORT || 8800;
app.listen(port, () => {
console.log(`listening on port ${port}...`);
});
You could test locally by:
node server.js
curl http://localhost:8800
- Write a Dockerfile.
Ref:
Dockerfile Sample
FROM node:latest
COPY server.js server.js
COPY package.json package.json
RUN npm install
ENV PORT 80
EXPOSE 80
CMD node server.js
- Build the container image.
Ref:
- https://docs.docker.com/engine/reference/commandline/build
- https://docs.docker.com/engine/reference/run
Build Commands
You can build and view the built images by:
docker build -t hello:latest -t hello:1.0.0 .
docker images
You can test locally by:
docker run -d --name hello --publish 8800:80 hello:latest
curl http://localhost:8800
- Push the container to ACR.
Ref:
- https://docs.microsoft.com/en-us/azure/aks/tutorial-kubernetes-prepare-acr
- https://docs.microsoft.com/en-us/azure/aks/tutorial-kubernetes-deploy-cluster#configure-acr-authentication
- https://docs.docker.com/engine/reference/commandline/tag
- https://docs.docker.com/engine/reference/commandline/push
Push Commands
az login
az acr login --name whatever
docker tag hello:1.0.0 whatever.azurecr.io/hello:1.0.0
docker tag hello:1.0.0 whatever.azurecr.io/hello:latest
docker images
docker push whatever.azurecr.io/hello:latest
docker push whatever.azurecr.io/hello:1.0.0
az acr repository list --name whatever --output table
az acr repository show-tags --name whatever --repository hello --output table
Alternatively, you can login to your ACR like this:
docker login whatever.azurecr.io -u whatever -p password
- Build a YAML file for the deployment.
Ref:
Deployment YAML File Sample
The following is an example deployment hello.yaml file:
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: hello
labels:
app: hello
spec:
replicas: 1
selector:
matchLabels:
app: hello
template:
metadata:
labels:
app: hello
spec:
containers:
- name: hello
image: pelasneacr.azurecr.io/hello:1.0.0
ports:
- containerPort: 80
- Deploy as a single container (1 replica) to Kubernetes.
Ref:
- https://docs.microsoft.com/en-us/azure/aks/tutorial-kubernetes-deploy-cluster
- https://v1-8.docs.kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-a-deployment
Deployment Commands
# login to Kubernetes
az aks get-credentials --resource-group whatever-rg --name whatever
kubectl get nodes
# grant the Kubernetes service principal access to ACR
CLIENT_ID=$(az aks show --resource-group pelasne-aks --name pelasne-aks --query "servicePrincipalProfile.clientId" --output tsv)
ACR_ID=$(az acr show --resource-group pelasne-acr --name pelasneacr --query "id" --output tsv)
az role assignment create --assignee $CLIENT_ID --role Reader --scope $ACR_ID
# create the deployment
kubectl create -f hello.yaml --record --save-config
kubectl get deployments
kubectl rollout status deployment hello
kubectl get rs
kubectl get pods --show-labels
Ref:
- https://kubernetes.io/docs/concepts/services-networking/service
- https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer
- https://github.com/Azure-Samples/azure-voting-app-redis/blob/master/azure-vote-all-in-one-redis.yaml
Deploy Commands
The following is an example hello-expose.yaml file:
apiVersion: v1
kind: Service
metadata:
name: hello
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: hello
Then you can run the following commands:
kubectl create -f hello-expose.yaml --record --save-config
kubectl get service hello --watch
Once you have an external IP it is done. You can then curl or open a browser to that IP and see your response.
Create a new container that responds with "Hello Lab!" instead of "Hello World!".
Ref:
- https://docs.docker.com/engine/reference/commandline/tag
- https://docs.docker.com/engine/reference/commandline/push
Create New Version
After changing the server.js source code, you can:
docker build -t hello:latest -t hello:2.0.0 -t whatever.azurecr.io/hello:latest -t whatever.azurecr.io/hello:2.0.0 .
docker images
docker push whatever.azurecr.io/hello:latest
docker push whatever.azurecr.io/hello:2.0.0
Ref:
- https://v1-8.docs.kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#in-place-updates-of-resources
- https://tachingchen.com/blog/kubernetes-rolling-update-with-deployment
Deploy New Version
One way to do this is to modify the hello.yaml file to change the container image version to 2.0.0 and then:
kubectl apply -f hello.yaml --record
Another way would be to modify the existing deployment by:
kubectl edit deployment hello
- Scale the number of replicas of your container
- Scale the number of Kubernetes nodes
- Deploy a database and setup connectivity between containers