Training DevOps
Hands on
07/01/2019 - 08/01/2019
Qui sommes-nous ?
Gautier DARCHEN <gdarchen@takima.fr>
Jonathan LE BLOAS <jlebloas@takima.fr>
- eBusiness Information fondée en 2000
- Séparation en 2009 d’une société partenaire
- Gérée par François-Pierre CHALOPIN et Olivier DUVOID
- Changement de nom en mai 2018 pour Takima
- Incubateur de 2 startups
- Technologies Java, Javascript, etc.
- Activités devops
- Agilité
- Bagneux (Hauts-de-Seine)
Retrouvez ces slides ici :
https://slides.com/gautierdarchen/training-devops-handson/fullscreen
Qu'allons-nous faire durant cette formation ?
- Voir ce qu'est une application testée
- Voir comment lancer une BD dans un conteneur
- Voir comment exécuter les tests dans un autre conteneur
- Comprendre comment utiliser un gestionnaire de build
- Configurer toute une pipeline de CI
- Analyser la qualité d'un code
- Automatiser le déploiement d'une application
- [BONUS] : lancer une VM
- [BONUS] : ajouter des badges sur le README.md
Introduction aux technologies utilisées dans cette formation
- Apache Maven : outil de gestion et d'automatisation de production des projets Java / JavaEE
- Produire un artéfact à partir de sources en optimisant les tâches effectuées à ces fins
- Permettre au développeur d'appréhender un projet plus rapidement
La documentation dit :Making the build process easy
Providing a uniform build system
Providing quality project information
Providing guidelines for best practices development
Allowing transparent migration to new features
1/2
- Paradigme Project Object Model (POM)
- Fichier central : pom.xml
- Permet d'indiquer les dépendances, les plugins...
- Liste des fonctionnalités de Maven ici
- Lifecycle
2/2
Travis CI
- Logiciel libre d'intégration continue (CI)
- Permet de compiler, tester, déployer...
- PaaS (Platform as a Service)
- Intégration facilitée avec GitHub
- Configuration de la pipeline en langage YAML
- Outils similaires :
- Jenkins (à héberger soi-même)
- Gitlab CI (surtout si on utilise Gitlab)
1/2
Travis CI Lifecycle
2/2
Analyse de la qualité du code
- Outil en PaaS : SonarCloud
- Version Cloud de SonarQube
- Définition de règles propres au langage (ici Java)
- Définition d'une Quality Gate
- Contraintes à respecter si on veut que le build passe
- Lié à des métriques
- Utilisation de la Quality Gate par défaut pour la formation
Exemple pour notre projet
- Environnement de virtualisation
- Concept identique aux VM, mais beaucoup plus léger
- Un conteneur docker peut porter un service
- Or, lancer une VM complète pour un seul service, c'est overkill
- Une VM nécessite la réquisition d'une partie des ressources physiques de la machine hôte (RAM, CPU...)
- Docker se base sur l'OS de la machine hôte, il n'y a pas nécessité de lui allouer des ressources
- Sur une machine où on ne pourrait lancer qu'une VM, on pourrait théoriquement lancer des dizaines de conteneurs
Introduction
Introduction
- Les images s'exécutent dans un simple process et ne prennent donc pas plus de ressources qu'une exécutable, ce qui est bien plus léger qu'une VM
- Une VM lance complètement un OS "guest" avec des accès virtuels aux ressources de la machine hôte (hypervisor)
Conteneurs
- Flexibles : tout type d'application peut être conteneurisée
- Légers : les conteneurs exploitent et partagent le kernel hôte
- Interchangeables : on peut déployer des mises à jour et des mises à niveau à la volée
- Portables : on peut les créer localement, les déployer sur le cloud et les exécuter n'importe où
- Scalables : on peut créer plusieurs conteneurs à partir d'une image
- Stackables : on peut lancer des conteneurs de différentes images
- Une image docker est pensée pour faire tourner un seul service (ex. : un serveur web)
- On peut créer une seconde image pour lancer un autre process (ex. : une base de données)
- Ces images docker sont cloisonnées et n'ont pas d'intéraction avec la machine hôte
- Une image docker, c'est un ensemble d'instructions (écrites dans un Dockerfile) permettant de construire l'environnement cible
- Une image docker peut alors être build puis run
- Une instance d'une image Docker est appelée un container
Vocabulaire
Exemple d'image docker
FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py
Dockerfile
- Utilise une image de base : Ubuntu (image taguée 15.04)
- Copie le contenu du répertoire courant dans le /app du conteneur
- Construis l'application avec la commande "make"
- Spécifie la commande à exécuter dans le conteneur
Commandes de base
docker build -t image_test .
- Construction de l'image
- Exécution de l'image (pour lancer un container)
- Voir les containers sur la machine (lancés ou stoppés)
- Voir les images installées sur la machine
- Supprimer un conteneur
- Supprimer une image
docker run image_test
docker ps
docker image ls
# ou
docker images
docker rm <CONTAINER_ID>
docker rmi <IMAGE_ID>
Pratique
Créer un repository Git pour l'application
L'application Maven (sources et tests) est hébergée sur un repository Github
- Rendez-vous sur
https://github.com/takima-training/sample-application-students - Connectez-vous
-
Forkez le projet pour en créer votre propre copie :
- Clonez votre fork du projet :
# via SSH
$ git clone git@github.com:<login-github>/sample-application-students.git
# ou via https
$ git clone https://github.com/<login-github>/sample-application-students.git
Configuration Maven
(sur les postes INSA)
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64
# Run Unit Tests
export MAVEN_OPTS="-Dhttp.proxyHost=proxy.insa-rouen.fr -Dhttp.proxyPort=3128 -Dhttps.proxyHost=proxy.insa-rouen.fr -Dhttps.proxyPort=3128"
<settings>
<localRepository>/tmp/maven2</localRepository>
<proxies>
<proxy>
<active>true</active>
<protocol>http</protocol>
<host>proxy.insa-rouen.fr</host>
<port>3128</port>
</proxy>
</proxies>
</settings>
Configuration du proxy et localRepository
Avec le wrapper (évite d'avoir à installer mvn en local)
~/.m2/settings.xml
Lancement des tests unitaires
# Run Unit Tests
# Avec le wrapper
./mvnw clean test
# Sans si mvn est déjà installé
mvn clean test
Lancement d'une VM pour utiliser Docker
(uniquement les postes INSA)
- Créer et lancer la machine virtuelle
- Charger les variables d'environnement de la docker-machine
- Testez votre environnement docker
docker-machine create \
--engine-env HTTP_PROXY=http://proxy.insa-rouen.fr:3128 \
--engine-env HTTPS_PROXY=http://proxy.insa-rouen.fr:3128 \
--engine-env NO_PROXY=registry.insa-rouen.fr \
-d virtualbox \
--virtualbox-boot2docker-url file:///opt/iso/boot2docker.iso \
--virtualbox-cpu-count 2 \
--virtualbox-hostonly-cidr 10.0.0.1/24 \
default
eval $(docker-machine env default)
docker version
Développement en local
- Pull l'image Docker de la base de données
docker pull takimatraining/devops-training-db
- Lancer les tests en local (unitaires/intégration)
mvn verify \
-Dspring.datasource.url=jdbc:mysql://10.0.0.100:3306/SchoolOrganisation
- Lancer l'application en local
java -jar ./target/*.jar \
--spring.datasource.url=jdbc:mysql://10.0.0.100:3306/SchoolOrganisation
- Tester l'API REST
- via Postman : https://www.getpostman.com/collections/e4d2b84795e1149d6fa9
- via un navigateur web : http://localhost:8080/departments/ASI/students
- Lancer l'image Docker de la base de données
docker run -d -p 3306:3306 takimatraining/devops-training-db
Détail de l'API
- Students
- Get by ID
- Delete by ID
- Save new student
- Update existing student
- Departments
- Get students in a department by ID
- Get department by name
- Get number of students in a department by name
Documentation ici
Objectifs de la pipeline de CI
Test
Quality
Registry
Deploy
Automatiser les tests unitaires et d'intégration
Analyse de la qualité du code
Hébergement de l'application conteneurisée sur un registry
Déploiement de l'application en production
Binding GitHub / Travis CI
- Connectez vous à Travis CI avec vos identifiants GitHub
- Autorisez Travis CI à accéder à vos repositories GitHub
- Choisir le repository du projet pour permettre à Travis CI d'y accéder
Création de la pipeline
GitHub
Hook on commit
Travis CI
- A la racine du projet, créer un fichier ".travis.yml"
- Configuration du langage et du JDK
language: java
jdk: oraclejdk8
.travis.yml
Avant tout, lancer la BD
Travis CI
takimatraining/devops-training-db
Pull l'image de la BD
Lancement de la BD en tâche de fond
Docker Hub
takimatraining/devops-training-db
# Define the services to use
services:
- docker
before_install:
- sudo service mysql stop
- docker pull takimatraining/devops-training-db
- docker run -d -p 127.0.0.1:3306:3306 takimatraining/devops-training-db
.travis.yml
Lancement des tests
- Corps de votre pipeline : section script
- Lancement des tests
- Maven build lifecycle
# Run Unit Test and Integration Tests
script:
- mvn verify
.travis.yml
Lancer votre premier build
# Create your branch
$ git checkout -b ci_config
# Add the pipeline script to git
$ git add .travis.yml
# Commit
$ git commit -m "ci: first version of the pipeline to automate unit and integration tests"
# Push
$ git push --set-upstream origin ci_config
Rendez-vous sur https://travis-ci.org/ dans la page de votre projet et vérifiez que le build se fait sans erreur
Optimisation
-
Maven télécharge beaucoup de dépendances et les stocke dans ~/.m2/repository
- A chaque nouveau build, Travis CI perd par défaut le contexte
- L'environnement est donc complètement nouveau
- Pour éviter de retélécharger les dépendances à chaque fois, on peut utiliser du cache
# Cache the .m2 folder to prevent redownloading dependencies on each build
cache:
directories:
- "$HOME/.m2/repository"
.travis.yml
Rendez-vous sur
https://docs.docker.com/get-started/
Avancez au maximum
(fin demain après-midi)
Configuration de SonarCloud 1/2
-
Accéder à SonarCloud
-
Aller dans My Account > Security
-
Générer un nouveau token et le copier précieusement
-
Chiffrer ce token :
-
Ajouter ce token sécurisé à votre .travis.yml en variable d'environnement
# travis encrypt should be installed
# else :
# $ gem install travis
$ travis encrypt SONAR_TOKEN=<TOKEN>
# Environment variables are strings (double quotes)
# Example:
# - secure: "DpR1th9rZvLMX0......"
env:
global:
- secure: <ENCRYPTED_TOKEN>
.travis.yml
Configuration de SonarCloud 2/2
- Modifiez votre script pour rajouter l'analyse SonarCloud à la pipeline
- Testez votre configuration en faisant un nouveau commit et en consultant SonarCloud en vous rendant sur la page du projet
# The pipe (|) is useful to create multiline scripts
script:
- |
mvn clean install sonar:sonar \
-Dsonar.projectKey=<SONAR_PROJECT_KEY> \
-Dsonar.organization=<SONAR_ORGANISATION_KEY> \
-Dsonar.host.url=https://sonarcloud.io \
-Dsonar.login=$SONAR_TOKEN
.travis.yml
Utilisation de SonarCloud
- Allez consulter la dette technique
- Déclarez l'erreur en tant que faux positif
- Règle déclenchée malgré la conformité du code
Configuration de SonarCloud
[FACULTATIF]
Pour ceux qui sont en avance, essayez de configurer une Quality Gate avec 95% de couverture de test, puis commentez un test pour vérifier que votre build est bien en échec
Notifications en cas d'échec
Réception d'une notification en cas d'échec du build
-
On peut configurer des notifications vers une multitude de plateformes :
Mail
Slack
...
On veut ici qu'un mail soit envoyé à la personne qui vient de commit en cas d'échec du build
# Send an email to the commiter if the pipeline failed at some point
notifications:
email:
on_failure: always
.travis.yml
Conteneurisation
- Dockerfile à la racine du projet
FROM openjdk:8-jre
COPY target/*.jar /app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar", "--spring.datasource.url=jdbc:mysql://db:3306/SchoolOrganisation"]
Dockerfile
docker build -t java-app-image .
- Build de l'image
Lancer en local
- Creation du network
- Lancement du conteneur db
- Lancement du conteneur à partir de l'image buildée
- Votre application tourne en local
docker run --network net -p 80:8080 --name app java-app-image
docker run -d -p 3306:3306 --network net --name db takimatraining/devops-training-db
docker network create net
Pousser l'image sur Docker Hub 1/2
-
La pousser sur un registry : Docker Hub
-
Se connecter à Docker Hub
-
Créer un repository sur Docker Hub
-
exemple : <login>/sample-application
-
-
Chiffrer votre login et mot de passe Docker Hub
$ travis encrypt DOCKER_USER=<docker_user>
$ travis encrypt DOCKER_PASS=<docker_pass>
Pousser l'image sur Docker Hub 2/2
# Build an image containing the .jar and push it to the Docker Hub
script:
...
# Login to Docker hub
- docker login -u $DOCKER_USER -p $DOCKER_PASS
# Tag text according to the branch
- export TAG=`if [ "$TRAVIS_BRANCH" == "master" ]; then echo "latest"; else echo $TRAVIS_BRANCH; fi`
# Image name
- export IMAGE_NAME=<login>/sample-application-students
# Build the image (see Dockerfile) and tag it with the commit ID
- docker build -t $IMAGE_NAME:$TRAVIS_COMMIT .
# Retag the image with the previously choosen tag
- docker tag $IMAGE_NAME:$TRAVIS_COMMIT $IMAGE_NAME:$TAG
# Push the tagged image to Docker Hub
- docker push $IMAGE_NAME:$TAG
.travis.yml
-
Ajouter ces credentials chiffrés au .travis.yml
- Configurer la pipeline
env:
global:
# [...] other tokens
- secure: <encrypted Docker Username>
- secure: <encrypted Docker Password>
.travis.yml
Liste des serveurs
achille-lacoin.takima.io
ali-bellamlihmamou.takima.io
alice-giraud.takima.io
allan-milhomme.takima.io
ana-calin.takima.io
andres-morenosolano.takima.io
antoine-questel.takima.io
arnaud-quillent.takima.io
aurelien-toutain.takima.io
benjamin-peltier.takima.io
corentin-poriel.takima.io
corentin-potron.takima.io
damien-toomey.takima.io
darya-orel.takima.io
emma-bonhomme.takima.io
flavien-cocu.takima.io
flavien-disson.takima.io
francisco-nobrefilho.takima.io
gabriel-alencarmedeiros.takima.io
gauthier-wiemann.takima.io
guillaume-dron.takima.io
haitam-zouhair.takima.io
handi-zhang.takima.io
imane-lafnoune.takima.io
jeanfrancois-robin.takima.io
leopold-masson.takima.io
louis-ulmer.takima.io
manon-ferchaud.takima.io
matthias-sesboue.takima.io
matthieu-pavageau.takima.io
maxime-bourgeois.takima.io
mehdi-abouzaid.takima.io
michel-livney.takima.io
monica-salama.takima.io
nicolas-kempf.takima.io
paul-cadorel.takima.io
pierre-bernard.takima.io
pierrefrancois-giraud.takima.io
quentin-enjalbert.takima.io
quentin-lautridou.takima.io
sean-manzambi.takima.io
tanya-angelova.takima.io
theo-couppey.takima.io
thibault-sauron.takima.io
thibaut-emion.takima.io
thomas-constum.takima.io
thomas-digregorio.takima.io
timothee-guiraud.takima.io
vitor-martinbordini.takima.io
victoria-daura.takima.io
weihao-zhou.takima.io
yannis-pages.takima.io
Gestion de clés ssh
- Récupération de la clé privée envoyée par mail
- Enregistrez la (ex : ~/.ssh/id_rsa_insa_training)
- Nous utiliserons cette clé uniquement pour provisionnner la machine
- Générer une clé ssh sans passphrase que travis utilisera pour déployer
ssh-keygen -t rsa -b 4096 -C 'build@travis-ci.org' -f ./travis_deploy_rsa
Connexion à votre serveur
- Connexion SSH :
- Créer le network
- Lancer le conteneur de bd dans le network
- Ajouter la clé travis dans les authorized keys du user training à la main ou via ssh-copy-id
ssh -i /path/to/private_key training@<login>.takima.io
docker run --name=db --restart=always --volume mysql-data:/var/lib/mysql \
--network net -d takimatraining/devops-training-db
sudo docker network create net
travis login --org
travis encrypt-file path/to/private/key --add
Déploiement 1/2
- Ajouter 2 variables d'environnement DEPLOY_USER et SERVER_IP_ADDRESS
- Chiffrage via client travis ou défini dans l'interface Travis
before_install:
...
# Prepare deploy
- openssl aes-256-cbc -K $encrypted_xxxxxxx_key -iv $encrypted_xxxxxxxxxxx_iv
-in travis_deploy_rsa.enc -out /tmp/travis_deploy_rsa -d # Généré par travis encrypt-file
- chmod 600 /tmp/travis_deploy_rsa
- eval "$(ssh-agent -s)"
- ssh-add /tmp/travis_deploy_rsa
- echo -e "Host $SERVER_HOST\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
...
# Deploy updated container over ssh
deploy:
provider: script
script: ssh -i /tmp/travis_deploy_rsa $DEPLOY_USER@$SERVER_HOST "sudo docker pull $IMAGE_NAME:$TAG && sudo docker rm -f app || true && sudo docker run -d --network net -p 80:8080 --name app $IMAGE_NAME:$TAG"
on:
branch: master
.travis.yml
Déploiement 2/2
Votre application est en prod!
http://<YOUR-hostname>.takima.io/departments/ASI/students
[Bonus] - Badges dans le README.md 1/3
- Il est courant d'ajouter des "badges" dans le fichier README.md
- But des badges : indiquer l'état de la pipeline pour le dernier commit
- Badge de l'état de la CI
- Badge de l'analyse de la qualité du code
- etc...
[Bonus] - Badges dans le README.md 2/3
- Sur Travis CI, cliquer sur le badge :
- Sélectionner le langage Markdown et copier le texte généré
[Bonus] - Badges dans le README.md 3/3
- Ajoutez le au README.md de votre projet
- Pour le badge de coverage, sur SonarCloud, cliquer sur "Get project badges", puis sélectionner "coverage"
- Ajouter le lien au README.md en le formattant comme suit :
[![SonarCloud Coverage](https://sonarcloud...)](https://sonarcloud...)
Retrouvez la correction
https://github.com/takima-training/sample-application
Training DevOps - Hands on
By Gautier Darchen
Training DevOps - Hands on
- 1,600