Comment automatiser le déploiement des ressources Azure avec Terraform à l'aide des Pipelines Azure DevOps.

TERRAFORM

Terraform est un outil open-source développé par HashiCorp, et utilisé pour provisionner et gérer des infrastructures IT dans le Cloud. Écrit en Go et fonctionnant en mode Infrastructure as a Code (IAC), il permet d’administrer une infrastructure grâce à du code au lieu de procéder à un ensemble d’opérations manuelles.

La force de Terraform est de reposer sur un langage de description d’infrastructure simple et lisible, on parle ici de HCL. L’approche IAC de Terraform permet de gérer le versioning d’une infrastructure en lui ajoutant ou retirant des composants.

Objectif

Dans cet article, nous allons voir :

  1. Comment définir une stack Terraform simple
  2. Comment utiliser conjointement Terraform et Azure DevOps dans l’optique de déployer l’infrastructure Azure, de manière automatique et continue.

Initialisation du projet

Voici la structure de fichier que nous allons adopter :

|– src\
|– terraform\
|– README.md

|– src\ will contain the sources of the Ansible Config,
|– terraform\ will contain all the deployment files.

1- Azure service principal

Rendons-nous dans Azure Active Directory et allons dans la partie App registrations.

  • Connectez-vous à votre compte Azure sur https://portal.azure.com
  • Cliquez sur le bouton Cloud Shell pour lancer le Cloud Shell.
  • La commande ci-dessous créera un principal de service avec le nom « SPName ». Remplacez la valeur et exécutez la commande dans le cloud shell.
az ad sp create-for-rbac --name SPName
  • À l’issu de cette commande, Azure CLI retournera un block JSON contenant les informations nécessaires a l’authentification du SP (client-id, client-secret)
abd###@Azure:~$ az ad sp create-for-rbac --name SPName
Changing "SPName" to a valid URI of "http://SPName", which is the required format used for service principal names
Creating a role assignment under the scope of "/subscriptions/##########-c1b3-####-8b7a-####9578ebf0"
  Retrying role assignment creation: 1/36
  Retrying role assignment creation: 2/36
  Retrying role assignment creation: 3/36
{
  "appId": "########-4611-4c09-9728-6ec9284314de",
  "displayName": "SPName",
  "name": "http://SPName",
  "password": "########",
  "tenant": "########-d76d-45cf-a7d2-ae98f73067ee"
}
  • Complétez le formulaire. Cliquez sur Vérifier la connexion pour vous assurer que les valeurs fonctionnent comme prévu. Cliquez sur OK une fois vérifié. Vous pourrez désormais référencer cette connexion à partir des tasks du pipeline.

2- TERRAFORM / INFRASTRUCTURE

|– src\
|– terraform\
____|– main.tf
____|– outputs.tf
____|– provider.tf
____|– variables.tf
____|– variables.tfvars
|– README.md

MAIN.tf file

data "azurerm_client_config" "current" {
}

locals {
  resource_group_name = "rg-${var.env}"

  tags = {
    env = "${var.env}"
  }
}

# ======================================================================================
# Resource Group
# ======================================================================================

resource "azurerm_resource_group" "resource_group" {
  location = "${var.location}"
  name     = "${var.env}-rg"
  tags     = "${local.tags}"
}

# ======================================================================================
# KeyVault
# ======================================================================================

resource "azurerm_key_vault" "key_vault" {
  name                        = "${var.env}-keyvault"
  location                    = "${azurerm_resource_group.app_resource_group.location}"
  resource_group_name         = "${azurerm_resource_group.app_resource_group.name}"
  tenant_id                   = "${data.azurerm_client_config.current.tenant_id}"
  enabled_for_disk_encryption = true

  sku {
    name = "standard"
  }

  access_policy {
    tenant_id = "${data.azurerm_client_config.current.tenant_id}"
    object_id = "${data.azurerm_client_config.current.object_id}"

    secret_permissions = [
      "get",
      "list",
      "set",
      "delete"
    ]
  }

  tags = "${local.tags}"
}

# ======================================================================================
# Network
# ======================================================================================

resource "azurerm_virtual_network" "vnet" {
  name                = "${var.vnet-name}"
  address_space       = "${var.address_space}"
  dns_servers         = [
           "192.168.0.1",
           "168.168.25.1",
        ]
  location            = "${azurerm_resource_group.resource_group.location}"
  resource_group_name = "${azurerm_resource_group.resource_group.name}"

  tags     = "${local.tags}"
}

resource "azurerm_subnet" "subnet" {
  name                 = "${var.subnet-name}"
  resource_group_name  = "${azurerm_resource_group.resource_group.name}"
  virtual_network_name = "${azurerm_virtual_network.vnet.name}"
  address_prefix       = "${var.address_prefix}"
  tags     = "${local.tags}"
}

resource "azurerm_network_interface" "vm-network-interface" {
  name                = "${var.vm-name}"
  location            = "${azurerm_resource_group.resource_group.location}"
  resource_group_name = "${azurerm_resource_group.resource_group.name}"
  
  ip_configuration {
    name                          = "vm-ipconfig"
    subnet_id                     = "${azurerm_subnet.subnet.id}"
    private_ip_address_allocation = "Dynamic"
  }
}
# ======================================================================================
# VM
# ======================================================================================

resource "azurerm_virtual_machine" "virtual-machine" {
  name                  = "${var.vm-name}"
  location              = "${azurerm_resource_group.resource_group.location}"
  resource_group_name   = "${azurerm_resource_group.resource_group.name}"
  network_interface_ids = ["${azurerm_network_interface.vm-network-interface.id}"]

  vm_size               = "DS3V2"

  storage_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2016-Datacenter"
    version   = "latest"
  }
  storage_os_disk {
    name              = "vm-os-disk"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
    
  }

  os_profile {
    computer_name  = "${var.computer-name}"
    admin_username = "${var.AdminUsername}"
    admin_password = "${var.AdminPassword}"
  }

}

PROVIDER.TF file

provider "azurerm" {
  version = "1.44.0"
}

terraform {
  required_version = "0.11.21"
  backend "azurerm" {
    storage_account_name = "shared$$_application_$$tfsa"
    container_name       = "terraform"
    key                  = "terraform-$$_environment_$$.tfstate"
    access_key           = "$$_tf_storage_account_key_$$"
  }
}

VARIABLES.TF file

data "azurerm_client_config" "current" {
}

provider "azurerm" {
    version = "=1.44.0"
    subscription_id  = "${data.azurerm_client_config.current.subscription_id}"               
    client_id        = "${data.azurerm_client_config.current.client_id}"                  
    tenant_id        = "${data.azurerm_client_config.current.tenant_id}"
    client_secret    = "$$_client_secret_$$"                 
    }

variable "env" {
  type = "string"
}
variable "location" {
  type = "string"
}
variable "address_space" {
  type = "string"
}
variable "subnet-name" {
  type = "string"
}
variable "address_prefix" {
  type = "string"
}

VARIABLES.TFVARS file

env = "$$_env_$$"
location = "$$_location_$$"
address_space = "$$_0.0.0.0/0_$$"
subnet-name = "$$_subnet-name_$$"
address_prefix = "$$_0.0.0.0/24_$$"

3- PIPELINE

Prérequis

Un compte GitHub, où vous pouvez gérer vos repository. Si vous n’en avez pas, vous pouvez créer un gratuitement.

Une organisation Azure DevOps. Si vous n’en avez pas, vous pouvez en créer une gratuitement. (Une organisation Azure DevOps est différente de votre organisation GitHub. Par best-practices, donnez-leur le même nom)

Commençons par créer notre premier pipeline !

1- Azure DevOps – BUILD

Créons un nouveau Build Pipeline, puis cliquer sur Use the visual designer pour avoir le mode visuel.

Pour ce lab, nous utiliserons la branche master.

commencer par un Empty job

Ensuite, ajoutez Publish Artifact. Cette étape est utilisée pour incorporer les fichiers Terraform dans l’artifact.

Ensuite, spécifiez le dossier ou le chemin du fichier à publier. Il peut s’agir d’un full path ou d’un chemin relatif à la racine du repository.

Enfin, procédons au lancement de notre première build. Si tout se passe bien, nous obtenons l’artifact suivant :

2- Azure DevOps – RELEASE

Créons maintenant un nouveau Release Pipeline, pour ce faire, nous allons commencer à partir d’un modèle de travail vide Empty job template.

Renommons la première étape DEV.

Pour utiliser Terraform, nous avons besoin de :

  1. créer son backend sur Azure Storage (Blob),
  2. récupérer la Key de ce Storage et de l’injecter dans les variables pour pouvoir écrire/lire dans le Blob.

Première étape, ajoutons une étape de type Azure CLI pour la création du backend :

az group create --location $(location) --name "rg-$(env)-tfstate" 

az storage account create --name "sa$(env)tfstate$(location)" --resource-group "rg-$(env)-tfstate" --location $(location) --sku Standard_LRS  --tags 

az storage container create --name "terraform" --account-name "sa$(env)tfstate$(location)"

Next, add a second job Azure Powershell to get the storage account access_key

$key = (Get-AzStorageAccountKey -ResourceGroup "rg-$(env)-tfstate" -Name "sa$(env)tfstate$(location)").Value[0]

Write-Host "##vso[task.setvariable variable=tf_storage_account_key]$key"

The following two steps allow you to replace the tokens ($$_value_$$) present in the Terraform files.

Ensuite, ajoutons les tasks terraform:

  • install terrafrom ()
  • init
  • validate
  • plan
  • apply

Add Pipiline variables

Link a KeyVault to your DevOps pipeline project

Conclusion

Dans cet article, nous avons vu comment provisionner une infrastructure Azure avec Terraform, le tout, déployé de manière continue au travers d’Azure DevOps 🙂

prochains articles :

  1. Configurer une ressource (AD serveur) a l’aide d’Ansible-DevOps en one shot
  2. Configurer une ressource (AD serveur) a l’aide du DSC-DevOps en one shot

L&L Kubernetes et AKS

Retrouvez notre Expert Christophe, dans une vidéo sur Kubernetes et AKS. La vidéo est Level 100, accessible à tous. URL sur Youtube: ici

Contenu: Il s’agit de prendre un projet Web API sous Visual Studio 2019 avec support Docker (container Linux) et de construire l’image Docker en local. Ensuite on pousse cette image dans une registry ACR afin de faire un déploiement dans un cluster AKS. Ensuite, on aborde kubectl, l’outil console de Kubernetes.

Pour réaliser toutes les opérations techniques, un HOWTO est à télécharger sur https://infeeny.com/net-core-sous-aks/

Infeeny est dans le magazine Programmez de Mars 2020

Retrouvez nos experts Infeeny dans le numéro 238 du magazine Programmez de Mars 2020.

On y trouve un article sur le monde du développement selon Microsoft avec un focus sur NET 5, la plateforme unifiée qui va sortir en Novembre 2020. C’est la fusion entre NET Framework 4.8 et NET Core 3.1.

Les experts Infeeny qui ont participé à cet article sont Timothé LARIVIERE et Christophe PICHAUD.

SQL 2019 Les nouveautés et les retours d’experience

Comme prévu Microsoft nous l’avait annoncé il y a quelque temps une nouvelle version de SQL Server est bientôt prête à arriver.

A l’heure actuelle, où j’écris ces lignes, nous en sommes à la version CTP 2.1

Au menu plein de petites nouveautés :

  • Du Machine Learning
    • Possibilité de créer un cluster Spark Big Data
      • Déployer des applications Python et R
    • Déployer un cluster Big Data avec des conteneurs SQL et Spark Linux sur Kubernetes
    • Accéder à votre Big Data à partir de HDFS
    • Exécuter l’analytique avancée et le Machine Learning avec Spark
    • Utiliser Spark Streaming pour envoyer des données aux pools de données SQL
    • Utiliser Azure Data Studio pour exécuter des livres de requêtes qui procurent une expérience de bloc-notes
  • Moteur de base de données
    • Traitement des requêtes intelligent avec la fonction inlining de fonction UDF
    • Amélioration de la gestion des erreurs en incluant les noms de tables de colonnes ainsi que les valeurs tronquées (pour les erreurs de troncations)
    • Prise en charge de l’UTF 8 à l’installation
    • Utilisation d’alias de tables dérivées ou de vues dans les requêtes de correspondance de graphe
    • Amélioration des données de diagnostic pour le blocage des statistiques
    • Pool de mémoires tampons hybride
    • Masquage statique des données
  • Linux
    • Prise en charge de la réplication
    • Prise en charge de MSDTC (Microsoft Distributed Transaction Coordinator)
    • Groupe de disponibilité Always On sur des conteneurs Docker avec Kubernetes
    • Prise en charge d’OpenLDAP pour les fournisseurs AD tiers
    • Machine Learning sur Linux
    • Nouveau registre de conteneurs
    • Nouvelles images conteneur basées sur RHEL
    • Notification de sollicitation de la mémoire
  • Outil
    • Azure Data Studio
      • Mise a jour pour SQL 2019
      • Nouvel outil SQL Server

 

Retour d’expérience :

Après avoir testé rapidement cette nouvelle version, j’ai eu quelques déboires avec PolyBase sans doute dû à des problèmes de drivers HDFS qui ont changé avec l’arrivée de la nouvelle version…

J’ai pu tester la mise en place de cluster Spark et vérifier l’intérêt de celui ci On-prem avant de diffuser sur un vrai cluster Spark en ligne sur Azure par exemple.

Il a un autre intérêt, il permet de travailler les données en amont de leur intégration et peut venir remplacer un ETL comme SSIS lors de la phase de Data Prep cela peut donc devenir une alternative intéressante. SQL2019

Exemple d’utilisation d’un script d’analyse prédictive depuis un cluster spark sur un un SQL Server 2019 en version CTP 2.1.

SparkSQL2019.png

Sources :

https://docs.microsoft.com/fr-fr/sql/sql-server/what-s-new-in-sql-server-ver15?view=sqlallproducts-allversions

Hands-on SharePoint Spaces, VR solution at the Microsoft Ignite 2018

I must admit that I was quite skeptical when I heard about this new feature earlier this year. One of the main reasons of my skepticism was that I could not find the right use case from an end-user perspective. During the Microsoft Ignite, 3 booths were available to get our hands on this new solution, so why not testing this and trying to change my mind ? 

SharePoint Spaces tested by Mozzaik Team

It started with a quick introduction from Vidya who’s part of the Microsoft SharePoint Space product team. I discovered that there are already 7 webparts developed, and more to come. Microsoft teams already using this feature internally, yet I couldn’t find if it would be easy to programmatically convert or extend a webpart so they support the 3D glasses, but I guess it’ll be possible with PnP in due time.

 

Creating a new space is really easy, you just need to select the « New » menu in the ribbon as you would do for a new page or a list. Select from the spaces available, and you’ll have the page loading instantly. I’ve seen the organization chart demo, then the data visualization (mind blowing!!)

SharePoint Spaces Data Vizualisation

 

So what about the rendering ? Though it’s still at the early stage for this technology, I can really see the potential in an industrial environment, especially for the FLW (First Line Workers) when browsing the details of a piece and following a specific process which could be a « Process viewer WebPart ». And folks, that’s the key take away here : the WebParts.

 

SharePoint Spaces Tent with the WebPart panel opened

My skepticism relied on the absence of solid user scenarios that could justify the investment on this technology, but knowing that it relies on webPart, I can easily imagine specific webparts for supply chain processes, where you trigger the right process with the controller, and it points out the manufactured pieces and the associated steps to build the piece. Also, knowing that FLW and Product teams could share and use the same Site and interface could really benefits for the communication for the whole building process. 

From a technology standpoint, it relies on BabylonJS , GLTF format for 3D scenes and models, and the HP Windows  Mixed Reality for the headset and the controller. 

If you want to know more about SharePoint Spaces and the mixed reality, check the Microsoft article : https://www.microsoft.com/en-us/microsoft-365/blog/2018/05/21/sharepoint-innovations-transform-content-collaboration-with-mixed-reality-and-ai/