Collecte de journaux Databricks avec Azure Monitor à l’échelle de l’espace de travail

Databricks est une plateforme d’analyse de données optimisée basée sur Apache Spark. La surveillance de la plateforme Databricks est cruciale pour garantir la qualité des données, la performance des tâches et les problèmes de sécurité en limitant l’accès aux espaces de travail de production.

Les métriques, les journaux et les événements de l’application Spark produits par un espace de travail Databricks peuvent être personnalisés, envoyés et centralisés vers diverses plates-formes de surveillance, notamment Journaux Azure Monitor. Cet outil, anciennement appelé Log Analytics par Microsoft, est un service cloud Azure intégré à Azure Monitor qui collecte et stocke les journaux des environnements cloud et sur site. Il fournit un moyen d’interroger les journaux à partir des données collectées à l’aide d’un langage de requête en lecture seule nommé “Kusto”, de créer des tableaux de bord “Classeurs” et de configurer des alertes sur les modèles identifiés.

Cet article se concentre sur l’automatisation de l’exportation des journaux Databricks vers un espace de travail Log Analytics à l’aide de l’outil Surveillance des étincelles bibliothèque à l’échelle de l’espace de travail.

Présentation de l’envoi de journaux Databricks


Présentation de la bibliothèque de surveillance Spark

Cette section est une vue d’ensemble de l’architecture. Des informations plus détaillées et le code source associé sont fournis plus loin dans l’article.

Surveillance des étincelles est un projet Microsoft Open Source pour exporter les journaux Databricks au niveau du cluster. Une fois téléchargée, la librairie est construite localement avec Docker ou Maven selon la version Databricks Runtime du cluster à configurer (versions Spark et Scala). La construction de la bibliothèque génère deux fichiers jar :

  • spark-listeners_$spark-version_$scala_version-$version: collecte les données d’un cluster en cours d’exécution ;
  • spark-listeners-loganalytics_$spark-version_$scala_version-$version: prolonge spark-listeners en collectant des données, en se connectant à un espace de travail Log Analytics, en analysant et en envoyant des journaux via l’API Data Collector

Dans la documentation, une fois les jars construits, ils sont mis sur le DBFS. Un script d’initialisation spark-monitoring.sh est modifié localement avec les configurations de l’espace de travail et du cluster et ajouté manuellement via l’interface Databricks au niveau du cluster.

Au lancement du cluster, les logs sont envoyés en streaming au format JSON vers l’API Log Analytics Data Collector et stockés dans 3 tables différentes, une pour chaque type de log envoyé :

  • SparkMetric_CL : Métriques d’exécution des applications Spark (utilisation de la mémoire, nombre de travaux, étapes des tâches soumises/terminées/en cours d’exécution) ;
  • SparkListenerEvent_CL : Tous les événements interceptés par SparkListener lors de l’exécution de l’application Spark (jobs, étapes et tâches start/end) ;
  • SparkLoggingEvent_CL : Journaux de l’appender log4j.

Certaines configurations permettent d’automatiser la configuration de l’envoi de journaux au niveau de l’espace de travail en configurant tous les clusters dans un espace de travail donné. Il s’agit de télécharger le projet, de le construire avec Docker ou Maven, d’éditer spark-monitoring.sh variables d’environnement du script et du cluster. Une fois toutes les configurations effectuées, l’exécution du script PowerShell configure l’espace de travail Databricks. Il est basé sur 3 scripts bash :

  • spark-monitoring-vars.sh: définir les variables d’environnement de l’espace de travail ;
  • spark-monitoring.sh: envoie les logs en streaming vers Log Analytics ;
  • spark-monitoring-global-init.sh: ce script à l’échelle de l’espace de travail s’exécute spark-monitoring-vars.sh alors spark-monitoring.sh.

Le script PowerShell dbx-monitoring-deploy.ps1 s’exécute localement et déploie des configurations au niveau de l’espace de travail. Il remplit spark-monitoring-vars.sh avec des variables d’espace de travail, copie les scripts et les jars dans DBFS et publie le script d’initialisation global dans Databricks.

Configuration d’un espace de travail

1. Construire les fichiers jar

Cloner le référentiel Surveillance des étincelles et créez localement les fichiers jar avec Docker ou Maven dans les versions d’exécution Databricks de tous les clusters qui doivent être configurés dans l’espace de travail conformément à la documentation.

Avec Docker :

A la racine de la spark-monitoring dossier, exécutez la commande build dans les versions Spark et Scala souhaitées. Dans cet exemple, la bibliothèque est conçue pour Scala 2.12 et Spark 3.0.1.

 docker run -it --rm -v pwd:/spark-monitoring -v "$HOME/.m2":/root/.m2 -w /spark-monitoring/src maven:3.6.3-jdk-8 mvn install -P "scala-2.12_spark-3.0.1"

Les bocaux sont construits dans le spark-monitoring/src/target dossier. La spark-monitoring.sh se trouve à l’intérieur du spark-monitoring/src/spark-listeners/scripts dossier.

Toutes ces étapes sont expliquées dans le chapitre Créer la bibliothèque de surveillance Azure Databricks du Référentiel GitHub des modèles et pratiques Microsoft.

2. Définition des variables d’environnement Log Analytics

L’ID et la clé de l’espace de travail Log Analytics sont stockés dans les secrets d’Azure Key Vault et référencés dans les variables d’environnement de tous les clusters configurés. Azure Databricks accède au coffre de clés via l’étendue secrète de l’espace de travail Databricks.

Après avoir créé les secrets de l’ID et de la clé de l’espace de travail Log Analytics, configurez chaque cluster en référençant manuellement les secrets en suivant les instructions sur la façon de configurer l’étendue secrète basée sur Azure Key Vault.

LOG_ANALYTICS_WORKSPACE_KEY=secrets/secret-scope-name/pw-log-analytics
LOG_ANALYTICS_WORKSPACE_ID=secrets/secret-scope-name/id-log-analytics

3. Ajout des scripts spark-monitoring-global-init.sh et spark-monitoring-vars.sh

Créer un jars dossier, téléchargez tous les jars et les fichiers de configuration en respectant l’arborescence de fichiers suivante :


Arborescence des fichiers du projet

  • spark-monitoring-global-init.sh: Ce script est lancé au lancement de chaque cluster dans l’espace de travail.

    #!/bin/bash
    
    
    STAGE_DIR=/dbfs/databricks/spark-monitoring
    
    
    VARS_SCRIPT=$STAGE_DIR/spark-monitoring-vars.sh
    
    MONITORING_SCRIPT=$STAGE_DIR/spark-monitoring.sh
    
    
    if [ -d "$STAGE_DIR" -a -f "$VARS_SCRIPT" -a -f "$MONITORING_SCRIPT" ]; then
    
    /bin/bash $VARS_SCRIPT;
    /bin/bash $MONITORING_SCRIPT;
    
    else
    echo "Directory $STAGE_DIR does not exist or one of the scripts needed is missing"
    fi
  • spark-monitoring-vars.sh: Ce script est un modèle de toutes les variables d’environnement nécessaires au niveau du cluster et de l’espace de travail.

    #!/bin/bash
    
    
    
    
    
    
    
    DB_HOME=/databricks
    SPARK_HOME=$DB_HOME/spark
    SPARK_CONF_DIR=$SPARK_HOME/conf
    
    tee -a "$SPARK_CONF_DIR/spark-env.sh" << EOF
    # Id of Azure subscription
    export AZ_SUBSCRIPTION_ID="$AZ_SUBSCRIPTION_ID"
    # Resource group name of workspace
    export AZ_RSRC_GRP_NAME="$AZ_RSRC_GRP_NAME"
    export AZ_RSRC_PROV_NAMESPACE=Microsoft.Databricks
    export AZ_RSRC_TYPE=workspaces
    # Name of Databricks workspace
    export AZ_RSRC_NAME="$AZ_RSRC_NAME"
    EOF

4. Modification et ajout de spark-monitoring.sh

Copie spark-monitoring.sh du projet cloné, ajoutez-le à l’arborescence de fichiers et modifiez les variables d’environnement comme suit :

DB_HOME=/databricks
SPARK_HOME=$DB_HOME/spark
SPARK_CONF_DIR=$SPARK_HOME/conf

tee -a "$SPARK_CONF_DIR/spark-env.sh" << EOF
# Export cluster id and name from environment variables
export DB_CLUSTER_ID=$DB_CLUSTER_ID
export DB_CLUSTER_NAME=$DB_CLUSTER_NAME
EOF

Compte tenu des coûts de stockage importants associés à un espace de travail Log Analytics, dans le contexte des métriques Spark, appliquez des filtres basés sur des expressions REGEX pour conserver uniquement les informations de journaux les plus pertinentes. Cette documentation sur le filtrage des événements vous donne les différentes variables à définir.

5. Modification, ajout et lancement du script PowerShell

Le scénario dbx-monitoring-deploy.ps1 est utilisé pour configurer l’exportation des journaux de cluster d’un espace de travail Databricks vers Log Analytics.

Il effectue les actions suivantes :

  1. Remplit spark-monitoring-vars.sh avec des valeurs correctes pour l’espace de travail.
  2. Téléchargements spark-monitoring-vars.sh, spark-monitoring.sh et tous les fichiers jar sur l’espace de travail de DBFS.
  3. Publie via le contenu de l’API Databricks du script d’initialisation global.

Il suppose qu’il existe 3 abonnements Azure différents (DEV/ PREPROD/ PROD) pour séparer les phases de développement, de test et de production d’une intégration continue. Un abonnement de préproduction est utilisé pour les tests d’intégration et les tests d’acceptation métier avant de passer en production.

Modifiez cette section en fonction de vos abonnements.


param(
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]$p,
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]$e,
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]$n,
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]$rg,
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]$w
    )

$armFolder = $p.TrimEnd("/","\")

$deploymentName = $n.ToLower()
$varsTemplatePath = "$armFolder/spark-monitoring-vars.sh"

if ($e -like "dev")

    $AZ_SUBSCRIPTION_ID = ""

elseif ($e -like 'prod') 
    $AZ_SUBSCRIPTION_ID = ""

elseif ($e -like 'preprod') 
    $AZ_SUBSCRIPTION_ID = ""

else
    Write-Output "no environment provided - exiting"
    Exit-PSSession




$AZ_RSRC_GRP_NAME = $rg
$AZ_RSRC_NAME = $w
$environment = $e.ToLower()

$parametersPath = "$armFolder/$environment/$deploymentName/spark-monitoring-vars-$environment-$deploymentName.sh"

$template = Get-Content "$varsTemplatePath" -Raw
$filledTemplate = Invoke-Expression "@`"`r`n$template`r`n`"@"

mkdir -p $armFolder/$environment/$deploymentName
Out-File -FilePath $parametersPath -InputObject $filledTemplate



try 
    $context = get-azContext
    if(!$context)
    
        Write-Output "No context, please connect !"
        $Credential = Get-Credential
        Connect-AzAccount -Credential $Credential -ErrorAction Stop
    
    if ($environment -like "dev")
    
        set-azcontext "AD-DEV01" -ErrorAction Stop
    
    elseif ($environment -like 'prod') 
        set-azcontext "AD-PROD01" -ErrorAction Stop
    
    elseif ($environment -like 'preprod') 
        set-azcontext "AD-PREPROD01" -ErrorAction Stop
    
    else
        Write-Output "no context found for provided environment- exiting"
        Exit
    

catch
    Write-Output "error setting context - exiting"
    Exit




$mydbx=Get-AzDatabricksWorkspace  -ResourceGroupName $AZ_RSRC_GRP_NAME
$hostVar = "https://" + $mydbx.Url

$myToken = Get-AzAccessToken -Resource "2ff814a6-3304-4ab8-85cb-cd0e6f879c1d"

$env:DATABRICKS_AAD_TOKEN=$myToken.Token

databricks configure --aad-token --host $hostVar

databricks fs mkdirs dbfs:/databricks/spark-monitoring

databricks fs cp --overwrite $armFolder/spark-monitoring.sh dbfs:/databricks/spark-monitoring
databricks fs cp --overwrite $armFolder/$environment/$deploymentName/spark-monitoring-vars-$environment-$deploymentName.sh dbfs:/databricks/spark-monitoring/spark-monitoring-vars.sh
databricks fs cp --recursive --overwrite $armFolder/jars dbfs:/databricks/spark-monitoring



$inputfile = "$armFolder/spark-monitoring-global-init.sh"
$fc = get-content $inputfile -Encoding UTF8 -Raw
$By = [System.Text.Encoding]::UTF8.GetBytes($fc)
$etext = [System.Convert]::ToBase64String($By, 'InsertLineBreaks')

$Body = @
    name = "monitoring"
    script = "$etext"
    position = 1
    enabled = "true"


$JsonBody = $Body | ConvertTo-Json

$Uri = "https://" + $mydbx.Url + "/api/2.0/global-init-scripts"

$Header = @Authorization = "Bearer $env:DATABRICKS_AAD_TOKEN"

Invoke-RestMethod -Method Post -Uri $Uri -Headers $Header -Body $JsonBody

Enrichissez et lancez le script avec ces paramètres :

Appelez le script comme suit :

pwsh dbx-monitoring-deploy.ps1 -p /home/Documents/pwsh-spark-monitoring/pwsh-deploy-dbx-spark-monitoring -e DEV -n deploy_log_analytics_wksp_sales -rg rg-dev-datalake -w dbx-dev-datalake-sales

Grâce à ce script, vous pouvez facilement déployer la librairie Spark-monitoring sur tous vos espaces de travail Databricks.

Les journaux envoyés nativement permettent de surveiller la santé du cluster, l’exécution des tâches et de signaler les erreurs à partir des blocs-notes. Une autre façon de surveiller le traitement quotidien des données consiste à effectuer une journalisation personnalisée à l’aide de l’appender log4j. De cette façon, vous pouvez ajouter des étapes pour implémenter la validation de la qualité des données sur les données ingérées et nettoyées et des tests personnalisés avec une liste prédéfinie d’attentes pour valider les données.

Nous pouvons imaginer utiliser des journaux personnalisés pour consigner les mauvais enregistrements, appliquer des vérifications et des contraintes sur les données, puis envoyer des métriques de qualité à Log Analytics pour les rapports et les alertes. Pour ce faire, vous pouvez créer votre propre bibliothèque de qualité des données ou utiliser des outils existants tels que Apache Griffon ou Amazon Deeque.