Christoph Vollmann

Azure, Office 365 and SharePoint from a consultant perspective

Erste Schritte mit Azure Bicep ūüí™

Anfang letzter Woche hat Microsoft die erste Version (0.1) von Azure Bicep veröffentlicht.

Azure Bicep stellt eine dom√§nenspezifische Sprache (DSL) dar, mit denen wir Azure Ressourcen deklarativ beschreiben k√∂nnen. Die Sprache ist kein ARM Ersatz. Vielmehr werden Bicep Templates in ARM Templates √ľbersetzt und wir werden weiterhin ARM Templates in Azure ausrollen. ARM Templates werden damit zu einer Intermediate Language (IL)

Ziele sind, dass wir wesentlich leichter modulare Templates bauen können, eine saubere und besser lesbare Syntax erhalten und unseren Template Code besser wiederverwenden können.

Voraussetzungen

Zum Start ist nicht viel nötig. Wir benötigen die Bicep CLI und zum leichteren Schreiben die Bicep VS Code Erweiterung.

Die Schritte f√ľr macOS, Linux und Windows sind gut dokumentiert im GitHub Repository.

Erstes Template

Heute beginnen wir mit ein paar Grundlagen. Parameter, Variablen, Ressourcen, Ausgaben.

Parameter

Wir legen zunächst einen Parameter fest:

param storageAccountName string = 'mycoolstorage' 

Es ist fast selbsterkl√§rend. “param” ist das Schl√ľsselwort, danach folgt der Parameter-Name, dann der Parameter-Typ (string, int, bool, array, object) und ein Default Wert.

Variablen

Eine Variable kommt ohne den Typ aus (genau wie in einem ARM Template):

var location = 'westeurope'

Um einen Parameter oder eine Variable zu nutzen, benötigen wir keine Funktionsaufrufe mehr. Einfach den Namen nutzen! Ein Beispiel:

param environment = 'dev'
param appName = 'MyApp'
var vmName = 'vm-${appName}-${environment}' // Ergebnis: "vm-MyApp-dev"

Ressourcen

Bauen wir uns eine Ressource. Einen Storage Account.
Wir ben√∂tigen einen Namen, eine Location und eine Angabe √ľber Redundanz.

resource MyStorageAccount 'Microsoft.Storage/storageAccounts@2019-06-01' = {
  name: 'mycoolstorage'
  location: 'westeurope'
  kind: 'Storage'
  sku: {
    name: 'Standard_LRS'
  }
}

“resource” ist wieder das Schl√ľsselwort, “MyStorageAccount” ist meine Ressourcen-Referenz, die ich sp√§ter im Template nutzen kann (Achtung: Das ist nicht der Name der Ressource!), dann folgt der Ressourcen-Typ mit API-Version.

Wir sollten ein paar Parameter und Variablen f√ľr unser Template nutzen:

param location string = resourceGroup().location
param environment string = 'dev'
param appName string = 'myapp'
var storageAccountName = 'st${appName}${environment}'

Der “Location” Parameter nutzt eine Expression (auch √§hnlich zu ARM Templates). Der Ausdruck hier verweist auf die Location der Ressource Group, in der das Deployment ausgef√ľhrt wird.

Dazu passen wir die Ressourcen-Beschreibung an:

resource MyStorageAccount 'Microsoft.Storage/storageAccounts@2019-06-01' = {
  name: storageAccountName
  location: location
  kind: 'Storage'
  sku: {
    name: 'Standard_LRS'
  }
}

Wie man an den Eigenschaften “name” und “location” erkennen kann: Sollten wir nichts verketten oder umschreiben, k√∂nnen wir die Variablen oder Parameter ohne weitere Funktionen nutzen. Eine – im Vergleich zu ARM – erfrischend kurze Schreibweise.

Ausgaben

Zum Schluss lassen wir uns noch beispielhaft die ID und den Blob-Endpunkt unseres Storage Accounts ausgeben:

output storageId string = MyStorageAccount.id
output blobEndpoint string = MyStorageAccount.properties.primaryEndpoints.blob

F√ľr Ausgaben ist “output” das Schl√ľsselwort, dann der Name, dann der Typ. Danach nutzen wir die Ressourcen-Referenz “MyStorageAccount” und greifen auf Eigenschaften zu.
Wir können auf alle Eigenschaften zugreifen, auf die wir auch im ARM-Template Zugriff hätten.

Zu ARM √ľbersetzen

Zun√§chst die vollst√§ndige Bicep-Datei (wir nennen sie “mytemplate.bicep”):

param location string = resourceGroup().location
param environment string = 'dev'
param appName string = 'myapp'
var storageAccountName = 'st${appName}${environment}'

resource MyStorageAccount 'Microsoft.Storage/storageAccounts@2019-06-01' = {
    name: storageAccountName
    location: location
    kind: 'Storage'
    sku: {
      name: 'Standard_LRS'
    }
}

output storageId string = MyStorageAccount.id
output blobEndpoint string = MyStorageAccount.properties.primaryEndpoints.blob

In einer PowerShell k√∂nnen wir jetzt die Datei zu ARM √ľbersetzen lassen:

bicep build .\mytemplate.bicep

Bicep erzeugt eine “mytemplate.json” Datei. Ein, wie wir ja vermutet hatten, ARM-Template:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    },
    "environment": {
      "type": "string",
      "defaultValue": "dev"
    },
    "appName": {
      "type": "string",
      "defaultValue": "myapp"
    }
  },
  "functions": [],
  "variables": {
    "storageAccountName": "[format('st{0}{1}', parameters('appName'), parameters('environment'))]"
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2019-06-01",
      "name": "[variables('storageAccountName')]",
      "location": "[parameters('location')]",
      "kind": "Storage",
      "sku": {
        "name": "Standard_LRS"
      }
    }
  ],
  "outputs": {
    "storageId": {
      "type": "string",
      "value": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
    },
    "blobEndpoint": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))).primaryEndpoints.blob]"
    }
  }
}

Schon beim Lesen hier im Blog sieht man den Vergleich, wie kurz und knackig Bicep-Dateien im Vergleich zu den sehr “geschw√§tzigen” ARM-Templates sind.

Links: Azure Bicep Datei, Rechts: Erzeugtes ARM-Template

Was ist gut gelungen?

Die Templates sind wesentlich schmaler und lesbarer. Es erinnert sehr an Terraform.

Automatische Dependencies. Wenn ich eine Resource in einer anderen referenziere, dann f√ľgt Bicep automatisch eine Abh√§ngigkeit (“dependsOn”) ein.

“concat” ist Geschichte. Einfach '${appName}-abc-${environment}' schreiben. Das ist wesentlich leichter lesbar als "[concat(parameters('appName'), '-abc', variables('environment')]".

Referenzen auf andere Ressourcen und deren Eigenschaften ist auch gut gelungen.
Vorher:reference(resourceId('Microsoft.insights/components', variables('appInsightsName'))).InstrumentationKey]"

Nachher: AppInsights.properties.InstrumentationKey

Was funktioniert (noch) nicht?

Bicep ist im Alpha-Stadium (momentan Version 0.1). Das heißt, da gibt es sicher noch jede Menge fehlende Funktionalität.

Was ist mir bisher beim Testen aufgefallen?

  • Keine Parameter-Datei:
    Bicep 0.1 erzeugt noch eine Parameter-Datei. Es steht uns aber frei einfach eine “mytemplate.parameters.json” Datei anzulegen. Dann nat√ľrlich im ARM-Format.
  • Subscription Level Templates nutzen momentan das falsche Schema. Es werden nur ARM-Templates mit Resource Group Deployments erzeugt.
    Das erzeugte Template kann man trotzdem auf Subscription-Ebene anwenden.
  • Die API-Version muss fest angegeben werden, du kannst keine Variable daf√ľr nutzen (das ist aber eh gegen die Best Practices)
  • Verschacheltung von Funktionen: Ich habe es nicht geschafft bspw. einen String zusammen zu stellen und diesen dann direkt durch “toLower” zu schicken. Momentan regele ich das √ľber zwei Variablen.

Referenzen, Version, Quellcode

Zum Schluss: Bicep? Warum denn nun gerade Bicep? “Well, your biceps let’s you flex your ARM.” ūüėé … Ich bin ja schon weg…

Save money using Azure Hybrid Benefit for your VMs

What is the Hybrid (Use) Benefit?

Azure Hybrid Benefit (a.k.a. Azure Hybrid Use Benefit or HUB) is a offer by Microsoft for (re)using already existing On-premises licenses for Windows Server or SQL Server on Azure if they are under Software Assurance.

There are a few rules in place as to when and if you’re eligible for this.

A short exerpt from the Azure Hybrid Use FAQ regarding Windows Server:

Each 2-processor license or each set of 16-core licenses, Datacenter or Standard Editions, are entitled to two instances of up to 8 cores, or one instance of up to 16 cores. Datacenter Edition licenses allow for simultaneous usage both on-premises and in Azure. Standard Edition licenses must be used either on-premises or in Azure, although customers get 180 days of concurrent use rights while they are migrating their servers.

In the end, you only pay the Linux price of a virtual machine (only Compute costs), without the added minute price for the Windows Server license.

How can I use Hybrid Benefit for my VM?

You can activate this benefit while deploying your VM from the Portal.

Activate Azure Hybrid Use while deploying your VM

If you’re deploying your VM via PowerShell or Azure CLI you have to provide the “LicenseType” parameter.

Here is an example creating a new Windows Server 2016 VM with activated Hybrid Benefit.

New-AzVM `
    -ResourceGroupName "rg-workload1" `
    -Name "vm-srvwithhub" `
    -Location "West Europe" `
    -ImageName "Win2016Datacenter" `
    -LicenseType "Windows_Server"

How can I see how many VMs are using Hybrid Benefit?

It’s really just a parameter on the VM. So you can easily query all VMs within your subscription and look at the “LicenseType” parameter.

Get-AzVM ` | 
    Where-Object { $_.LicenseType -like "Windows_Server" } | `
    Select-Object ResourceGroupName, Name, LicenseType -ExpandProperty "HardwareProfile"

Be sure to also view and export the hardware size to determine exactly how many Windows Server licenses you are using.

For how many VMs may I activate the Hybrid Benefit?

Use this calculator to get your maximum server count with activated HUB: https://azure.microsoft.com/en-us/pricing/hybrid-benefit/

Hybrid Benefit Calculator for Windows Server VMs

I hope this helps you to save further (also unnecessary) costs in Azure.

Export your Azure inventory as CSV files

You can always use the Azure portal to export all your resources to one CSV file (Use the “All resources” blade and then click “Export to CSV”).

Script for exporting your inventory

Or you can use this script to export your Azure inventory. It builds different CSV files for each subscription with resources.

After downloading open your favorite PowerShell and type

.\Get-AzureInventory.ps1

Marketplace resources vs. CSP contracts

It also creates a CSV file thats contains only your marketplace items. This is most useful if you change your Azure contract model.

For example you switch from your EA/SCE or Pay-As-You-Go to a CSP contract then some of the marketplace resources aren’t available yet in CSP.

So you can send your CSP provider this files to give them an overview about your Azure environment and then discuss with them if all your resources will be available.

Download

Download ZIP file

or view the repository on GitHub:
https://github.com/cloudchristoph/AzureInventory

I’ve tested this with:

  • PowerShell 5.1
  • PowerShell 6.0 Core
  • Azure Az Module Version 3.3.0

Don’t hesitate to contact me if you have questions or ideas for this script.

What are the default security settings for an Azure VNet?

My client has asked me in our workshop:

What are the default security settings for an Azure VNet?

On an Azure VNet you cannot initially apply things like a Network Security Group, only things like allowed services (via Service endpoints or Private endpoints). So there are no default security settings except those that Microsoft itself always applies (e.g. DDoS Protection).

However, each VNet consists of at least one subnet. Network Security Groups (NSGs) can (and should) then be applied at the subnet level.

Whats a Network Security Group?

An NSG contains security rules in the form of a 5-tuple ACL.
So you define source IP (or IP range), destination IP (or IP range), source port, destination port and protocol (TCP or UPD). Furthermore you define the action – Allow or Deny.

The order is determined by priority. Higher priority (lower number) means that the rule will beat a rule with lower priority.

What are the default rules?

Default Network Security Group rules

For outgoing connections you’ll find these rules:

  • Allow any outgoing connections to other resources in the same VNet
  • Allow any outgoing connections to the Internet
  • Everything else outgoing? Deny

For incoming connections you’ll find these rules:

  • Allow any incoming connections from other resources in the same VNet
  • Allow any connections from Azure Load Balancer probes
  • Everything else incoming? Deny

“Unwritten rule” – Port 25

Port 25 (used for sending Emails over SMTP) is blocked by default if you’re not on an EA contract or your agreement was made after November 2017. If you want to send Mails from your VMs over Port 25, you’ll have to open a support case at Microsoft.
Why does this rule exist? I think that Microsoft wants to prevent spambots from running in Azure on a large scale and messing up the entire IP address space.

Should I adjust these default rules?

It depends (of course). For example, if you don’t want your resources in this VNet to communicate directly with the Internet, you have to adapt this rule.
Very often a rule is also set up that opens the RDP port for Windows or SSH for Linux. For this you should rather use modern methods like Azure Bastion or Just-in-time Access.

Learn more

Microsoft Docs about Network Security Groups

4 useful sites for your next Azure Workshop

Besides the Azure Portal of course, there are some useful and nicely done websites that I use during my workshops. Maybe they are also helpful for your next meeting.

Azure Charts

This site from Alexey Polkovnikov gives you a great overview over all Azure services and their latest updates. At this moment the region comparison tool is very useful to me. I use it for example to show my customers what services are still missing in the new Germany datacenters compared to West Europe.

Azure Speed

If my customers asking me about the “best” Azure region for they workloads from their location, i’ll open up Azure Speed and then discuss with them.

azureprice.net

When talking about different prices for the same service in each region, I’m opening azureprice.net/region and show them the difference in VM pricing.

AAD Application Proxy Port Check

“Are we ready for AAD App Proxy?” – Start with checking the connections from your designated server. It’s a nice starting point.¬†

If you have more useful sites, let me know!

« Older posts

© 2020 Christoph Vollmann

Theme by Anders NorenUp ↑