Host a new database using Azure Cosmos DB
Now that we've reviewed the basic concepts of external states and how to deal with them using Kubernetes, let's create the resources that will support your freight company's application and then create the application itself.
Create a resource group
Important
You need your own Azure subscription to run this exercise, and you might incur charges. If you don't already have an Azure subscription, create a free account before you begin.
Sign into Azure portal using your own subscription.
Open the Cloud Shell and select Bash.
Create an Azure resource group using the
az group create
command and specify a region. This example creates a resource group named rg-ship-manager in the eastus region:az group create --name rg-ship-manager --location eastus
The creation process can take a few moments to complete.
Create the state
As we described earlier, it's possible but not recommended to handle state in Kubernetes. Managing a highly available application state can become too difficult when you need to manage the state yourself.
To solve that problem, we'll externalize the state to an application that specializes in dealing with external state: Azure Cosmos DB.
Note
Although we're creating an Azure Cosmos DB instance as part of the required resources to run the application, Azure Kubernetes Service (AKS) and Azure Cosmos DB are not related to one another.
Create Bash variables to store the Azure Cosmos DB account name and the resource group name for use throughout the rest of the module.
export RESOURCE_GROUP=rg-ship-manager export COSMOSDB_ACCOUNT_NAME=contoso-ship-manager-$RANDOM
Create a new Azure Cosmos DB account using the
az cosmosdb create
command.az cosmosdb create --name $COSMOSDB_ACCOUNT_NAME --resource-group $RESOURCE_GROUP --kind MongoDB
The creation process can take a few moments to complete.
Create a new database using the
az cosmosdb mongodb database create
command. In this example, the database is named contoso-ship-manager.az cosmosdb mongodb database create --account-name $COSMOSDB_ACCOUNT_NAME --resource-group $RESOURCE_GROUP --name contoso-ship-manager
Verify the database was successfully created using the
az cosmosdb mongodb database list
command.az cosmosdb mongodb database list --account-name $COSMOSDB_ACCOUNT_NAME --resource-group $RESOURCE_GROUP -o table
Your output should look similar to the following example output:
Name ResourceGroup -------------------- --------------- contoso-ship-manager rg-ship-manager
Now that you've created an external state to store all the data from the ship manager application, let's create the AKS resource to store the application itself.
Create the AKS cluster
Create a Bash variable to store the cluster name for use throughout the rest of the module.
AKS_CLUSTER_NAME=ship-manager-cluster
Create an AKS cluster using the
az aks create
command.az aks create --resource-group $RESOURCE_GROUP \ --name $AKS_CLUSTER_NAME \ --node-count 3 \ --generate-ssh-keys \ --node-vm-size Standard_B2s \ --enable-addons http_application_routing
The creation process can take a few moments to complete.
Note
All Azure services set default limits and quotas for resources and features, including usage restrictions for certain virtual machine (VM) SKUs. If you encounter an error suggesting your desired VM SKU is not available in the region you've selected, you most likely need to increase this quota through an Azure support request (for Issue type, select Quota).
Download the kubectl configuration using the
az aks get-credentials
command.az aks get-credentials --name $AKS_CLUSTER_NAME --resource-group $RESOURCE_GROUP
If you receive any messages about existing clusters, for example:
A different object named ship-manager-cluster already exists in your kubeconfig file. Overwrite? (y/n):
Enter
y
to overwrite.Test the configuration using the
kubectl get nodes
command.kubectl get nodes
Your output should look similar to the following example output:
NAME STATUS ROLES AGE VERSION aks-nodepool1-12345678-vmss000000 Ready agent 3m19s v1.27.7 aks-nodepool1-12345678-vmss000001 Ready agent 3m25s v1.27.7 aks-nodepool1-12345678-vmss000002 Ready agent 3m20s v1.27.7
Deploy the application
To create the application, you need to create the YAML files to deploy to Kubernetes.
Deploy the back-end API
Get your Azure Cosmos DB database connection string using the
az cosmosdb keys list
command.az cosmosdb keys list --type connection-strings -g $RESOURCE_GROUP -n $COSMOSDB_ACCOUNT_NAME --query "connectionStrings[0].connectionString" -o tsv
Your output should look similar to the following example output:
mongodb://contoso-ship-manager-12345678.documents.azure.com:10255/?ssl=true&replicaSet=globaldb
Create a new file named backend-deploy.yml and paste in the following deployment specification:
apiVersion: apps/v1 kind: Deployment metadata: name: ship-manager-backend spec: replicas: 1 selector: matchLabels: app: ship-manager-backend template: metadata: labels: app: ship-manager-backend spec: containers: - image: mcr.microsoft.com/mslearn/samples/contoso-ship-manager:backend name: ship-manager-backend resources: requests: cpu: 100m memory: 128Mi limits: cpu: 250m memory: 256Mi ports: - containerPort: 3000 name: http env: - name: DATABASE_MONGODB_URI value: "{your database connection string}" - name: DATABASE_MONGODB_DBNAME value: contoso-ship-manager
Replace the
{your database connection string}
placeholder with the database connection string you retrieved in the previous step.Note
Don't forget to add quotes
"
to the environment variables, as the connection string sometimes presents invalid YAML characters. You might consider using secrets as a secure way to store and retrieve connection string in AKS.Save and close the file.
Apply the back-end API deployment using the
kubectl apply
command.kubectl apply -f backend-deploy.yml
You should see a message similar to the following example output:
deployment.apps/ship-manager-backend created
To make this application available to everyone, you need to create a service and an ingress to take care of the traffic.
Get your cluster API server address using the
az aks show
command.az aks show -g $RESOURCE_GROUP -n $AKS_CLUSTER_NAME -o tsv --query fqdn
Your output should look similar to the following example output:
ship-manag-rg-ship-manager-a1bcd2-efghij56.hcp.eastus.azmk8s.io
Create a new file named backend-network.yml and paste in the following networking specification:
apiVersion: v1 kind: Service metadata: name: ship-manager-backend spec: type: ClusterIP ports: - port: 80 targetPort: 3000 selector: app: ship-manager-backend --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ship-manager-backend spec: ingressClassName: webapprouting.kubernetes.azure.com rules: - host: <host-name> http: paths: - backend: service: name: ship-manager-backend port: number: 80 path: / pathType: Prefix
Replace the
<host-name>
placeholder with the connection string you retrieved in the previous step.Save and close the file.
Apply the back-end networking deployment using the
kubectl apply
command.kubectl apply -f backend-network.yml
Your output should look similar to the following example output:
service/ship-manager-backend created ingress.networking.k8s.io/ship-manager-backend created
You can access the API through the host name that you pasted in your ingress resource. The Azure DNS zone resource can take up to five minutes to complete the DNS detection. If you can't access the API right away, wait a few minutes and try again.
Check the ingress status by querying Kubernetes for the available ingresses using the
kubectl get ingress
command.kubectl get ingress
Once the ADDRESS field in the output is filled, it means the ingress has been deployed and it's ready to be accessed, as shown in the following example output:
NAME CLASS HOSTS ADDRESS PORTS AGE ship-manager-backend webapprouting.kubernetes.azure.com ship-manag-rg-ship-manager-a1bcd2-efghij56.hcp.eastus.azmk8s.io xx.xx.xx.xx 80 2m40s
Deploy the front-end interface
Create a new file named frontend-deploy.yml and paste in the following deployment specification:
apiVersion: apps/v1 kind: Deployment metadata: name: ship-manager-frontend spec: replicas: 1 selector: matchLabels: app: ship-manager-frontend template: metadata: labels: app: ship-manager-frontend spec: containers: - image: mcr.microsoft.com/mslearn/samples/contoso-ship-manager:frontend name: ship-manager-frontend imagePullPolicy: Always resources: requests: cpu: 100m memory: 128Mi limits: cpu: 250m memory: 256Mi ports: - containerPort: 80 volumeMounts: - name: config mountPath: /usr/src/app/dist/config.js subPath: config.js volumes: - name: config configMap: name: frontend-config --- apiVersion: v1 kind: ConfigMap metadata: name: frontend-config data: config.js: | const config = (() => { return { 'VUE_APP_BACKEND_BASE_URL': 'http://{YOUR_BACKEND_URL}', } })()
Replace the
{YOUR_BACKEND_URL}
placeholder with the host name URL of the back-end API that you retrieved in the previous section.Save and close the file.
Apply the front-end deployment using the
kubectl apply
command.kubectl apply -f frontend-deploy.yml
Your output should look similar to the following example output:
deployment.apps/ship-manager-frontend created configmap/frontend-config created
Next, you can create the networking resources that this application needs to be open to the web.
Create a new file named frontend-network.yml and paste in the following networking specification:
apiVersion: v1 kind: Service metadata: name: ship-manager-frontend spec: type: ClusterIP ports: - port: 80 targetPort: 80 selector: app: ship-manager-frontend --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ship-manager-frontend spec: ingressClassName: webapprouting.kubernetes.azure.com rules: - host: <host-name> http: paths: - backend: service: name: ship-manager-frontend port: number: 80 path: / pathType: Prefix
Replace the
<host-name>
placeholder with the connection string you retrieved in the previous section.Save and close the file.
Apply the front-end networking deployment using the
kubectl apply
command.kubectl apply -f frontend-network.yml
Your output should look similar to the following example output:
service/ship-manager-frontend created ingress.networking.k8s.io/ship-manager-frontend created
You can access the API through the host name that you pasted in your ingress resource. The Azure DNS zone resource can take up to five minutes to complete the DNS detection. If you can't access the API right away, wait a few minutes and try again.
Check the ingress status by querying Kubernetes for the available ingresses using the
kubectl get ingress
command.kubectl get ingress
Once the ADDRESS field in the output is filled, it means the ingress has been deployed and it's ready to be accessed, as shown in the following example output:
NAME CLASS HOSTS ADDRESS PORTS AGE ship-manager-backend webapprouting.kubernetes.azure.com ship-manag-rg-ship-manager-a1bcd2-efghij56.hcp.eastus.azmk8s.io xx.xx.xx.xx 80 2m40s ship-manager-frontend webapprouting.kubernetes.azure.com ship-manag-rg-ship-manager-a1bcd2-efghij56.hcp.eastus.azmk8s.io xx.xx.xx.xx 80 100s
You can now access the URL from the ingress resource's host name to enter the ship manager application.