AOUT 03

Visual Studio Code Extensions - ARM Params File Generator

Si comme moi, vous êtes un utilisateur courant de Visual Studio Code, vous savez qu’il s’agit du deuxième meilleur produit fourni par Microsoft (juste après Azure).

Ce produit est génial parce qu’il est très simple de l’enrichir via des extensions, comme Visual Studio, sauf que contrairement à ce dernier la création des extensions est extrêmement simple.

J’ai donc créé une extension qui s’appelle ARM Params File Generator

Le pourquoi de cette extension est très simple, j’écris le plus souvent des templates ARM qui ont les particularités d’être très paramétrables, voire trop, et elles impliquent le plus souvent des ressources complexes comme Service Fabric.

Ce qui me donne l’avantage de pouvoir réutiliser mes templates dans plusieurs cas, par exemple si je prends celui que je vous ai présenté dans l’article : http://blog.woivre.fr/blog/2018/05/service-fabric-creer-un-cluster-via-un-template-arm

J’utilise ce template dans les cas suivants :

  • 1 node type de 3 noeuds pour les démos
  • 2 node type de 3 noeuds chacun pour des tests infra
  • 3 node type de 7 noeuds primaires et pleins de secondaires pour les clients

Créer mes templates via VS Code est assez facile avec les tools ARM qui vont biens à savoir :

Autant créer son fichier de paramètres sans faire de faute de frappe sur le nom de mes paramètres est une plaie, j’ai donc créé une extension qui le fait pour moi et donc pour vous !

Allez vite l’installer -> ARM Params File Generator

Dans les fonctionnalités que j’ai mises en place :

Génération d’un nouveau fichier de paramètres

Il est possible de le faire de pleins de manières différentes :

  • Clic droit un peu partout si cela a un rapport avec le fichier (editeur, exploreur, titre), puis Azure RM: Generate parameters file
  • Lancer la commande Azure RM: Generate parameters file qui prendra en compte la fenêtre active

Consolidation d’un fichier de paramètre existant

Pour cela, rien de plus simple il faut lancer la commande Azure RM: Consolidate parameters file, puis renseigner les 2 fichiers.

Pour cette fonctionnalité, j’ai pris le choix de n’ajouter que des valeurs et de ne pas supprimer des paramètres exitants.

Le mieux maintenant pour vous est de télécharger cette extension, et je serais bien entendu enchanté si vous avez des fonctionnalités que vous souhaiteriez que j’implémente.

Pour rappel voici les liens


JUIL 23

Sandbox Azure - Monitorer l'usage grâce à Event Grid

Dans le cadre de la sandbox Azure dont je vous ai parlé dans les articles précédents:

Sur ma sandbox, j’ai donc mis en place la création des utilisateurs, et des groupes de ressources. Les utilisateurs sont dorénavant autonomes sur la plateforme Azure.

Afin que la consommation ne s’envole pas, j’utilise des Azure Policy afin de limiter les SKUs de certains services, à la fois ceux que je juge possiblement coûteux et ceux que je juge utiles. Pas besoin d’avoir un IoT Hub en standard pour faire des tests.

Cependant il s’agit ici d’une souscription utilisée pour faire de l’auto-formation, afin d’être proactif, je souhaite savoir quel type de service est utilisé sur la plateforme et par qui. Pour réaliser cela, je vais utiliser Event Grid afin de m’abonner aux actions qui sont réalisées sur la souscription.

Afin de mettre cela en place, je vais créer une Logic Apps, et utiliser le trigger “When a Event Grid event occurs”

image

Ensuite je configure ce trigger de cette manière afin de monitorer l’intégralité des évènements qui sont déclenchés sur la souscription

image

Après cette étape je vous conseille de jouer quelques évènements afin de voir le format qui est généré par celui-ci pour l’exploiter par la suite.

De ces données je souhaite extraire les informations suivantes :

  • Id de l’évènement
  • Heure de l’évènement
  • Action réalisée (Création ou Suppression principalement)
  • Scope
  • Nom de l’utilisateur ou Id du service principal

J’ai donc effectué divers tests pour avoir quelques exemples de json générés par des actions. Dès que j’ai mes différents exemples, je les compare afin de chercher les informations dont j’ai besoin. Ici, je vois que la structure est légèrement différente entre les actions générées par un utilisateur, et celles faites par un Service Principal.

Dans mon workflow Logic Apps, je vais donc ajouter une action de type “Data Operations - Parse JSON” et je vais lui fournir un exemple de json afin de générer un schéma, j’aurai bien entendu pris en compte les différences entre mes deux structures.

Ce qui me donne cette opération suivante :

image

J’ai donc en 2 étapes récupéré les données que je souhaitais avoir, je peux donc soit les stocker dans un Table Storage par exemple, ou les envoyer par mail dans mon cas.

Je le fais ici via une tâche Gmail, car Logic Apps est un produit contenant une grande quantité de connecteurs et qui ne sont pas tous liés à Microsoft.

image

On peut noter par ailleurs que ma tâche précédente extrait toutes le données dans des variables, ce qui est très facile à utiliser par la suite.

Par ailleurs, petit tips, dans la tâche Gmail, le format HTML est dans les options avancées.


JUIL 17

Service Fabric Mesh

Le mois de juillet a apporté pleins de bonnes nouvelles, la France a gagné une deuxième étoile, mais cela est anecdotique par rapport à l’annonce de Microsoft autour du produit Service Fabric. La public preview de Service Fabric Mesh est enfin disponible !

Pour ceux qui ne l’ont pas vu, voici le lien : https://azure.microsoft.com/en-us/blog/azure-service-fabric-mesh-is-now-in-public-preview/

Ceux qui ont déjà mis en place des clusters Service Fabric en production savent que le côté “Service managé” a quelques limites qui peuvent vous faire perdre quelques cheveux, d’ailleurs j’en ai écrit un retour d’expérience sur ce blog : http://blog.woivre.fr/blog/2018/01/bonne-resolution-prendre-soin-de-son-cluster-service-fabric

En résumé ce qui vous pose des problèmes avec Service Fabric c’est bien souvent l’infrastructure sur laquelle repose votre cluster. Service Fabric Mesh vous permet de ne plus vous soucier de cette infra sous-jacente.

Par contre à ce jour, cela a un coût, il faut dire adieu aux Reliables Services et au SDK fourni par Service Fabric, et mettre un focus sur les Containers. Pour le coût financier, pour le moment c’est gratuit en preview et bien entendu sans SLA.

Dans cet article, je vous propose de regarder comment déployer nos premiers services sous Service Fabric Mesh.

Commençons par installer le module pour la CLI Azure, pour info il n’y a pas encore de module pour Powershell

# Lister les extensions présentes
az extension list
# Supprimer l'installation précédente
az extension remove --name mesh
# Installer la nouvelle version 
az extension add --source https://sfmeshcli.blob.core.windows.net/cli/mesh-0.8.1-py2.py3-none-any.whl

Déployons l’application de démo fournie par Microsoft :

az mesh deployment create --resource-group myResourceGroup --template-uri https://sfmeshsamples.blob.core.windows.net/templates/helloworld/mesh_rp.linux.json --parameters "{'location': {'value': 'westeurope'}}"

On remarquera que Service Fabric Mesh est dispo sur le datacenter West europe, la liste exhaustive n’est pas disponible sur la documentation Azure, mais je pense qu’il s’agit de la même que Service Fabric, c’est-à-dire toutes les régions Azure.

Dans le portail Azure, on peut voir notre application Mesh comme ci-dessous :

Il s’agit là d’une preview, donc on ne va pas avoir beaucoup plus de détails dans le portail Azure.

Maintenant si on regarde un peu plus le template ARM qu’on a déployé précédemment,on voit qu’il s’agit de celui ci :

{
  "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "metadata": {
        "description": "Location of the resources."
      }
    }
  },
  "resources": [
    {
      "apiVersion": "2018-07-01-preview",
      "name": "helloWorldNetwork",
      "type": "Microsoft.ServiceFabricMesh/networks",
      "location": "[parameters('location')]",
      "dependsOn": [],
      "properties": {
        "addressPrefix": "10.0.0.4/22",
        "ingressConfig": {
          "layer4": [
            {
              "name": "helloWorldIngress",
              "publicPort": "80",
              "applicationName": "helloWorldApp",
              "serviceName": "helloWorldService",
              "endpointName": "helloWorldListener"
            }
          ]
        }
      }
    },
    {
      "apiVersion": "2018-07-01-preview",
      "name": "helloWorldApp",
      "type": "Microsoft.ServiceFabricMesh/applications",
      "location": "[parameters('location')]",
      "dependsOn": [
        "Microsoft.ServiceFabricMesh/networks/helloWorldNetwork"
      ],
      "properties": {
        "description": "Service Fabric Mesh HelloWorld Application!",
        "services": [
          {
            "type": "Microsoft.ServiceFabricMesh/services",
            "location": "[parameters('location')]",
            "name": "helloWorldService",
            "properties": {
              "description": "Service Fabric Mesh Hello World Service.",
              "osType": "linux",
              "codePackages": [
                {
                  "name": "helloWorldCode",
                  "image": "seabreeze/azure-mesh-helloworld:1.1-alpine",
                  "endpoints": [
                    {
                      "name": "helloWorldListener",
                      "port": "80"
                    }
                  ],
                  "resources": {
                    "requests": {
                      "cpu": "1",
                      "memoryInGB": "1"
                    }
                  }
                },
                {
                  "name": "helloWorldSideCar",
                  "image": "seabreeze/azure-mesh-helloworld-sidecar:1.0-alpine",
                  "resources": {
                    "requests": {
                      "cpu": "1",
                      "memoryInGB": "1"
                    }
                  }
                }
              ],
              "replicaCount": "1",
              "networkRefs": [
                {
                  "name": "[resourceId('Microsoft.ServiceFabricMesh/networks', 'helloWorldNetwork')]"
                }
              ]
            }
          }
        ]
      }
    }
  ]
}

On voit dans ce template ARM, 2 objets. Le premier est un composant réseau de type ‘Microsoft.ServiceFabricMesh/networks’

    {
      "apiVersion": "2018-07-01-preview",
      "name": "helloWorldNetwork",
      "type": "Microsoft.ServiceFabricMesh/networks",
      "location": "[parameters('location')]",
      "dependsOn": [],
      "properties": {
        "addressPrefix": "10.0.0.4/22",
        "ingressConfig": {
          "layer4": [
            {
              "name": "helloWorldIngress",
              "publicPort": "80",
              "applicationName": "helloWorldApp",
              "serviceName": "helloWorldService",
              "endpointName": "helloWorldListener"
            }
          ]
        }
      }
    }

Il s’agit là d’un composant réseau où l’on peut mettre nos applications, attention il ne s’agit pas d’un Virtual Network sur Azure.

Les informations essentielles sont donc les suivantes :

  • La plage d’adresse IPs disponibles, ici : 10.0.0.4/22
  • Les points d’entrées réseaux contenant
    • Le nom de votre endpont : helloWorldIngress
    • Le port : 80
    • Le nom de votre application qui sera exposé : helloWorldApp
    • Le nom de votre service qui sera exposé : helloWorldService
    • Le nom de votre endpoint : helloWorldListener

Le deuxième élément correspond à notre service applicatif:

              "osType": "linux",
              "codePackages": [
                {
                  "name": "helloWorldCode",
                  "image": "seabreeze/azure-mesh-helloworld:1.1-alpine",
                  "endpoints": [
                    {
                      "name": "helloWorldListener",
                      "port": "80"
                    }
                  ],
                  "resources": {
                    "requests": {
                      "cpu": "1",
                      "memoryInGB": "1"
                    }
                  }
                }

Il contient par ailleurs le type de l’OS, puisque ici on embarque la définition de notre cluster. Ici, il s’agit d’un OS de type linux, car après tout c’est généralement des images Docker pour linux que l’on crées.

On définit ensuite nos différents containers en renseignant le type de l’image. Ici il s’agit d’images situées sur Docker Hub

Par ailleurs si vous souhaitez déployer depuis une registry privée comme Azure Container Registry, vous pouvez mettre ces informations dans le template ARM :

"image": "azure-mesh-helloworld:1.1-alpine",
"imageRegistryCredential": {
    "server": "[parameters('registry-server')]",
    "username": "[parameters('registry-username')]",
    "password": "[parameters('registry-password')]"
},

Vous pouvez retrouver différents exemples de template ARM pour Service Fabric sur ce github : https://github.com/Azure/azure-rest-api-specs/tree/master/specification/servicefabricmesh/resource-manager/Microsoft.ServiceFabricMesh/preview/2018-07-01-preview

Il existe différents exemples de code fournis par Microsoft, notamment la classique voting-app, mais il y a aussi containo une application de démo créée par la Tom Kerkhove qui montre comment utiliser Service Fabric Mesh : https://github.com/tomkerkhove/containo/blob/master/deploy/service-fabric-mesh/service-fabric-mesh-orders-declaration.json


JUIL 10

Migrer vos vieux comptes de stockage

Mois de juillet oblige, c’est le grand nettoyage de printemps avec quelques mois de retard. Je suis donc en train de faire le grand ménage dans mes différents comptes Azure.

Si comme moi il vous reste des vieux comptes de stockage en mode classic, il est peut être temps de les migrer.

La procédure est très simple à faire en Powershell notamment, à partir du moment ou vous êtes Classic Admin de votre souscription Azure.

Pour commencer il vous faut le module powershell Azure, installer le si vous n’avez que AzureRM.

Install-Module Azure

Ensuite, il vous faut vérifier que le provider Microsoft.ClassicInfrastructureMigrate est bien enregistré sur votre souscription, soit via le portail Azure, soit via powershell via les commandes suivantes :

Install-AzureRmResourceProvider -ProviderNamespace Microsoft.ClassicInfrastructureMigrate

Get-AzureRmResourceProvider -ProviderNamespace Microsoft.ClassicInfrastructureMigrate

Attention, il s’agit là de commande AzureRM, il faut donc être loggué en conséquence.

Maintenant tout le reste se fait en mode classic, on va donc commencer par s’authentifier à l’ancienne

Add-AzureAccount
Select-AzureSubscription -SubscriptionName $subscriptionName

Afin de valider si votre storage est migrable, vous pouvez utiliser la commande suivante :

Move-AzureStorageAccount -Validate -StorageAccountName $storageAccountName

Cette commande vérifie notamment qu’il n’y a pas de disques de VM attaché à ce storage account.

Maintenant que tout est validé, il est possible de migrer via ces 2 commandes powershell

Move-AzureStorageAccount -Prepare -StorageAccountName $storageAccountName

Move-AzureStorageAccount -Commit -StorageAccountName $storageAccountName

Il est possible d’annuler l’opération entre le Prepare et le Commit via la commande

Move-AzureStorageAccount -Abort -StorageAccountName $storageAccountName

Après un temps plus ou moins long, selon votre Storage Account, vous pouvez retrouver votre Storage Account fraichement migré dans un nouveau Resource Group s’appelant “$storageAccountName-Migrated”

Il est bien entendu possible de le Move par la suite afin de le mettre au bon endroit dans votre souscription

A noter au passage qu’il a changé de resourceId, cela va donc impacter les différentes ressources liées telles que :

  • Les dashboard Application Insights
  • L’autoscaling basé sur des métriques provenant de ce storage
  • Tout autre produit se basant sur les resourceId

Bien entendu, cela va de soit, vos clés primaires et secondaires d’accès au storage sont inchangées.

Je vous souhaite une bonne migration !


JUIL 02

Sandbox Azure - Mise en place de policy Azure

Dans le cadre de la sandbox Azure dont je vous ai parlé dans les articles précédents:

Maintenant que les utilisateurs peuvent créer un compte et créer des ressources groups, je souhaite contrôler certaines de leurs actions afin que ce ne soit pas l’anarchie au bout de 2 semaines. Je souhaite donc contrôler les éléments suivants :

  • La localisation des ressources : afin de m’assurer que tout soit situé en Europe
  • Le niveau de SKU des ressources : afin de m’assurer d’avoir encore du crédit à la fin de la semaine

Pour effectuer cela, j’ai plusieurs solutions qui s’offrent à moi.

  • Soit je contrôle ces éléments lors de la création des ressources.

  • Soit je le fais a posteriori, ce qui demande d’analyser les différents objets et de mettre en place du développement spécifique basé sur EventGrid afin de valider les différentes ressources qui ont été créées, et effectuer les opérations nécessaires par la suite.

  • Soit encore je le fais à la création des ressources, pour cela il est possible de mettre en place une surcouche applicative qui prend tous les templates ARM et qui les valide avant les exécuter, mais du coup cela oblige tous les utilisateurs à passer par un système tiers et de ce fait ne pas pouvoir avoir une expérience totale via le portail Azure. Et par ailleurs en cas de changement de règle les ressources existantes ne sont pas prises en compte.

Afin d’allier les deux, une fonctionnalité existe sur Azure, il s’agit de la fonctionnalité “Policy – Compliance” que l’on peut retrouver sur le portail ou via les API REST / Azure Powershell / Azure CLI

Il existe par défaut un certain nombre de policy qu’il est possible d’exploiter, comme par exemple les suivantes :

  • Allowed Locations : Elle permet de limiter l’utilisation de différentes régions sur Azure, utile si par exemple vous ne souhaitez avoir que des ressources en Europe
  • Allowed Resource types : Elle permet de limiter l’usage des ressources avec un filtre plus fin que l’utilisation ou non d’un provider. Par exemple pour autoriser l’utilisation de Service Fabric, et en refusant celle des edgeclusters
  • Enforce tag and its value : Comme son nom l’indique elle permet de forcer l’usage d’un tag, ce qui peut être pratique pour des gestions de coûts par exemple
  • Allowed virtual machine SKUs : Permet de garder uniquement les tailles de machines virtuelles que l’on souhaite utiliser, par exemple en n’autorisant pas celle avec des GPUs

Il est possible d’assigner ces règles à des scopes Azure , un peu comme le système RBAC, sauf qu’ici on est limité à la souscription ou à un groupe de ressource, ce qui est déjà en soit bien suffisant.

Ci-dessous voici un json d’un exemple de politique associé à ma souscription :

{
  "Name": "686a94bb904447afb201f2cf",
  "ResourceId": "/subscriptions/subscription_id/providers/Microsoft.Authorization/policyAssignments/686a94bb904447afb201f2cf",
  "ResourceName": "686a94bb904447afb201f2cf",
  "ResourceType": "Microsoft.Authorization/policyAssignments",
  "SubscriptionId": "subscription_id",
  "Properties": {
    "displayName": "Allowed locations",
    "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c",
    "scope": "/subscriptions/subscription_id",
    "notScopes": [

    ],
    "parameters": {
      "listOfAllowedLocations": {
        "value": [
          "francecentral",
          "francesouth",
          "northeurope",
          "westeurope"
        ]
      }
    },
    "description": "Only specific locations are available for CloudSandbox",
    "metadata": {
      "assignedBy": "Admin Admin",
      "parameterScopes": {
        "listOfAllowedLocations": "/subscriptions/subscription_id"
      }
    }
  },
  "Sku": {
    "name": "A0",
    "tier": "Free"
  },
  "PolicyAssignmentId": "/subscriptions/subscription_id/providers/Microsoft.Authorization/policyAssignments/686a94bb904447afb201f2cf"
}

Cependant vu que rien n’est parfait, il n’y a pas plétore de policy “build-in”, et donc pas toujours celles que l’on souhaite. Bonne nouvelle cependant, tout comme les rôles RBAC, il est possible d’en créer des personnalisables.

Par exemple, si je souhaite limiter le type de SKU d’une instance SQL Database, je peux écrire le JSON suivant :

{
	"if": {
		"allOf": [
			{
				"field": "type",
				"equals": "Microsoft.Sql/servers/databases"
			},
			{
				"not": {
                    "field": "Microsoft.Sql/servers/databases/requestedServiceObjectiveName",
                    "in": "[parameters('listOfSKUId')]"
				}
			}
		]
	},
	"then": {
		"effect": "deny"
	}
}

Il est possible par la suite de l’associer à notre souscription via cette commande Powershell

New-AzureRmPolicyDefinition -Name 'SqlDBSkus' -DisplayName 'My custom policy for SQL DB SKUs' -Policy 'SQLDbsSKUsPolicy.json'

Après, la mise en place de votre policy se fait soit via le portail Azure, soit via cette commande powershell.

$rg = Get-AzureRmResourceGroup -Name 'rg-demo'
$policy = Get-AzureRmPolicyDefinition -Name 'SqlDBSkus'
New-AzureRmPolicyAssignment -Name 'limit-sql-db-skus' -DisplayName 'Custom policy for SQL DB SKUs' -Scope $rg.ResourceId -PolicyDefinition $definition -PolicyParameter .\AllowedSqlDBSkus.json

Les policy Azure vous offrent de ce fait la possibilité de mieux gérer et organiser votre souscription Azure que ce soit pour valider des règles de naming ou mieux maitriser le coût comme ici.