ARM Template: Storage Account mit Fileshare und Verzeichnissen erstellen

06. Februar 2017
 
Beim Erstellen eines ARM Templates wollte ich neulich einen Storage Account erstellen, in welchem ich auch gleichzeitig Fileshares und eine vordefinierte Ordnerstruktur bereitstellen kann. Nach einiger Zeit bin ich dann auf dieses wenig hoffnungsvolle Issue gestoßen:
 
 
In einem ARM Template lassen sich also keine FileShares und keine Directories für einen neuen Storage Account erstellen.
 
Da im Netz keine brauchbaren Lösungen zu finden waren, musste also ein eigener Workaround her, den ich hier vorstellen möchte.
 
Grundvoraussetzung: Es wird neben dem Storage Account auch eine Linux VM erstellt.
 
Idee: Mit Extensions lassen sich Scripte auf der VM nach der Erstellung ausführen. Wir schreiben uns also ein Script, welches die FileShares und Directories während der Bereitstellung automatisch erzeugt.
 
Das Bash-Script sieht folgendermaßen aus und bekommt den Namen „createFS.sh”:
 
#!/bin/bash
STORAE_ACCOUNT="$1"
STORAGE_KEY="$2"
DATE_ISO=$(TZ=GMT date "+%a, %d %h %Y %H:%M:%S %Z")
VERSION="2015-12-11"
HEADER_RESOURCE="x-ms-date:$DATE_ISO\nx-ms-version:$VERSION"
shift
shift
numargs=$#
for ((i=1 ; i <= numargs ; i++))
do
      SHARE_OR_DIR_NAME="$1"
      if [[ $SHARE_OR_DIR_NAME == *"/"* ]]; then
            TYPE="directory"
      else
            TYPE="share"
      fi
      URL_RESOURCE="/$STORAE_ACCOUNT/$SHARE_OR_DIR_NAME\nrestype:$TYPE"
      STRING_TO_SIGN="PUT\n\n\n\n\n\n\n\n\n\n\n\n$HEADER_RESOURCE\n$URL_RESOURCE"
      DECODED_KEY="$(echo -n $STORAGE_KEY | base64 -d -w0 | xxd -p -c256)"
      SIGN=$(printf "$STRING_TO_SIGN" | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$DECODED_KEY" -binary |  base64 -w0)
      curl -X PUT \
        -H "x-ms-date:$DATE_ISO" \
        -H "x-ms-version:$VERSION" \
        -H "Authorization: SharedKey $STORAE_ACCOUNT:$SIGN" \
        -H "Content-Length:0" \
"https://$STORAE_ACCOUNT.file.core.windows.net/$SHARE_OR_DIR_NAME?restype=$TYPE"
      shift
done
 
Dieses Script erzeugt FileShares und Directories in einem existierenden StorageAccount (AccountName und AccountKey müssen als Parameter übergeben werden). Wie wird dieses Script nun aber beim Erstellvorgang automatisch ausgeführt? Und woher kenne ich den Account Namen und Key eines Storage Accounts, welcher erst neu erstellt wird?
 
Zu Frage eins:
Zunächst muss dieses Script online abgelegt werden, sodass per URL darauf zugegriffen werden kann. Beispielsweise auf Github. In meinem Beispiel nutze ich jedoch einen bereits vorhandenen Storage Account (also NICHT den Account, auf dem die Shares und Directories angelegt werden sollen!).
 
Nun kann das ARM-Template so konfiguriert werden, dass es sich dieses Script automatisch herunterläd und ausführt. Als Beispiel soll ein einfaches ARM-Template dienen, welches eine einzelne Linux VM erstellt:
 
Hier fügen wir zunächst eine neue Variable namens „storageAccountID“ hinzu:
 
"storageAccountID": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().Name, '/providers/','Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]" 
 
Diese ID wird benötigt, um auf den Access Key des neu erstellten Storage Account zugreifen zu können.
 
Anschließend fügen wir in die Ressourcenliste die CustomScript-Extension hinzu:
 
{
            "type": "Microsoft.Compute/virtualMachines/extensions",
            "name": "[concat(variables('vmName'), '/FileShareScript')]",
            "apiVersion": "2015-05-01-preview",
            "location": "[resourceGroup().location]",
            "dependsOn": [
                "[resourceId('Microsoft.Compute/virtualMachines/', variables('vmName'))]",
            ],
            "properties": {
                "publisher": "Microsoft.OSTCExtensions",
                "type": "CustomScriptForLinux",
                "typeHandlerVersion": "1.5",
                "autoUpgradeMinorVersion": true,
                "settings": {
                    "fileUris": [
                        "https://URL/TO/MY/SCRIPT/createFS.sh"
                    ]
                },
                "protectedSettings": {
                    "commandToExecute": "[concat('bash ./createFS.sh ', variables('storageAccountName'), ' ', listkeys(variables('storageAccountID'), '2015-05-01-preview').key1, ' myshare myshare/dir myshare/dir/subdir')]",
                    "storageAccountName": "<Storage_Account_Name_wo_createFS.sh_abgelegt_wurde>",
                    "storageAccountKey": "<Storage_Account_key>”
                }
            }
        } 
Diese Extension läd -wie bereits erwähnt – alle Dateien auf die VM, welche unter „fileUris“ angegeben sind. Die Parameter „storageAccountName“ und „storageAccountKey“ sind nur dann notwendig, wenn die fileUri auf einen Azure Storage Account (blob.core.windows.net) verweist.
 
createFS.sh erwartet als 1. Parameter den StorageAccountName des ZielStorages und auch den Key für diesen StorageAccount. Um den Key zu erhalten, wird die vorher definierte Variable „storageAccountID“ benötigt (siehe Code Snippet). Um also Frage zwei zu beantworten: die Funktion „listkeys“ liefert uns den Key unseres neuen StorageAccounts.
 
Falls ihr euren storageAccountKey nicht in Klartext im ARM Template ablegen möchtet, empfehle ich die Verwendung von Azure KeyVault
 
In der „commandToExecute“-Zeile können am Ende die Shares und Directories definiert werden, welche erstellt werden sollen.
Dabei muss jedoch Schrittweise vorgegangen werden. Soll bspw. (wie im Code Snippet zu sehen) ein Share namens „myshare“ mit Ordner „dir“ und Unterordner „subdir“ erstellt werden, so sind drei Parameter notwendig: „share“, „share/dir“ und „share/dir/subdir“.
Zuerst wird share erzeugt, erst dann kann share/dir und am Ende share/dir/subdir erzeugt werden.
 
Wenn ihr die Standard createFS.sh ohne Änderungen verwenden wollt, so könnt ihr auch die folgende GitHub URL dazu nutzen: https://raw.githubusercontent.com/mrmunch/common/master/Azure/ARM_Templates/createFS.sh
 
Im selben Repo findet ihr auch noch das komplette ARM Template – dort allerdings mit Verweis auf die Github URL statt auf den Azure Storage Account.
 

Neuen Kommentar schreiben