Déployer efficacement et gouverner simplement les intermédiations

L’intégration continue est un classique dans les enjeux actuels de productivité des développements logiciels. Elle est répandue et maîtrisée pour les technologies comme Java.

Pour l’intégration des médiations ESB et API, cet aspect est plus délicat. Un projet d’ intermédiation est un ensemble de routes, elles-mêmes composées de sous-éléments tels que les demi-interfaces. Le CD/CD des bus d’entreprise ou des API finissent par être très riches. Il est alors difficile de gérer les déploiements de Projets qui englobent plusieurs médiations.

Pour m’être confronté à ce problème plusieurs fois, je vous propose une solution efficace qui se veut simpliste, basée sur le concept de séparation des cycle de vie, le tout sur des produits Open Source.

Intégration Continue et Déploiement Continue

L’ IC/DC est aujourd’hui un grand classique. Dans le domaine des ESB et API, l’approche est similaire aux projets Java.

Les produits d’intermédiation doivent être compilés, construits, testés et délivrés sur des plateformes multiples. En général, on dénombre les environnements suivants:

  1. Développement,
  2. Intégration,
  3. Recette,
  4. Pré-Production et
  5. Production.

La transition entre chaque environnement se déclenche lors de l’acceptation de la qualité des éléments testés.

Le temps nécessaire à déployer est toujours important. Entre les paramètres, les URL, les certificats, etc, cela n’est pas facile de s’y retrouver. Les minutes voir les heures s’accumulent et s’envolent. Les erreurs humaines sont aussi fréquentes. Bref, c’est un gouffre en temps et en effort… pour lequel je n’ai encore jamais vu de code d’imputation :-O !

Pour corser le tout, chaque projet fait évoluer son ensemble de demies-interfaces indépendamment des autres projets. Cela ajoute une dimension supplémentaire à ces jeux de déploiements. L’enjeu de la gouvernance des médications prend ici tout son intérêt.

Je ne peux que regretter qu’il faille malheureusement passer par cette étape de douleurs pour comprendre la plus-value de l’automatisation…

Vue statique

Vue statique des environnements

La représentation d’un environnement doit être stable. Je suis parti d’une définition simple afin d’obtenir un résultat maintenable.

Définition: Un environnement est un tout composé par plusieurs projets versionnés.

Exemples:


Pour chaque environnement, une simple liste est nécessaire. Un fichier de propriétés est suffisant. Il porte:

  • la liste des projets
  • la version Git à déployer/déployée.

Exemple de contenu:

A=1.0
B=1.1
C=2.0

Dépendances au Run Time

Les Projets d’intermédiation ont la particularité de multiplier les médiations. Celle-ci exposent 1 ou n contrats de services ou API. Chaque médiation est interdépendante avec d’autres. Elle est une consommatrice ou une productrice de messages, d’appels et d’événements. Comme, heureusement, les dépendances circulaires sont proscrites (et dangereuses), il est possible de les déployer en série.

Un orchestrateur doit porter cette complexité et apporter une interaction simple et accessible.

Exemple de 2 projets (BLEU et GRIS) composés de leurs médiations interdépendantes:

 

Dépendance au Design Time

Au fil du temps, les besoins évoluent et se complètent. Les Projets “utilisateurs” génèrent des changements. Par répercussion, chaque médiation évolue pour y répondre.

La gestion du changement

Chaque environnement évolue à son rythme et en fonction des priorités des projets qu’il accueille. Il nécessaire de comprendre que ces environnements n’évoluent pas suivant un processus linéaire. Les demandes de correctifs viennent bousculer le chemin simple des transitions entre environnements.

Moteur du changement

Le Projet “utilisateur” qui pilote ces changements est le moteur de ces évolutions. C’est donc celui-ci qui porte la définition des contraintes de déploiement.

Exemple d’orchestration au déploiement:

Projet BLEU Projet GRIS
  1. Médiation C
  2. Médiation B
  3. Médiation A
  1. Médiation C
  2. Médiation E
  3. Médiation D

Vue dynamique

La vue dynamique est la composition des 2 vues statiques précédentes:

  • Définition de l’environnement
  • Composition du projet.

Elle consiste en la mise à jour des plateformes d’exécution. Pour produire cela, il convient de :

  1. Récupérer la définition de l’environnement ciblé
  2. Pour chaque médiation du Projet:
    1. Récupérer la bonne version
    2. Adapter le projet à l’environnement ciblé
    3. Déployer la médiation.

Cette vue est portée par des orchestrateurs tels que JENKINS ou BAMBOO.

Exemple complet

Les environnements de Recette et de Production sont à un instant T composés de 2 projets, BLEU et GRIS, portant 5 médiations: A, B, C, D et E.

L’environnement de Recette exécute les évolutions les plus récentes afin de valider le comportement attendu.

L’environnement de Production execute les dernières versions stables des intermédiations.

 

Dans cet exemple, le projet BLEU, avec les médiations A, B et C n’évolue pas.

Le projet GRIS, avec les médications D et E évolue. Il tire avec lui l’évolution de la médiation C, initialement développée dans le cadre de BLEU.

Vue statique des environnements

Les fichiers des environnements mis en jeux sont alors:

RECETTE PRODUCTION
A=1.0
B=1.1
C=2.0
D=1.2
E=2.1
A=1.0
B=1.1
C=1.2
D=1.1
E=2.0

Pour permettre un suivi et une traçabilité des changements, ces fichiers sont gérés en configuration dans un projet GIT appelé governance. Il contient tous les fichiers de chaque environnement.

PS: Ajouter un environnement correspond à l’ajout d’un fichier.

Vue statique des projets

La définition du projet et de ses médiations (ici BLEU=A+B+C et GRIS=C+D+E) est déléguée à Jenkins. Chaque projet contient son fichier Jenkinsfile qui pilote l’orchestration.

Cette tâche de déploiement a besoin:

  • de l’environnement à cibler: paramètre ENV
  • de la release du projet governance (GOV_VERSION). Ceci permet de figer et de faciliter les rollback.

Chaque tâche Jenkins de déploiement des intermédiations sera appelée.

Dans notre exemple, les tâches C, D et E doivent :

  1. respecter le passage des paramètres (ci-dessous “ENV”, “VERSION” et “MAVEN_OPTIONS”).
  2. s’appeler comme le projet GIT référencé (ci-dessous “C”, “D” et “E”).

Le fichier Jenkinsfile de l’orchestration du project GRIS est donc similaire à ceci:


node {
	// input for task
	properties([
		parameters([
		text(defaultValue: '-Dmaven.test.failure.ignore=true', description: "Maven OPTIONS", name: "MAVEN_OPTIONS"),
		text(defaultValue: 'dev', description: "Environment", name: "ENV"),
		text(defaultValue: 'master', description: "Git version for GOVERNANCE", name: "GOV_VERSION")
		])
	])
	
	// Git checkout
	stage ('Checkout') {
		checkout scm
	}
	
	// Retreive governance
	// allow one build in parallel if version is used.
	stage ('Governance') {
		loadVersions(params.GOV_VERSION, params.ENV)
		print"Versions: "+props
	}
	
	// Deploy C
	stage ('Deploy mediation C') {
		def projectName ="C"
		buildProject(projectName)
	}
	
	// Deploy E
	stage ('Deploy mediation E') {
		def projectName ="E"
		buildProject(projectName)
	}

 	// deploy D
	stage ('Deploy mediation D') {
		def projectName ="D"
		buildProject(projectName)
	}
		
}

	// properties of versions
	def props
	
	// Load versions of projects
	def loadVersions(governanceVersion, environmentName) {
		bat "IF EXIST governance rmdir governance /q /s"
		bat "git clone $GOVERNANCE_GITURL governance"
		bat "cd governance"
		bat "git checkout ${governanceVersion}"
		// read versions of projects
		def envFile ="governance/${environmentName}.properties"
		print"Read file: "+envFile
		props = readProperties file:envFile
		print"Versions: "+props
	}
	
	// Build a jenkins project
	// Use version specifyed in properties file
	def buildProject(projectName) {
		print"Request build of "+projectName+":"+props[projectName]+" on "+params.ENV
		build(
			job: projectName,
			parameters: [
				[$class: 'StringParameterValue', name: 'ENV', value: params.ENV ],
				[$class: 'StringParameterValue', name: 'MAVEN_OPTIONS', value: params.MAVEN_OPTIONS ],
				[$class: 'StringParameterValue', name: 'VERSION', value: props[projectName] ]
			]
	)
}

PS: Ce fichier a été réalisé pour tourner sur Windows. Il suffit d’appeler “sh” au lieu de “bat” pour obtenir un résultat sur Lnux.

Execution Jenkins

Le déploiement dans Jenkins devient alors simplissime. Il suffit de demander l’exécution de la tâche du projet GRIS.

Celle-ci présentera un formulaire composé des variables du Jenkinsfile ci-dessus avec:

  • l’environnement ciblé,
  • la version du projet de Gouvernance,
  • quelques paramètres MAVEN comme les mots de passe.

Le résultat fera apparaitre les médiations inclus dans la tâche Jenkins:

Les étapes (stages) du pipeline Jenkins seront alors pour le projet GRIS:

  • Checkout
  • Governance
  • Deploy mediation C
  • Deploy mediation D
  • Deploy mediation E

Exemple de résultat de pipeline pour un déploiement SOA Suite:

Résumé

Ce mécanisme de CI/CD basé sur la définition des environnements facilite puis d’accélère les déploiements de “Projets applicatifs”. Il a été mis en oeuvre dans des contextes d’intermédiations ESB et API mais il peut être facilement être adapté à du Micro-Services ou des constellations d’applications plus classiques.

 

Mises en oeuvre

Pour finir, je vous partage 2 mises en oeuvre sur des plateformes bien différentes:

Si vous désirez des détails ou des démonstrations de ces déploiements, contactez-moi 😀 !

Laisser un commentaire