|
| 1 | +Microservices with Dapr using the CLI |
| 2 | +===================================== |
| 3 | + |
| 4 | +Setup base resources |
| 5 | +-------------------- |
| 6 | + |
| 7 | +```sh |
| 8 | +RESOURCE_GROUP="containerapps" |
| 9 | +LOCATION="canadacentral" |
| 10 | +CONTAINERAPPS_ENVIRONMENT="containerapps-env" |
| 11 | +LOG_ANALYTICS_WORKSPACE="containerapps-logs" |
| 12 | +ACR_NAME=containerappsreg |
| 13 | +STORAGE_ACCOUNT_CONTAINER="mycontainer" |
| 14 | +STORAGE_ACCOUNT="containerapps$(openssl rand -hex 5)" |
| 15 | + |
| 16 | +az login |
| 17 | + |
| 18 | +az extension add \ |
| 19 | + --source https://workerappscliextension.blob.core.windows.net/azure-cli-extension/containerapp-0.2.0-py2.py3-none-any.whl |
| 20 | + |
| 21 | +az provider register --namespace Microsoft.Web |
| 22 | + |
| 23 | +az group create \ |
| 24 | + --name $RESOURCE_GROUP \ |
| 25 | + --location "$LOCATION" |
| 26 | + |
| 27 | +az monitor log-analytics workspace create \ |
| 28 | + --resource-group $RESOURCE_GROUP \ |
| 29 | + --workspace-name $LOG_ANALYTICS_WORKSPACE |
| 30 | + |
| 31 | +LOG_ANALYTICS_WORKSPACE_CLIENT_ID=`az monitor log-analytics workspace show --query customerId -g $RESOURCE_GROUP -n $LOG_ANALYTICS_WORKSPACE --out tsv` |
| 32 | + |
| 33 | +LOG_ANALYTICS_WORKSPACE_CLIENT_SECRET=`az monitor log-analytics workspace get-shared-keys --query primarySharedKey -g $RESOURCE_GROUP -n $LOG_ANALYTICS_WORKSPACE --out tsv` |
| 34 | + |
| 35 | +az containerapp env create \ |
| 36 | + --name $CONTAINERAPPS_ENVIRONMENT \ |
| 37 | + --resource-group $RESOURCE_GROUP \ |
| 38 | + --logs-workspace-id $LOG_ANALYTICS_WORKSPACE_CLIENT_ID \ |
| 39 | + --logs-workspace-key $LOG_ANALYTICS_WORKSPACE_CLIENT_SECRET \ |
| 40 | + --location "$LOCATION" |
| 41 | + |
| 42 | +az storage account create \ |
| 43 | + --name $STORAGE_ACCOUNT \ |
| 44 | + --resource-group $RESOURCE_GROUP \ |
| 45 | + --location "$LOCATION" \ |
| 46 | + --sku Standard_RAGRS \ |
| 47 | + --kind StorageV2 |
| 48 | + |
| 49 | +STORAGE_ACCOUNT_KEY=`az storage account keys list --resource-group $RESOURCE_GROUP --account-name $STORAGE_ACCOUNT --query '[0].value' --out tsv` |
| 50 | +echo $STORAGE_ACCOUNT_KEY |
| 51 | +``` |
| 52 | + |
| 53 | +Configure the state store component for Dapr |
| 54 | +-------------------------------------------- |
| 55 | + |
| 56 | +```sh |
| 57 | +cat << EOF > ./components.yaml |
| 58 | +# components.yaml for Azure Blob storage component |
| 59 | +- name: statestore |
| 60 | + type: state.azure.blobstorage |
| 61 | + version: v1 |
| 62 | + metadata: |
| 63 | + # Note that in a production scenario, account keys and secrets |
| 64 | + # should be securely stored. For more information, see |
| 65 | + # https://docs.dapr.io/operations/components/component-secrets |
| 66 | + - name: accountName |
| 67 | + value: $STORAGE_ACCOUNT |
| 68 | + - name: accountKey |
| 69 | + value: $STORAGE_ACCOUNT_KEY |
| 70 | + - name: containerName |
| 71 | + value: $STORAGE_ACCOUNT_CONTAINER |
| 72 | +EOF |
| 73 | +``` |
| 74 | + |
| 75 | +Create new node app image (for custom message) |
| 76 | +---------------------------------------------- |
| 77 | + |
| 78 | +```sh |
| 79 | +pushd ~ |
| 80 | + |
| 81 | +git clone https://github.com/clarenceb/quickstarts dapr-quickstarts |
| 82 | +cd dapr-quickstarts/hello-kubernetes/node |
| 83 | + |
| 84 | +az acr create --resource-group $RESOURCE_GROUP --name $ACR_NAME --sku Basic --admin-enabled true |
| 85 | +ACR_USERNAME=$(az acr credential show --resource-group $RESOURCE_GROUP --name $ACR_NAME --query username -o tsv) |
| 86 | +ACR_PASSWORD=$(az acr credential show --resource-group $RESOURCE_GROUP --name $ACR_NAME --query passwords[0].value -o tsv) |
| 87 | + |
| 88 | +az acr build --image hello-k8s-node:v2 \ |
| 89 | + --registry $ACR_NAME \ |
| 90 | + --file Dockerfile . |
| 91 | + |
| 92 | +popd |
| 93 | +``` |
| 94 | + |
| 95 | +Deploy the service application (HTTP web server) |
| 96 | +------------------------------------------------ |
| 97 | + |
| 98 | +```sh |
| 99 | +az containerapp create \ |
| 100 | + --name nodeapp \ |
| 101 | + --resource-group $RESOURCE_GROUP \ |
| 102 | + --environment $CONTAINERAPPS_ENVIRONMENT \ |
| 103 | + --image $ACR_NAME.azurecr.io/hello-k8s-node:v2 \ |
| 104 | + --registry-login-server $ACR_NAME.azurecr.io \ |
| 105 | + --registry-username $ACR_USERNAME \ |
| 106 | + --registry-password $ACR_PASSWORD \ |
| 107 | + --environment-variables MESSAGE=v1 \ |
| 108 | + --target-port 3000 \ |
| 109 | + --ingress 'external' \ |
| 110 | + --min-replicas 1 \ |
| 111 | + --max-replicas 1 \ |
| 112 | + --enable-dapr \ |
| 113 | + --dapr-app-port 3500 \ |
| 114 | + --dapr-app-id nodeapp \ |
| 115 | + --dapr-components ./components.yaml |
| 116 | + |
| 117 | +az containerapp revision list -n nodeapp -g $RESOURCE_GROUP -o table |
| 118 | +``` |
| 119 | + |
| 120 | +Deploy the client application (headless client) |
| 121 | +----------------------------------------------- |
| 122 | + |
| 123 | +```sh |
| 124 | +az containerapp create \ |
| 125 | + --name pythonapp \ |
| 126 | + --resource-group $RESOURCE_GROUP \ |
| 127 | + --environment $CONTAINERAPPS_ENVIRONMENT \ |
| 128 | + --image dapriosamples/hello-k8s-python:latest \ |
| 129 | + --min-replicas 1 \ |
| 130 | + --max-replicas 1 \ |
| 131 | + --enable-dapr \ |
| 132 | + --dapr-app-id pythonapp |
| 133 | + |
| 134 | +az containerapp list -o table |
| 135 | + |
| 136 | +az monitor log-analytics query \ |
| 137 | + --workspace $LOG_ANALYTICS_WORKSPACE_CLIENT_ID \ |
| 138 | + --analytics-query "ContainerAppConsoleLogs_CL | where ContainerAppName_s == 'nodeapp' and (Log_s contains 'persisted' or Log_s contains 'order') | project ContainerAppName_s, Log_s, TimeGenerated | order by TimeGenerated desc | take 20" \ |
| 139 | + --out table |
| 140 | +``` |
| 141 | + |
| 142 | +Create some orders |
| 143 | +------------------ |
| 144 | + |
| 145 | +```sh |
| 146 | +NODEAPP_INGRESS_URL=$(az containerapp show -n nodeapp -g $RESOURCE_GROUP --query configuration.ingress.fqdn -o tsv) |
| 147 | +curl --request POST --data "@sample.json" --header Content-Type:application/json $NODEAPP_INGRESS_URL/neworder |
| 148 | + |
| 149 | +curl $NODEAPP_INGRESS_URL/order |
| 150 | + |
| 151 | +watch -n 5 az monitor log-analytics query --workspace $LOG_ANALYTICS_WORKSPACE_CLIENT_ID --analytics-query "\"ContainerAppConsoleLogs_CL | where ContainerAppName_s == 'nodeapp' and (Log_s contains 'persisted' or Log_s contains 'order') | project ContainerAppName_s, Log_s, TimeGenerated | order by TimeGenerated desc | take 20\"" --out table |
| 152 | + |
| 153 | +i=0 |
| 154 | +while [[ $i -lt 20 ]]; do |
| 155 | + ordernum=$(openssl rand -hex 3) |
| 156 | + echo "Sending order ($i): $ordernum" |
| 157 | + curl -i --request POST --data "{\"data\": {\"orderId\": \"$ordernum\"}}" --header Content-Type:application/json $NODEAPP_INGRESS_URL/neworder |
| 158 | + let "i+=1" |
| 159 | +done |
| 160 | +``` |
| 161 | + |
| 162 | +Deploy v2 of nodeapp |
| 163 | +-------------------- |
| 164 | + |
| 165 | +```sh |
| 166 | +az containerapp update \ |
| 167 | + --name nodeapp \ |
| 168 | + --resource-group $RESOURCE_GROUP \ |
| 169 | + --image $ACR_NAME.azurecr.io/hello-k8s-node:v2 \ |
| 170 | + --registry-login-server $ACR_NAME.azurecr.io \ |
| 171 | + --registry-username $ACR_USERNAME \ |
| 172 | + --registry-password $ACR_PASSWORD \ |
| 173 | + --environment-variables MESSAGE=v2 \ |
| 174 | + --target-port 3000 \ |
| 175 | + --ingress 'external' \ |
| 176 | + --min-replicas 1 \ |
| 177 | + --max-replicas 1 \ |
| 178 | + --enable-dapr \ |
| 179 | + --dapr-app-port 3500 \ |
| 180 | + --dapr-app-id nodeapp \ |
| 181 | + --dapr-components ./components.yaml |
| 182 | +``` |
| 183 | + |
| 184 | +In the Azure Portal, split traffic 50% to v1 and v2 and send some orders. |
| 185 | +Inspect the logs to see round-robin between the two revisions. |
| 186 | + |
| 187 | +Cleanup |
| 188 | +------- |
| 189 | + |
| 190 | +```sh |
| 191 | +az group delete \ |
| 192 | + --resource-group $RESOURCE_GROUP |
| 193 | +``` |
0 commit comments