MS Certificering: AZ-204, overnieuw beginnen, deel 05

Ingediend door Dirk Hornstra op 21-dec-2021 15:20

Na het 1e blok: Azure App Service web apps (link), het 2e blok: Implement Azure Functions (link), het 3e blok: Develop solutions that use Blob Storage (link) en het 4e blok: Develop solutions that use Azure Cosmos DB (link) is het nu tijd voor het 5e learning-block: Implement infrastructure as a service solutions, link.

Module 1: Provision virtual machines in Azure, link.

We gaan aan de slag met virtuele machines. Voordeel van VM's is dat je niet zelf de hardware hoeft te kopen en wel zelf je eigen software kunt installeren. Je kunt een VM gebruiken voor development en test. Als het soms er druk op jouw resources is kun je applicaties in de cloud laten draaien (en weer uitschakelen als het niet nodig is) en het kan gemakkelijk gekoppeld worden met je eigen netwerk.

De huidige limiet is dat je maximaal 20 VMs in een regio kunt laten draaien. Meer nodig? Doe dan een aanvraag: link.

Je kunt je eigen image gebruiken of een bestaande uit de marketplace. Hier een overzicht van populaire images: link.
Standard disks zijn HDD schijven, ideaal voor dev en test. Premium disks zijn SSD schijven.

Je hebt Managed Disks, beheerd door Azure, disk kan max 4TB groot zijn. Makkelijker om uit te schalen.
Unmanaged Disks, eigen beheer, dus zelf verantwoordelijk voor de storage accounts waarin je VHDs opgeslagen worden. Een storage account kan max 20.000 input/output acties per seconde verwerken. Je kunt er (dus) max 40 VHD's met volle belasting in draaien. Uitschalen naar meer schijven: dan meer storage accounts nodig.

Er zijn extensies voor VM, "Custom Script Extension": na provisionen eigen scripts runnen, "Powershell Desired State Configuration (DSC) Extension": zet een DSC op zodat je configuratie en omgeving kunt beheren, "Azure Diagnostics Extension": verzamel data zodat je kunt controleren hoe "gezond" je VM is.
Met Linux VM's biedt Azure cloud-init (link) die meerdere tools ondersteunt, zoals Ansible, Chef, SaltStack en Puppet.

Met availability zones heb je controle over je VM. Je hebt binnen een regio 3 availability zones, dat zijn fysiek gescheiden locaties: link.

Een availability set is een groepering van VMs waardoor je beschermd ben van downtime tijdens fouten of tijdens updates: link.

Met een fault domain geef je aan welke zaken bij elkaar horen (dus in hetzelfde rek staan).

Met een virtual machine scale set maak en beheer je een groep van VM's die geloadbalanced worden. Het aantal instanties kan automatisch verhoogd of verlaagd worden, afhankelijk van de drukte: link.

En meer info over de load-balancer: link.

Nog even uitleg over de verschillende soorten VM's:

VM Type Description
General Purpose Balanced CPU-to-memory ratio. Ideal for testing and development, small to medium databases, and low to medium traffic web servers.
Compute Optimized High CPU-to-memory ratio. Good for medium traffic web servers, network appliances, batch processes, and application servers.
Memory Optimized High memory-to-CPU ratio. Great for relational database servers, medium to large caches, and in-memory analytics.
Storage Optimized High disk throughput and IO ideal for Big Data, SQL, NoSQL databases, data warehousing and large transactional databases.
GPU Specialized virtual machines targeted for heavy graphic rendering and video editing, as well as model training and inferencing (ND) with deep learning. Available with single or multiple GPUs.
High Performance Compute Our fastest and most powerful CPU virtual machines with optional high-throughput network interfaces (RDMA).


Een resize zorgt voor een reboot, dus op productie-systemen niet aan te raden!

Kosten voor Linux: link en kosten voor Windows: link.
En een overzicht van de verschillende beschikbare groottes: link.

Vervolgens wordt met de Azure CLI een VM aangemaakt.
Een wachtwoord moet minimaal 12, maximaal 123 tekens hebben, uppercase, lowercase, een cijfer en een speciaal karakter.


// resource group aanmaken

az group create --name az204-vm-rg --location <myLocation>

// VM aanmaken
// check in de output het veld publicIpAddress

az vm create \
    --resource-group az204-vm-rg \
    --name az204vm \
    --image UbuntuLTS \
    --generate-ssh-keys \
    --admin-username azureuser

// open poort 80
az vm open-port --port 80 \
--resource-group az204-vm-rg \
--name az204vm

// via SSH connecten
ssh azureuser@<publicIPAddress>

// installeer NGINX
sudo apt-get -y update
sudo apt-get -y install nginx

// ruim de boel weer op
az group delete --name az204-vm-rg --no-wait


Module 2: Create and deploy Azure Resource Manager templates, link.

Alles in Azure gaat via de Azure Resource Manager.
Je hebt de ARM templates, voordelen hiervan zijn:

  • syntax is declaratief, je kunt niet alleen VMs, maar ook netwerk infrastructuur, storage systems en andere resource aanmaken.
  • herhaalbare resultaten, hierdoor weet je dat zaken consistent opgebouwd worden.
  • orchestration/aansturing, resource manager zorgt dat zaken in de juiste volgorde uitgevoerd worden. Als het mogelijk is worden zaken parallel uitgevoerd zodat het sneller klaar is. Je deployed met 1 commando in plaats van meerdere commando's "achter elkaar".


Binnen je sjabloon kun je expressies schrijven die je JSON uitbreiden, daarmee maak je gebruik van de functies van Resource Manager: link.

Het sjabloon bestaat uit:

  • parameters, hiermee kun je hetzelfde sjabloon voor verschillende omgevingen gebruiken
  • variabelen, definieer variabelen die in het sjabloon gebruikt worden (kunnen via parameters gevuld worden)
  • user-defined functions, maak functies om je sjabloon beter leesbaar te maken
  • resources, specifieer wat gedeployed moet worden
  • outputs, de return-waardes van de resources die gedeployed zijn


We zien een voorbeeld van hoe je een Storage Account aan kunt maken. Let op de "apiVersion", daarmee zorg je dat de juiste aanroepen uitgevoerd worden:


"resources": [
  {
    "type": "Microsoft.Storage/storageAccounts",
    "apiVersion": "2019-04-01",
    "name": "mystorageaccount",
    "location": "westus",
    "sku": {
      "name": "Standard_LRS"
    },
    "kind": "StorageV2",
    "properties": {}
  }
]

Je kunt een sjabloon via verschillende manieren laten uitvoeren:

  • Azure portal
  • Azure CLI
  • PowerShell
  • REST API
  • Button in GitHub repository
  • Azure Cloud Shell


Hoe je de sjablonen op wilt zetten, dat is eigen keuze. Zo kun je in 1 template een hele omgeving met VM, app service en SQL DB opzetten, binnen een resource group. Maar om het overzichtelijk te houden worden vaak doel-gerichte sjablonen gemaakt die zich op 1 punt richten (VM maken, App Service opbouwen). Je moet daarvoor een master template maken die deze geneste sjablonen bevat.

Azure Resource Manger inspecteert jouw instructies en zorgt ervoor dat deze in de juiste volgorde uitgevoerd worden (op basis van aangegeven dependencies, afhankelijkheden).

De sjablonen kun je binnen je organisatie delen. Je kunt deze opslaan als een resource type, Template specs geeft uitleg: link.

Met rollen kun je zorgen dat sommige gebruikers met read-rechten de template kunnen deployen, maar niet aan kunnen passen.

Soms moet iets optioneel gedeployed worden. Dat kun je met een condition-element afvangen (die geeft een true of false). Dat geldt dan voor de resource en niet voor child resources: link. Als je dat wel wilt, moet je dezelfde conditie toepassen op elk resource type.

In dit voorbeeld kun je of een nieuwe resource aanmaken of een bestaande gebruiken:


{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "storageAccountName": {
      "type": "string"
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    },
    "newOrExisting": {
      "type": "string",
      "defaultValue": "new",
      "allowedValues": [
        "new",
        "existing"
      ]
    }
  },
  "functions": [],
  "resources": [
    {
      "condition": "[equals(parameters('newOrExisting'), 'new')]",
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2019-06-01",
      "name": "[parameters('storageAccountName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS",
        "tier": "Standard"
      },
      "kind": "StorageV2",
      "properties": {
        "accessTier": "Hot"
      }
    }
  ]
}

Als je een list of reference functie uitvoert op iets wat door een conditie niet aangemaakt is, dan wordt dat nog steeds uitgevoerd en krijg je (dus) een runtime error. Je zult hier zelf een if-check aan moeten toevoegen.

Meer informatie over template functies: link.

Als je een resource deployed, geef je aan of het een incrementele of een volledige update is. Standaard mode is incrementeel.

Als je voor de Complete mode gaat, dan worden alle resources die niet in je sjabloon staan verwijderd. Als iets niet gedeployed wordt, omdat een conditie niet voldoet, daarbij geldt hetzelfde (behalve met een oudere versie dan versie 2019-05-10, toen bleven ze bewaard). Wees voorzichtig met copy loops. Als een resource na een copy loop niet gematcht is wordt deze dus verwijderd!

In de Incrementele mode blijven bestaande resources die niet in het sjabloon voorkomen in stand. Maar let op, je moet wel alle eigenschappen instellen! Eigenschappen die niet ingesteld zijn worden wel degelijk weggehaald of leeg gemaakt.

Om de deployment mode in te stellen, gebruik Mode in PowerShell:


New-AzResourceGroupDeployment `
  -Mode Complete `
  -Name ExampleDeployment `
  -ResourceGroupName ExampleResourceGroup `
  -TemplateFile c:\MyTemplates\storage.json

In Azure CLI gebruik je mode:

 

az deployment group create \
  --mode Complete \
  --name ExampleDeployment \
  --resource-group ExampleResourceGroup \
  --template-file storage.json

In het volgende deel krijgen we een oefening, via Visual Studio Code deployen;

We maken hier een ARM template aan, deze wordt standaard gevuld:


{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {},
    "functions": [],
    "variables": {},
    "resources": [],
    "outputs": {}
}

Via intellisense gaan we bij resources "storage" intypen en het item arm-storage invoegen:


"resources": [{
    "name": "storageaccount1",
    "type": "Microsoft.Storage/storageAccounts",
    "apiVersion": "2019-06-01",
    "tags": {
        "displayName": "storageaccount1"
    },
    "location": "[resourceGroup().location]",
    "kind": "StorageV2",
    "sku": {
        "name": "Premium_LRS",
        "tier": "Premium"
    }
}],

Vervolgens voegen we parameters toe:


"parameters": {
    "storageAccountName": {
        "type": "string",
        "metadata": {
            "description": "Storage Account Name"
        },
        "minLength": 3,
        "maxLength": 24
    }
},

En op deze manier kun je in je sjabloon de parameter(s) gebruiken:


"resources": [{
    "name": "[parameters('storageAccountName')]",
    "type": "Microsoft.Storage/storageAccounts",
    "apiVersion": "2019-06-01",
    "tags": {
        "displayName": "storageaccount1"
    },
    "location": "[resourceGroup().location]",
    "kind": "StorageV2",
    "sku": {
        "name": "Premium_LRS",
        "tier": "Premium"
    }
}],

Vervolgens kunnen we nog een parameters-bestand aanmaken, azuredeploy.parameters.json :


{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "storageAccountName": {
            "value": "az204storageacctarm"
        }
    }
}

Vervolgens gaan we de zaken deployen:


// inloggen

az login

// resource groep aanmaken

az group create --name az204-arm-rg --location <myLocation>

// deploy

az deployment group create --resource-group az204-arm-rg --template-file azuredeploy.json --parameters azuredeploy.parameters.json

// controle van je werk:

az storage account show --resource-group az204-arm-rg --name <myStorageAccount>


Module 3: Manage container images in Azure Container Registry, link.

Je kunt meerdere doelen instellen om naar te deployen, naar scalable orchestration systems, zoals Kubernetes, DC/OS en Docker Swarm of Azure services, zoals Azure Kubernetes Service (AKS), App Service, Back, Service Fabric en meer.

Ontwikkelaars kunnen ook pushen op basis van een container ontwikkel workflow. Je kunt het bijvoorbeeld als doel instellen vanuit Azure Pipelines of Jenkins.

Je kunt ACR (Azure Container Registry) Tasks instellen om applicatie images te rebuilden als de base image bijgewerkt is, of als het team een GIT commit doet. Je hebt 3 verschillende abonnementen:

Basic, zelfde specs als Standard en Premium (dus Azure Active Directory integratie, image deletion en webhooks). Opslag en image-doorvoer zijn geschikt voor "laag gebruik".
Standard, idem als Basic, maar dan meer opslag en image doorvoer. Voor de meeste productie-scenario's ruim voldoende.
Premium, hoogste specs. Extra features, zoals geo-replicatie om een enkele registry over meerdere regionen beschikbaar te maken, image tag signing voor betrouwbaarheid, private link endpoints om toegang tot de registry af te schermen.

Naast de Docker container images worden ook gerelateerde formaten opgeslagen zoals Helm charts (link) en containers volgens de OCI (Open Container Initiative) Image Format Specification gebouwd zijn (link).

En die ACR Tasks, daar kun je hier meer informatie vinden: link.

Containers worden geëncrypt opgeslagen. Ze worden ook Geo-redundant opgeslagen om verlies van je containers tegen te gaan. En met Geo-replication in je Premium register ben je beschermd als een hele regio uitvalt.

Resources, Images, Layers, Tags, er zit geen limiet aan. Wel kan een grote hoeveelheid de boel vertragen, dus ruim je spul wel zo nu en dan op. Verwijderd is ook echt verwijderd, niet meer terug te halen. Storage (opslag), daar zit een limiet van 5TB op.

ACR Tasks is een compleet framework. Het kan:

  • Quick task: bouw en push een enkele container image naar een registry in Azure (dus denk aan docker build, docker push in de cloud). Gebruik hier voor az acr build: link.
  • Automatically triggered tasks: bouw een image als je trigger afgaat die je ingesteld hebt op een update van source code, een update van de base image of een schedule die matcht. Gebruik hiervoor de az acr task create, specificeer de GIT repo en optionele branche en Dockerfile.
  • Multi-step task: bouw die quick task (die een enkele taak is) uit naar een multi-stappen, multi-container workflow. Dit werkt met een YAML-bestand: link.
     

Elke ACR Task is gekoppeld aan source code context - deze code bouwt de container image of het artifact. Voorbeeld is GIT repo of lokale bestanden.

Als je een eigen container wilt bouwen zul je moeten weten hoe een Dockerfile bestand opgebouwd is. Het is een tekstbestand welke de specs bevat.
Uitleg kun je hier vinden: link.

Voorbeeld:


# Step 1: Specify the parent image for the new image
FROM ubuntu:18.04

# Step 2: Update OS packages and install additional software
RUN apt -y update &&  apt install -y wget nginx software-properties-common apt-transport-https \
    && wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \
    && dpkg -i packages-microsoft-prod.deb \
    && add-apt-repository universe \
    && apt -y update \
    && apt install -y dotnet-sdk-3.0

# Step 3: Configure Nginx environment
CMD service nginx start

# Step 4: Configure Nginx environment
COPY ./default /etc/nginx/sites-available/default

# STEP 5: Configure work directory
WORKDIR /app

# STEP 6: Copy website code to container
COPY ./website/. .

# STEP 7: Configure network requirements
EXPOSE 80:8080

# STEP 8: Define the entry point of the process that runs in the container
ENTRYPOINT ["dotnet", "website.dll"]

Hierna volgt een voorbeeld waarbij je zelf een container in de registry van Azure gaat toevoegen.


// maak een resource group

az group create --name az204-acr-rg --location <myLocation>

// maak een registry aan
// registernaam moet 5 tot 50 alfanumerieke tekens bevatten
// hier maak je een Basic versie aan, weinig kosten (prima voor devs dus)

az acr create --resource-group az204-acr-rg \
    --name <myContainerRegistry> --sku Basic

// maak een Dockerfile aan

echo FROM mcr.microsoft.com/hello-world > Dockerfile

// bouw de image

az acr build --image sample/hello-world:v1  \
    --registry <myContainerRegistry> \
    --file Dockerfile .

// deel van de output

- image:
    registry: <myContainerRegistry>.azurecr.io
    repository: sample/hello-world
    tag: v1
    digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a
  runtime-dependency:
    registry: mcr.microsoft.com
    repository: hello-world
    tag: latest
    digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a
  git: {}


Run ID: cf1 was successful after 11s

// check of het werkt, vraag de lijst op

az acr repository list --name <myContainerRegistry> --output table

// toon de tags

az acr repository show-tags --name <myContainerRegistry> \
    --repository sample/hello-world --output table

// voer hetimage uit

az acr run --registry <myContainerRegistry> \
    --cmd '$Registry/sample/hello-world:v1' /dev/null

// je krijg jouw verwachte output (als het goed is). nu kun je de boel weer opruimen

az group delete --name az204-acr-rg --no-wait

Module 4: Run container images in Azure Container Instances, link.

Azure Container Instances (ACI) bieden de snelste manier om een container online te brengen in Azure, zonder dat je een VM hoeft te beheren.

De voordelen:

  • snel starten, een container kan in seconden opgestart worden
  • online beschikbaar, je container krijg een IP adres en volledige domeinnaam (FQDN)
  • hypervisor-level beveiliging, je app is net zo geïsoleerd als in een VM
  • klant-data, zo weinig mogelijk data wordt opgeslagen, alleen welke benodigd is om je container groups te laten werken
  • aanpasbare groottes, exacte specs van CPU cores en geheugen
  • persistente opslag, door Azure File shares te koppelen kun je daar data ophalen en opslaan
  • Linux en Windows, gebruiken dezelfde API

Als je een situatie hebt waarbij je orchestration nodig hebt, inclusief service discovery over meerdere containers, automatisch schalen en gecoördineerde applicatie upgrades, dan kun je het beste Azure Kubernetes Service gebruiken: link.

Een container groep bevat meerdere containers en is vergelijkbaar met een pod in Kubernetes.

Multi-container groups ondersteunen nu alleen Linux containers.

Een multi-container group deployen, via Resource Manager template of YAML file (aangeraden als je alleen de container instantie gaat deployen).

Als je een container group met 2 instanties hebt en beide hebben 1 CPU nodig, dan krijgt de container group 2 CPU's.

Containers in een group kunnen elkaar bereiken via localhost:poort, ook als die naar buiten niet open staat.

Je kunt meerdere soorten opslag gebruiken (mounten) zoals Azure file share, secret, empty directory en cloned GIT repo.

Een groep met meerdere containers kan gebruikt worden om 1 als web applicatie te laten dienen en de andere de meest recente content uit source control op te laten halen, 1 als applicatie container en 1 als logging container, 1 applicatie container en 1 monitoring container (deze kan regelmatig een request op de andere container uitvoeren om te controler "of die het nog doet"), 1 front-end en 1 back-end container; front-end vor de web-applicatie, de back-end voor het aanleveren van de data.


Hierna volgt een oefening waarbij een container aangemaakt wordt met de Azure CLI.

// maak resource group aan

az group create --name az204-aci-rg --location <myLocation>

// maak een container

DNS_NAME_LABEL=aci-example-$RANDOM

az container create --resource-group az204-aci-rg
    --name mycontainer
    --image mcr.microsoft.com/azuredocs/aci-helloworld
    --ports 80
    --dns-name-label $DNS_NAME_LABEL --location <myLocation>

// controle of container gestart is

az container show --resource-group az204-aci-rg
    --name mycontainer
    --query "{FQDN:ipAddress.fqdn,ProvisioningState:provisioningState}"
    --out table

// ruim de boel weer op

az group delete --name az204-aci-rg --no-wait

Het gemak en snelheid van containers zorgt dat het een populair platform is om bepaalde 1-malige taken uit te voeren, zoals builden, testen en afbeeldingen te renderen.

Met een restart policy kun je instellen dat een container stopt als de taken afgerond zijn. Omdat je per second moet betalen, betaal je dan alleen voor wat je echt gebruikt.

Je hebt 3 type policy instellingen, Always: containers worden altijd herstart, dit is de standaard. Never: containers worden niet herstart, een container wordt maximaal 1x opgestart. OnFailure: alleen herstarten als er een proces in de container crasht (exit code is niet 0). Container start minimaal 1x. Bij Never en OnFailure wordt de eindstatus "Terminated" als de taken klaar zijn.

Met de --restart-policy parameter bij de az container create geef je de waarde aan:


az container create \
    --resource-group myResourceGroup \
    --name mycontainer \
    --image mycontainerimage \
    --restart-policy OnFailure

Soms is het handig om in je container omgeving variabelen beschikbaar te hebben. Bij Docker is dit de --env parameter bij de docker run.


az container create
    --resource-group myResourceGroup
    --name mycontainer2
    --image mcr.microsoft.com/azuredocs/aci-wordcount:latest
    --restart-policy OnFailure
    --environment-variables 'NumWords'='5' 'MinLength'='8'

Sommige waardes zijn "secure" (wachtwoorden en dergelijke). Gebruik daarvoor de secureValue eigenschap.


apiVersion: 2018-10-01
location: eastus
name: securetest
properties:
  containers:
  - name: mycontainer
    properties:
      environmentVariables:
        - name: 'NOTSECRET'
          value: 'my-exposed-value'
        - name: 'SECRET'
          secureValue: 'my-secret-value'
      image: nginx
      ports: []
      resources:
        requests:
          cpu: 1.0
          memoryInGB: 1.5
  osType: Linux
  restartPolicy: Always
tags: null
type: Microsoft.ContainerInstance/containerGroups

 

az container create --resource-group myResourceGroup
    --file secure-env.yaml

Containers zijn "stateless", dus na een reboot begin je weer vanaf 0. Daarom kun je Azure Files gebruiken om een share te mounten.
Dit kan alleen bij Linux containers, je moet de container runnen als root en shares zijn gelimiteerd tot CIFS.

Voorbeeld met de CLI:


az container create \
    --resource-group $ACI_PERS_RESOURCE_GROUP \
    --name hellofiles \
    --image mcr.microsoft.com/azuredocs/aci-hellofiles \
    --dns-name-label aci-demo \
    --ports 80 \
    --azure-file-volume-account-name $ACI_PERS_STORAGE_ACCOUNT_NAME \
    --azure-file-volume-account-key $STORAGE_KEY \
    --azure-file-volume-share-name $ACI_PERS_SHARE_NAME \
    --azure-file-volume-mount-path /aci/logs/

Voorbeeld met YAML:


apiVersion: '2019-12-01'
location: eastus
name: file-share-demo
properties:
  containers:
  - name: hellofiles
    properties:
      environmentVariables: []
      image: mcr.microsoft.com/azuredocs/aci-hellofiles
      ports:
      - port: 80
      resources:
        requests:
          cpu: 1.0
          memoryInGB: 1.5
      volumeMounts:
      - mountPath: /aci/logs/
        name: filesharevolume
  osType: Linux
  restartPolicy: Always
  ipAddress:
    type: Public
    ports:
      - port: 80
    dnsNameLabel: aci-demo
  volumes:
  - name: filesharevolume
    azureFile:
      sharename: acishare
      storageAccountName: <Storage account name>
      storageAccountKey: <Storage account key>
tags: {}
type: Microsoft.ContainerInstance/containerGroups

Als je meerdere schijven mount, kun je dat in het ARM template als volgt instellen:


"volumes": [{
  "name": "myvolume1",
  "azureFile": {
    "shareName": "share1",
    "storageAccountName": "myStorageAccount",
    "storageAccountKey": "<storage-account-key>"
  }
},
{
  "name": "myvolume2",
  "azureFile": {
    "shareName": "share2",
    "storageAccountName": "myStorageAccount",
    "storageAccountKey": "<storage-account-key>"
  }
}]


"volumeMounts": [{
  "name": "myvolume1",
  "mountPath": "/mnt/share1/"
},
{
  "name": "myvolume2",
  "mountPath": "/mnt/share2/"
}]

test