diff --git a/.pipelines/diabetes_regression-cd.yml b/.pipelines/diabetes_regression-cd.yml index a691cc47..c113f94c 100644 --- a/.pipelines/diabetes_regression-cd.yml +++ b/.pipelines/diabetes_regression-cd.yml @@ -26,6 +26,8 @@ resources: variables: - template: diabetes_regression-variables-template.yml - group: devopsforai-aml-vg +- name: "ACR_NAME" + value: "$(BASE_NAME)amlcr" stages: - stage: 'Deploy_ACI' @@ -142,6 +144,34 @@ stages: condaFilePath: '$(Build.SourcesDirectory)/$(SOURCES_DIR_TRAIN)/conda_dependencies.yml' - script: echo $(IMAGE_LOCATION) >image_location.txt displayName: "Write image location file" + + - task: AzureCLI@2 + displayName: 'Get ACR username and password' + continueOnError: false + inputs: + azureSubscription: '$(AZURE_RM_SVC_CONNECTION)' + scriptLocation: inlineScript + scriptType: 'bash' + inlineScript: | + export acr_password=`az acr credential show -n $(ACR_NAME) --query passwords[0].value -g $(RESOURCE_GROUP)` + export acr_username=`az acr credential show -n $(ACR_NAME) --query username -g $(RESOURCE_GROUP)` + echo "Got username: " + echo $acr_username + echo "##vso[task.setvariable variable=acr_password]$acr_password" + echo "##vso[task.setvariable variable=acr_username]$acr_username" + + - task: AzureResourceGroupDeployment@2 + inputs: + azureSubscription: '$(AZURE_RM_SVC_CONNECTION)' + action: 'Create Or Update Resource Group' + resourceGroupName: '$(RESOURCE_GROUP)' + location: $(LOCATION) + templateLocation: 'Linked artifact' + csmFile: '$(Build.SourcesDirectory)/environment_setup/arm-templates/webapp-env.json' + overrideParameters: '-baseName $(BASE_NAME) -location $(LOCATION) -imagelocation $(IMAGE_TAGGED) -acr $(ACR_NAME) -acr_password $(acr_password) -acr_username $(acr_username)' + deploymentMode: 'Incremental' + displayName: 'Create webapp' + - task: AzureWebAppContainer@1 name: WebAppDeploy displayName: 'Azure Web App on Container Deploy' diff --git a/.pipelines/diabetes_regression-package-model-template.yml b/.pipelines/diabetes_regression-package-model-template.yml index 16fc1c1d..7bd85d43 100644 --- a/.pipelines/diabetes_regression-package-model-template.yml +++ b/.pipelines/diabetes_regression-package-model-template.yml @@ -40,3 +40,6 @@ steps: # Set environment variable using the last line of logs that has the package location IMAGE_LOCATION=$(tail -n 1 image_logs.txt) echo "##vso[task.setvariable variable=IMAGE_LOCATION]$IMAGE_LOCATION" + echo $IMAGE_LOCATION > image_location.txt + IMAGE_TAGGED="$(sed 's/@sha256.*/:latest/g' image_location.txt)" + echo "##vso[task.setvariable variable=IMAGE_TAGGED]$IMAGE_TAGGED" diff --git a/docs/getting_started.md b/docs/getting_started.md index 977fe626..e7606c4a 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -380,9 +380,7 @@ Delete the **ACI_DEPLOYMENT_NAME** variable. The pipeline uses the [Azure ML CLI](../.pipelines/diabetes_regression-package-model-template.yml) to create a scoring image. The image will be registered under an Azure Container Registry instance that belongs to the Azure Machine Learning Service. Any dependencies that the scoring file depends on can also be packaged with the container with an image config. Learn more about how to create a container using the Azure ML SDK with the [Image class](https://docs.microsoft.com/en-us/python/api/azureml-core/azureml.core.image.image.image?view=azure-ml-py#create-workspace--name--models--image-config-) API documentation. -Make sure your webapp has the credentials to pull the image from the Azure Container Registry created by the Infrastructure as Code pipeline. Instructions can be found on the [Configure registry credentials in web app](https://docs.microsoft.com/en-us/azure/devops/pipelines/targets/webapp-on-container-linux?view=azure-devops&tabs=dotnet-core%2Cyaml#configure-registry-credentials-in-web-app) page. You'll need to run the pipeline once (including the Deploy to Webapp stage up to the `Create scoring image` step) so an image is present in the registry. After that, you can connect the Webapp to the Azure Container Registry in the Azure Portal. - -![build](./images/multi-stage-webapp.png) +The pipeline should create the webapp automatically the first time it is run with **WEBAPP_DEPLOYMENT_NAME** set. ### Example pipelines using R diff --git a/environment_setup/arm-templates/webapp-env.json b/environment_setup/arm-templates/webapp-env.json new file mode 100644 index 00000000..67736b30 --- /dev/null +++ b/environment_setup/arm-templates/webapp-env.json @@ -0,0 +1,104 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "imagelocation": { + "type": "string" + }, + "acr_username": { + "type": "string" + }, + "acr_password": { + "type": "secureString" + }, + "baseName": { + "type": "string", + "maxLength": 10, + "minLength": 3, + "metadata": { + "description": "The base name to use as prefix to create all the resources." + } + }, + "location": { + "type": "string", + "metadata": { + "description": "Specifies the location for all resources." + } + }, + "acr": { + "type": "string", + "defaultValue": "[concat(toLower(parameters('baseName')),'amlcr')]" + }, + "webAppName": { + "type": "string", + "defaultValue": "[concat(toLower(parameters('baseName')),'webapp')]", + "metadata": { + "description": "Base name of the web app name and app service plan" + }, + "minLength": 2 + }, + "sku": { + "type": "string", + "metadata": { + "description": "SKU for the app service plan" + }, + "defaultValue": "S1" + } + }, + "variables": { + "webAppPortalName": "[concat(parameters('webAppName'), '-webapp')]", + "appServicePlanName": "[concat(parameters('webAppName'),'AppServicePlan')]" + + }, + "resources": [ + { + "type": "Microsoft.Web/serverfarms", + "apiVersion": "2018-02-01", + "name": "[variables('appServicePlanName')]", + "location": "[parameters('location')]", + "sku": { + "name": "[parameters('sku')]" + }, + "kind": "linux", + "properties": { + "reserved": true, + "maximumElasticWorkerCount": 5 + } + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2018-11-01", + "name": "[variables('webAppPortalName')]", + "location": "[parameters('location')]", + "kind": "app,linux,container", + "dependsOn": [ + "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]" + ], + "properties": { + "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]", + "httpsOnly": true, + "siteConfig": { + "linuxFxVersion": "[concat('DOCKER|', parameters('imagelocation'))]", + "appSettings": [ + { + "name": "WEBSITES_ENABLE_APP_SERVICE_STORAGE", + "value": "false" + }, + { + "name": "DOCKER_REGISTRY_SERVER_URL", + "value": "[concat('https://', parameters('acr'), '.azurecr.io')]" + }, + { + "name": "DOCKER_REGISTRY_SERVER_USERNAME", + "value": "[parameters('acr_username')]" + }, + { + "name": "DOCKER_REGISTRY_SERVER_PASSWORD", + "value": "[parameters('acr_password')]" + } + ] + } + } + } + ] +}