Les pratiques et outils présentés ci-après sont issues de la culture DevOps . Mais c'est quoi le DevOps ?
l’union des personnes, des processus et des technologies issus du développement (Dev) et opérations (Ops) destinés à fournir continuellement de la valeur aux clients
une culture
une stratégie opérationnelle
Dev: Modifications aux moindres coûts, le plus rapidement possible
Ops: Stabilité du système, qualité, sécurité
Améliorer la communication entre les développeurs et l’exploitation afin de réduire le temps de mise sur le marché d’un produit
Proposer des bonnes pratiques destinées à répondre au besoin croissant d’industrialisation et de normalisation du système d’information
Sécuriser et stabiliser les mises en production
Limiter les interventions humaines : sources principales d'erreur
Démarche qualité orientée industrialisation des développements
Démarche d'amélioration continue basée sur :
Démarche qui doit résoudre les problèmes
Dans le cadre d’une intégration continue
Utiliser le contrôle de code source
Valider tôt, valider souvent
Compiler votre solution à chaque commit
Automatiser les tests
Écouter les retours
Développer une culture DevOps
Dans le cadre d’une livraison continue
On automatise la phase de livraison
chaque fois qu’un nouvel artefact de build est disponible, l’artefact est automatiquement placé dans l’environnement souhaité et déployé.
Build unique
Séparer les préoccupations environnementales
Stocker la configuration dans le contrôle de code source (pas forcément au même endroit que le code)
Nettoyer vos environnements
Maintenir le pipeline
Dans le cadre d’un déploiement continu
On automatise l’ensemble du processus, de la validation du code à la production
L'étape entre les phases de développement et de livraison est automatique
Les modifications de code sont donc transmises en direct une fois qu’elles reçoivent la validation et réussissent tous les tests.
Dans les faits, déploiement et livraison continus sont souvent confondus
Maitriser la livraison continue et l'exploiter
Maitriser l'infrastructure
Automatiser chaque déploiement
Une bonne communication entre Dev et Ops
Maitriser les modes de déploiement (Rolling upgrade, Blue-green , canary)
L'idée : Rendre disponible une nouvelle version du logiciel à un petit sous-ensemble des utilisateurs (10%)
L'idée : Avoir deux environnements de production actifs en même temps (Bleu et Vert), mais un seul est utilisé
Déploiement et derniers tests du nouveau logiciel sur l’environnement non utilisé
Changement de version active en changeant le routage
Un CVS : git / github / gitlab / svn …
Un IDE : Eclipse , NetBeans , IDEA ...
Des outils de build : Jenkins, GitLab CI, GitHub Actions, teamCity ...
Une plateforme d’analyse du code : SonarQube , Code Climate...
Jenkins est un outil d’intégration continue descendant du projet Hudson.
Jenkins propose avant tout une gestion de tâche automatisée sur des projets enregistrés sur la plateforme.
Jenkins est un serveur Web, multiplateforme, développé en JAVA. Jenkins est construit en suivant un modèle maître/esclave.
Son principe est d’exécuter des scripts et d’utiliser le résultat de la commande pour définir le succès ou non de la construction du projet.
Muni de greffons (plugins, addons) Jenkins permet aussi de rapporter des métriques intéressantes tels que des graphiques d’évolution des tests unitaires, le code coverage ou encore le respect de normes de code.
Les pipelines
Les pipelines est le composant de premier niveau de l’intégration, de la livraison et du déploiement continus de GitLab.
Les pipelines gèrent des étapes qui contiennent des tâches qui sont exécutés sur des runners.
Les étapes (stages)
Les étapes sont simplement une division logique entre des ensembles de tâches.
Toutes les tâches d’une même étape sont exécutées en parallèle (s’il y a suffisamment de runners) et l’étape suivante ne commence que lorsque toutes les tâches de l’étape précédente sont terminées sans erreurs.
Il suffit que l’une des tâches échoue pour que l’ensemble du pipeline échoue à part quelques cas particuliers.
Les tâches
Une tâche est un ensemble d’instructions qu’un runner doit exécuter et peut produire un artefact.
Les artefacts
Un artefact peut contenir des fichiers et/ou dossiers qui vont être stockés au sein des pipelines pour être utilisé par d’autres tâches.
Il faut déclarer un manifeste .gitlab-ci.yml à la racine du projet
Dans ce manifeste vous allez pouvoir définir des stages, et des jobs
Basé sur une syntaxe yaml
stages :
- lint
- test
image: "python:3.7"
job_lint :
stage : lint
script :
- pip install pylint
- cd src
- pylint MyClass
job_test:
stage : test
script :
- cd src
- python -m unittest discover
Dans un premier temps, je définis les étapes de mon pipeline avec le mot clé stages.
Ce mot clé permet de définir l'ordre des étapes.
Ici, la première étape va être le lint, et ensuite les test.
stages :
- lint
- test
image: "python:3.7"
job_lint :
stage : lint
script :
- pip install pylint
- cd src
- pylint MyClass
job_test :
stage : test
script :
- cd src
- python -m unittest discover
image : l'image Docker qui va être lancée par GitLab afin d'exécuter les lignes de script que nous avons définies
stage : le nom de l'étape qui va apparaître dans notre pipeline d'intégration continue.
Cela correspond aussi au stage auquel sera exécuté le job
script : ce sont les lignes de script à lancer afin d'exécuter l'étape.
L'installation et l'exécution de pylint pour la partie lint et dans la partie test, nous lançons les tests unitaires.
Si un seul de ces tests échoue, le pipeline s'arrête.
stages :
- lint
- test
image: "python:3.7"
job_lint :
stage : lint
script :
- pip install pylint
- cd src
- pylint MyClass
job_test :
stage : test
script :
- cd src
- python -m unittest discover
Variables customisées déclarées dans Gitlab dans la partie CI/CD: $DB_URL, $passwords ...
Variables d'environnement liées aux projets, liées au repository, à l'exécution de la CI/CD : $CI_PROJECT_ID, $GITLAB_USER_NAME,$CI_JOB_STAGE ...
stage: test
script:
- echo "$CI_JOB_STAGE" # calls a predefined variable
- echo "$TEST" # calls a custom variable of type `env_var`
- echo "$VAR_FILE" # calls a custom variable of type `file` that contains the path to the temp file
- cat "$VAR_FILE" # the temp file itself contains the variable value
OUTPUT$ echo "$CI_JOB_STAGE"
test
$ echo "$TEST"
ceci est une variable ci/cd de test
$ echo "$VAR_FILE"
/builds/cylo/template-tp.tmp/VAR_FILE
$ cat "$VAR_FILE"
Ceci est un fichier qui doit contenir une variable
Cleaning up file based variables
Job succeeded
only , except , et environnement, vous pouvez créer des règles de déploiement différentes suivantes deploy_review :
stage : deploy
script :
- echo "Deploy a review app on $CI_ENVIRONMENT_SLUG"
environment :
name: review/$CI_COMMIT_REF_NAME
url: https://$CI_ENVIRONMENT_SLUG.example.com
only :
- branches
except :
- master
deploy_prod:
stage: deploy
script:
- echo "Deploy on prod"
environment:
name: production
url: https://www.example.com
only:
- master
when: manual
when: manual permet de ne pas déclencher automatiquement le déploiement en production, une intervention manuelle est nécessaireil suffit de publier du contenu html (généré automatiquement ou pas) dans le répertoire public
il faut ajouter un job spécifique intitulé pages
et il faut configurer les pages dans l'onglet Pages du menu Parameters
Exemple avec le générateur de site Hugo
image: monachus/hugo
pages :
script :
- hugo
artifacts :
paths :
- public
only:
- master
Exemple simplifié du déploiement de la documentation du CCIN2P3stages :
- build
- test
- docker
- wok
default :
image : docker:latest
sphinx :
stage : build
image : gitlab-registry.in2p3.fr/documentation/centre-de-calcul/cc-in2p3-docs-engine:master
script :
- './ci/doc_build.sh'
artifacts :
name: "CC-IN2P3"
paths :
- /builds/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/ci/htmloutput
preview_master :
stage : test
image : gitlab-registry.in2p3.fr/documentation/centre-de-calcul/cc-in2p3-docs-engine:master
script:
- './ci/doc_test_master.sh'
needs:
- job : sphinx
artifacts : true
docker:
stage: docker
services :
- docker : dind
script :
- docker login -u "$OPENSHIFT_NGINX_REGISTRY_USER" -p "$OPENSHIFT_NGINX_REGISTRY_PWD" $CI_REGISTRY
- docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" ./ci/
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
needs :
- job : sphinx
artifacts : true
wok :
image : docker.io/appuio/oc:v3.11
stage : wok
script :
- 'oc login $WOK_URL --insecure-skip-tls-verify --token $WOK_TOKEN'
- 'oc project $WOK_PROJECT'
- 'oc patch deployment $DEPLOYMENT_NAME -p "{\"spec\": {\"template\": {\"spec\": {\"containers\": [{\"name\": \"$CONTAINER_NAME\", \"image\":\"$CI_REGISTRY_IMAGE:$CI_COMMIT_TAG\"}]}}}}"'