Ajouter des paramètres pour le déploiement du template ARM Azure Data Factory

La longueur du titre de cet article laisse présager du niveau de précision dans lequel nous allons nous lancer ! Je vais donc rapidement situer le contexte faisant appel à un tel besoin.

Nous cherchons à déployer de manière automatisée un environnement de développement Azure Data Factory sur l’environnement de production. Nous utilisons pour cela un pipeline de release Azure DevOps. Le processus DevOps pour ADF est expliqué dans ce livre blanc Microsoft ou dans cet excellent article de Florian Eiden.

Pour résumer les grandes lignes du fonctionnement, nous remplaçons dans un fichier de paramètres au format JSON les valeurs des chaînes de connexion de l’environnement de développement par celles de production. Ceci se fait au moyen de la case « override template parameters ».

Valeurs manquantes pour le service lié Databricks

La chose se complique lorsque nous utilisons un service lié de calcul de type Azure Databricks puisque les paramètres de ce service n’apparaissent pas par défaut dans le fichier de paramétrage ! Nous avons en particulier besoin de remplacer :

  • La Databricks Workspace URL
  • Le Secret name (où se trouve enregistré un Personal Access Token correspondant à l’espace de travail souhaité)

En effet, un choix arbitraire a été fait par Microsoft pour présenter uniquement certains paramètres mais un grand nombre de valeurs existent et elles sont visibles en éditant le fichier disponible dans le menu : Parametrization template.

Ce fichier au format JSON recense l’intégralité des paramètres disponibles par défaut, ainsi que leur visibilité au moyen d’une propriété qui n’est pas simple à interpréter :

= (signe égal) permet de conserver la valeur actuelle en tant que valeur par défaut pour le paramètre

– (signe moins) permet de ne pas conserver la valeur par défaut pour le paramètre

Le symbole | (pipe) permet de réaliser le lien avec une valeur stockée dans le coffre-fort Azure Key Vault.

Nous allons maintenant rechercher le nom des paramètres manquants. Pour cela, nous passons par la définition du service lié Databricks au format JSON.

Nous obtenons ainsi le nom exact des paramètres (ne pas se fier à l’interface graphique).

L’URL de l’espace de travail se nomme ainsi domain, le secret du Key Vault se désigne par secretName et ses deux propriétés dépendent du niveau TypeProperties et du sous-niveau accessToken pour le secret.

Nous pouvons donc maintenant citer ces propriétés dans le JSON des paramètres, en respectant l’arborescence des propriétés.

La définition des paramètres dans la branche Master

Arrive ici la partie peut-être la moins documentée (jusqu’à présent !). Il faut comprendre que ce fichier JSON doit figurer à la racine de la branche Master du dépôt contenant la synchronisation du Data Factory avec un gestionnaire de version comme GitHub ou un repo Azure DevOps, sous le nom arm-template-parameters-definition.json.

Il ne faut donc pas utiliser la branche spécifique à Data Factory qui se nomme adf_publish mais nous irons ensuite vérifier que les deux fichiers JSON qu’elle contient ont bien été modifiés en conséquence.

Pour lancer cette modification, nous devons tout d’abord faire les deux actions suivantes :

  • Refresh
  • Publish

Le volet latéral du Publish (pending changes) doit s’afficher même si aucune modification n’est visible.

Nous pouvons enfin vérifier que les paramètres sont disponibles dans le fichier ARMTemplateParametersForFactory.json de la branche adf_publish.

Modifier la valeur des paramètres pendant la release

Il ne reste qu’à utiliser ces noms de paramètres dans le pipeline de release Azure DevOps. Les nouvelles valeurs peuvent être définies comme des variables du pipeline pour plus de commodité.

Cet article a pu être écrit grâce à la documentation officielle de Microsoft ainsi que d’autres articles de blog, en anglais, que leurs auteurs en soient ici remerciés :

https://medium.com/@sanajitghosh/manage-ci-cd-pipelines-using-azure-devops-azure-data-factory-azure-databricks-8239a9ceef3

https://www.modern-dataengineering.com/post/how-to-add-custom-parameters-to-data-factory-templates

https://medium.com/@patrickpicard_50914/azure-data-factory-modifying-arm-template-parameters-53b11f38bced

Relancer un pipeline Azure Data Factory

Azure Data Factory est à la fois un ordonnanceur de traitements, un ETL ou un ELT selon la manière dont on pense les transformations et le chargement dans la destination (« sink » dans le vocable d’ADF). Il est muni d’une fenêtre de monitoring permettant de superviser l’exécution de pipelines au travers de triggers (déclencheurs en bon français). Et il ne sera pas rare (le plus rare possible, on vous le souhaite !) de rencontrer les icônes rouges de l’échec du traitement dans cette fenêtre.

Pipeline run : status failed

Dans cet article, nous allons explorer différentes méthodes de déclenchement ou relance d’un pipeline Azure Data Factory.

Relancer manuellement

Depuis le monitoring des pipelines, nous disposons de plusieurs boutons comme le bouton « rerun » au niveau de l’exécution globale du trigger.

Lorsqu’il existe une ou plusieurs activités dans le pipeline, il suffit d’aller sur le détail de l’exécution du pipeline pour choisir une des activités (cliquer dessus) et la relancer (« rerun from failed activity »). Ce second mode est particulièrement intéressant lorsqu’une chaîne de traitement a déjà réalisé des étapes importantes et ne nécessite pas d’être reprise depuis le début. Les gains de temps de traitement seront sans doute conséquents.

Ces deux stratégies sont bien sûr manuelles et nécessitent de venir observer la console de supervision. Nous allons maintenant explorer des stratégies plus automatisées.

Démarrage ou relance automatique

Une approche classique de déclenchement des pipelines consiste à définir un jour et une heure de déclenchement. S’il existe des dépendances aux activités, on prendra soin d’inclure différentes activités au sein du même pipeline et de les relier grâce aux différentes sorties disponibles (« add activity on »).

Il existe quatre types de conditions :

  • Success
  • Failure
  • Completion : exécution de l’activité suivante en cas de succès ou d’échec de l’activité
  • Skipped : exécution de l’activité suivante uniquement si l’activité n’a pas été exécutée

Ce blog vous permettra de rentrer plus en détails dans le fonctionnement de ces conditions.

Mais certains événements comme la présence d’un fichier, de lignes dans une table ou encore la réponse à une requête HTTP peuvent être des conditions de déclenchement attendues.

Par le paramétrage d’une activité

La manière sans doute la plus simple et basique de relancer une activité consiste à utilise le paramétrage de l’activité elle-même. Pour cela, dans la section General du module :

  • Renseigner un nombre maximum de Retry
  • Renseigner un intervalle en secondes entre chaque essai

Remarque : le time out par défaut est à 7 jours, il peut être diminuer.

Il faut toutefois anticiper ici un nombre maximum fini de relances, ce que l’on n’est pas forcément en capacité d’anticiper.

A la première exécution avec succès, les retry ne sont bien sûr plus pris en compte.

Les activités de type for each ou execute pipeline ne disposent pas de ce paramétrage.

Avec le composant Until

La documentation du composant Until est disponible sur ce lien et définit son fonctionnement de la sorte :

The Until activity provides the same functionality that a do-until looping structure provides in programming languages. It executes a set of activities in a loop until the condition associated with the activity evaluates to true. You can specify a timeout value for the until activity in Data Factory.

Nous allons créer ainsi le scénario suivant : sur présence d’un fichier testé par le composant Until, nous déclenchons une activité de copie.

Une variable nommée FileExists, de type chaîne de texte (string), est définie au niveau du pipeline.

A l’intérieur du composant Until, nous allons travailler avec deux activités que sont Get Medatada et Wait.

L’activité Get Metadata permet d’obtenir des informations sur un dataset préalablement défini, comme un checksum de type MD5, le nom, le type ou l’existence d’un item.

Le composant suivant Set variable n’est pas indispensable mais il nous permet d’illustrer ici la manière de conserver dans une variable une partie de l’information obtenue par l’activité Get Metadata.

La valeur de la variable est définie de la sorte :

@string(activity('Get Metadata from Source').output.exists)

On utilisera la fenêtre d’ajout de contenu dynamique pour obtenir directement certaines parties de cette expression.

Enfin, une activité Wait est déclenchée pour laisser un laps de temps s’écouler avant de tester à nouveau la présence du fichier.

Le composant If exists permet de ne pas jouer l’activité Wait lorsque le fichier attendu est détecté. Il n’est pas nécessaire de définir la partie True de ce composant.

L’activité Until peut enfin paramétrée à l’aide de l’expression suivante :

@equals(variables(‘FileExists’),’True’)

Voici enfin une démonstration du fonctionnement complet de ce pipeline.