The following command creates a container in Azure that is mapped to a file share/volume:
az container create -g MyResourceGroup --name myapp --image myimage:latest
--azure-file-volume-share-name myshare --azure-file-volume-account-name mystorageacct
--azure-file-volume-account-key mystoragekey --azure-file-volume-mount-path /mnt/azfile
But I need my container to be mapped to two volumes, not just one. Is this possible?
I do not know if it is possible to do this via azure cli. I do know that you can do this through Azure Resource Manager Templates.
In this example, see how the container group has an array of volumes, while each container can have an array of volume mounts.
{
"type": "Microsoft.ContainerInstance/containerGroups",
"apiVersion": "2018-10-01",
"name": "[parameters('ContainerGroupName')]",
"location": "australiaeast",
"identity": {
"type": "UserAssigned",
"userAssignedIdentities": {
"[variables('managedIdentityId')]": {}
}
},
"dependsOn": [
"[variables('managedIdentityId')]"
],
"properties": {
"containers": [
{
"name": "[parameters('ContainerGroupName')]",
"properties": {
"image": "[parameters('SourceImage')]",
"ports": [{"port": 80},{"port": 443}],
"environmentVariables": [],
"resources": { "requests": { "memoryInGB": 1.5, "cpu": 1 } },
"volumeMounts": [
{
"name": "httpscertificatevolume",
"mountPath": "/https"
},
{
"name": "videofoldervolume",
"mountPath": "[variables('videoFolderMountPath')]"
}
]
}
}
],
"volumes": [{
"name": "httpscertificatevolume",
"azureFile": {
"shareName": "[parameters('HttpsCertificateFileShare')]",
"storageAccountName": "[parameters('StorageAccountName')]",
"storageAccountKey" : "[parameters('StorageAccountKey')]"
}
},
{
"name": "videofoldervolume",
"azureFile": {
"shareName": "[parameters('VideoFileShare')]",
"storageAccountName": "[parameters('StorageAccountName')]",
"storageAccountKey" : "[parameters('StorageAccountKey')]"
}
}
]
}
}
Related
I'm creating a file share and container instance using ARM template, and I need to mount this created file share to the container. I have the below template -
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_GRS",
"metadata": {
"description": "Storage Account type"
}
},
"storageAccountName": {
"type": "string",
"defaultValue": "[concat('storage', uniquestring(resourceGroup().id))]",
"metadata": {
"description": "Name of the Azure Storage account."
}
},
"sharePrefix": {
"type": "string",
"defaultValue": "files",
"metadata": {
"description": "Specifies the prefix of the file share names."
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
},
.....
},
"variables": {
"ContainerGroupName": "[concat('my-cg',uniquestring(resourceGroup().id))]",
"storageAccountId": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]",
"ContainerName": "my-container"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[parameters('storageAccountName')]",
"apiVersion": "2019-06-01",
"location": "[parameters('location')]",
"kind": "Storage",
"sku": {
"name": "[parameters('storageAccountType')]"
}
},
{
"type": "Microsoft.Storage/storageAccounts/fileServices/shares",
"apiVersion": "2019-06-01",
"name": "[concat(parameters('storageAccountName'), '/default/', parameters('sharePrefix'))]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
]
},
{
"name": "[variables('ContainerGroupName')]",
"type": "Microsoft.ContainerInstance/containerGroups",
"apiVersion": "2018-10-01",
"location": "[parameters('location')]",
"properties": {
"containers": [
{
"name": "[variables('ContainerName')]",
"properties": {
"image": "imageNameinACR",
"resources": {
"requests": {
"memoryInGB": 14,
"cpu": 4
}
},
"volumeMounts": [
{
"name": "filesharevolume",
"mountPath": "/app"
}
]
}
}
],
"imageRegistryCredentials": [
....
],
"restartPolicy": "OnFailure",
"osType": "Linux",
"volumes": [
{
"name": "filesharevolume",
"azureFile": {
"shareName": "[concat(parameters('storageAccountName'), '/default/', parameters('sharePrefix'))]",
"storageAccountName": "[parameters('storageAccountName')]",
"storageAccountKey": "[listKeys(parameters('storageAccountName'), '2019-06-01').keys[0].value]"
}
}
]
},
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]",
"[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), 'default', parameters('sharePrefix'))]"
]
}
],
"outputs": {}
}
However, this is throwing the error
"error": {
"code": "CannotAccessStorageAccount",
"message": "The Azure storage account 'storage6x2un3wwsta6u' in volume 'filesharevolume' can't be accessed: 'The remote server
returned an error: (400) Bad Request.'. This can be caused by
incorrect Azure storage account key or Azure storage firewalls." }
I've also tried the resourceId to retrieve the secret like below, but it throws the same error.
"storageAccountKey": "[listKeys(variables('storageAccountId'), '2019-06-01').keys[0].value]"
Am I missing anything in the template? I referred to various samples that show this method to retrieve access keys in ARM template.
In my DOCKERFILE for the container image, I'm running
RUN MKDIR /App
Could there be an issue with the mount path? My assumption is that the fileshare will be mounted in this directory - /app/filesharevolume.
I don't see the definition of the variable storageAccountId, but the template function listkeys really works with the resource Id. So I give the code that works on my side:
"storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value]"
And if the storage account is not in the same resource group with the container group, then you can add the group name of the storage account when you get the resource Id:
"storageAccountKey": "[listKeys(resourceId(variables('resourceGroupName'), 'Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value]
Here is the example.
Update:
And there is a problem in the volumes of the container group. You need to change the file share name into this:
"volumes": [
{
"name": "filesharevolume",
"azureFile": {
"shareName": "[parameters('sharePrefix')]",
"storageAccountName": "[parameters('storageAccountName')]",
"storageAccountKey": "[listKeys(parameters('storageAccountName'), '2019-06-01').keys[0].value]"
}
}
]
How can I get the cluster ca certificate from the arm template for some ManagedClusters?
In terraform we use:
azurerm_kubernetes_cluster.aks_cluster.kube_config.0.cluster_ca_certificate
But in ARM I can't find it anywhere.
Can you please give some help?
Thanks
My solution:
"resources": [
{
"type": "Microsoft.Resources/deploymentScripts",
"apiVersion": "2019-10-01-preview",
"name": "get-cluster-ca",
"location": "[resourceGroup().location]",
"identity": {
....
}
},
"kind": "AzureCLI",
"azCliVersion": "2.0.80",
"environmentVariables": [
{
"name": "RESOURCE_GROUP_NAME",
"value": "[resourceGroup().name]"
},
{
"name": "CLUSTER_NAME",
"value": "[variables('cluster_name')]"
}
],
"scriptContent": "#!/bin/bash\r\n\r\naz aks get-credentials --resource-group ${RESOURCE_GROUP_NAME} --name ${CLUSTER_NAME}\r\n\r\naz aks install-cli\r\n\r\necho '{\"ca\":' $(kubectl config view --raw -o json | jq -c '.clusters[0].cluster.\"certificate-authority-data\"') > $AZ_SCRIPTS_OUTPUT_PATH\r\n",
"timeout": "PT30M",
"cleanupPreference": "OnSuccess",
"retentionInterval": "P1D"
}
],
"outputs": {
"result": {
"value": "[reference('get-cluster-ca').outputs.ca]",
"type": "string"
}
}
I created an ARM template with a virtual machine scale set, Now I am stuck in my ARM template development because I couldn't get private IPs of the virtual machine created inside the scale set. Private IPs are required to update Cassandra seeds using extension scripts.
{
"type": "Microsoft.Compute/virtualMachineScaleSets",
"apiVersion": "2020-06-01",
"name": "[parameters('vmName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]",
"Microsoft.Compute/images/myCustomImage"
],
"identity": {
"type": "SystemAssigned"
},
"sku": {
"name": "[parameters('vmSku')]",
"tier": "Standard",
"capacity": "[parameters('instanceCount')]"
},
"properties": {
"overprovision": "false",
"upgradePolicy": {
"mode": "Manual"
},
"virtualMachineProfile": {
"storageProfile": {
"imageReference": {
"id": "[resourceId('Microsoft.Compute/images', 'myCustomImage')]"
}
},
"osProfile": {
"computerNamePrefix": "[parameters('vmName')]",
"customdata": "1",
"adminUsername": "centos",
"linuxConfiguration": {
"disablePasswordAuthentication": true,
"ssh": {
"publicKeys": [
{
"path": "/home/centos/.ssh/authorized_keys",
"keyData": "xxxx"
}
]
}
}
},
"networkProfile": {
"networkInterfaceConfigurations": [
{
"name": "[parameters('nicName')]",
"properties": {
"primary": true,
"ipConfigurations": [
{
"name": "[variables('ipConfigName')]",
"properties": {
"subnet": {
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), 'cassandra')]"
}
}
}
]
}
}
]
}
}
}
}
How to get private IPs of VMs created within the scale set?
You can use the function reference to get the NIC resource of the VMSS instances. And the resource id of the instance NICs, look like this:
/subscriptions/{subscriptionId}/resourceGroups/{groupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmssName}/virtualMachines/{instanceId}/networkInterfaces/{nicName}
So you can set the variables for each instance id and then get the private IP addresses, the part of the template looks like this:
"variables": {
"instanceNic-0": "[concat('/subscriptions/{subscriptionId}/resourceGroups/{groupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmssName}/virtualMachines/0/networkInterfaces/', parameters('nicName'))]"
},
"outputs": {
"instanceNic-0-IP": {
"type": "string",
"value": "[reference(variables('instanceNic-0'), '2016-09-01').ipConfigurations[0].properties.privateIPAddress]"
}
}
I have problem deploying more than one azure vms from custom image (aka ami) built using packer.
Here's my packer script to create the base image:
{
"builders": [
{
"type": "azure-arm",
"client_id": "CHANGE_ME",
"client_secret": "CHANGE_ME",
"object_id": "CHANGE_ME",
"subscription_id": "CHANGE_ME",
"tenant_id": "CHANGE_ME",
"resource_group_name": "packerrgvm",
"storage_account": "packerrgvm",
"capture_container_name": "images",
"capture_name_prefix": "packer",
"os_type": "Linux",
"image_publisher": "Canonical",
"image_offer": "UbuntuServer",
"image_sku": "16.04.0-LTS",
"azure_tags": {
"dept": "engineering"
},
"location": "westeurope",
"vm_size": "Standard_A2"
}
],
"provisioners": [
{
"type": "shell",
"inline": ["do sth interesting here"]
},
{
"type": "shell",
"inline": [
"sudo /usr/sbin/waagent -force -deprovision+user && export HISTSIZE=0 && sync"
]
}
]
}
Now, I'm trying to deploy new vm using ARM templates. My template contains imageName, imageUri and vhdUri provided by packer after successfull build. Vnets, network interfaces etc ommited:
{
"apiVersion": "2016-03-30",
"type": "Microsoft.Compute/virtualMachines",
"name": "[variables('workerVM').machine.name]",
"location": "[resourceGroup().location]",
"properties": {
"hardwareProfile": {
"vmSize": "[variables('workerVM').machine.size]"
},
"storageProfile": {
"osDisk": {
"osType": "Linux",
"name": "[variables('workerVM').machine.imageName]",
"createOption": "FromImage",
"image": {
"uri": "[variables('workerVM').machine.imageUri]"
},
"vhd": {
"uri": "[variables('workerVM').machine.vhdUri]"
},
"caching": "ReadWrite"
}
},
"osProfile": {
"computerName": "[variables('workerVM').machine.name]",
"adminUsername": "[variables('workerVM').machine.adminUsername]",
"adminPassword": "[variables('workerVM').machine.adminPassword]"
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', variables('workerVM').network.nicName)]"
}
]
},
"diagnosticsProfile": {
"bootDiagnostics": {
"enabled": false
}
},
"provisioningState": 0
}
}
When I deploy it for the first time, it works. Hovewer, even if I remove my resource group completely and try to deploy the vm once again, I get the following error:
error: The resource operation completed with terminal provisioning state 'Failed'.
error: Blob https://packerrgvm.blob.core.windows.net/vmcontainera1ba96d3-a593-44b9-8c71-1d345ef67a2d/osDisk.a1ba96d3-a593-44b9-8c71-1d345ef67a2d.vhd already exists. Please provide a different blob URI as target for disk 'packer-osDisk.49359f62-5c49-44c1-aed8-4ea1613ab2e9.vhd'.
Is it possible to use custom ami built by packer this way?
how do i create more than 1 vm from single base image built with backer
You could change the value vhdUri variable before re-deploy the ARM template.
"vhd": {
"uri": "[variables('workerVM').machine.vhdUri]"
}
The vhdUri variable in your ARM template could be like this,
"variables": {
"workerVM": {
"machine": {
"vhdUri": "reset this uri"
}
}
In ARM template add below storage resource which uses image uri generated by packer
{
"type": "Microsoft.Compute/images",
"apiVersion": "2016-04-30-preview",
"name": "[variables('imageName')]",
"location": "[resourceGroup().location]",
"properties": {
"storageProfile": {
"osDisk": {
"osType": "Windows",
"osState": "Generalized",
"blobUri": "[parameters('your_image_uri_generated_by_packer')]",
"storageAccountType": "Standard_LRS"
}
}
}
},
And modify storage profile property in Microsoft.Compute/virtualMachines to use this resource
"storageProfile": {
"imageReference": {
"id": "[resourceId('Microsoft.Compute/images', variables('imageName'))]"
}
},
I have created template1 which will deploy HDI cluster and template2 which will deploy Azure VM seperately.
Now I want to get the Head-node Private IP from cluster and pass it to Azure VM template for processing using ARM template.
How can I do so?
Considering this is the object you are getting from HDcluster:
{
"id": "xxx",
"name": "xxx",
"type": "Microsoft.HDInsight/clusters",
"location": "East US",
"etag": "xxx",
"tags": null,
"properties": {
"clusterVersion": "3.5.1000.0",
"osType": "Linux",
"clusterDefinition": {
"blueprint": "https://blueprints.azurehdinsight.net/spark-3.5.1000.0.9865375.json",
"kind": "SPARK",
"componentVersion": {
"Spark": "1.6"
}
},
"computeProfile": {
"roles": [
{
"name": "headnode",
"targetInstanceCount": 2,
"hardwareProfile": {
"vmSize": "ExtraLarge"
},
"osProfile": {
"linuxOperatingSystemProfile": {
"username": "sshuser"
}
}
},
{
"name": "workernode",
"targetInstanceCount": 1,
"hardwareProfile": {
"vmSize": "Large"
},
"osProfile": {
"linuxOperatingSystemProfile": {
"username": "sshuser"
}
}
},
{
"name": "zookeepernode",
"targetInstanceCount": 3,
"hardwareProfile": {
"vmSize": "Medium"
},
"osProfile": {
"linuxOperatingSystemProfile": {
"username": "sshuser"
}
}
}
]
},
"provisioningState": "Succeeded",
"clusterState": "Running",
"createdDate": "2017-04-11T09:07:44.68",
"quotaInfo": {
"coresUsed": 20
},
"connectivityEndpoints": [
{
"name": "SSH",
"protocol": "TCP",
"location": "xxx.azurehdinsight.net",
"port": 22
},
{
"name": "HTTPS",
"protocol": "TCP",
"location": "xxx.azurehdinsight.net",
"port": 443
}
],
"tier": "standard"
}
}
I'm guessing this is the best output you can get, so you can use something like:
"outputs": {
"test": {
"type": "Object",
"value": "[reference(parameters('clusterName'),'2015-03-01-preview').connectivityEndpoints[0].location]"
}
}
This will get you an output of xxx.azurehdinsight.net
And you can either create a new deployment with this data or (just like I said) add RHEL VM to the same template and make it dependOn on the HDCluster deployment and reference the same thing as an input to VMextension.