Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Des principes de la démarche DevOps à sa mise en oeuvre

7,192 views

Published on

Slides de ma présentation DevOps effectuée dans le cadre du Developer Day 2016 à l'ESGI

  • Be the first to comment

Des principes de la démarche DevOps à sa mise en oeuvre

  1. 1. Des principes de la démarche DevOps à sa mise en oeuvre Developer Day - le 24/03/2016 Stéphane Manciot

  2. 2. ○ Principes de la démarche DevOps ○ Mise en oeuvre ○ Recap Présentation
  3. 3. ○ Bénéfices attendus ○ Intégration à la démarche agile ○ Intégration continue ○ Livraison continue ○ Déploiement continu Principes de la démarche DevOps
  4. 4. DevOps - Pourquoi ? ○ Des cycles de déploiement plus courts ○ Une mise à disposition de nouvelles fonctionnalités plus rapidement ○ Des applications ciblées et de qualité pour accroître la satisfaction cliente ○ Une réduction des coûts et une affectation des ressources à des tâches à plus haute valeur ajoutée ○ Amélioration de la gouvernance liée à l’automatisation du tracking et du reporting
  5. 5. DevOps - Démarche agile
  6. 6. DevOps - Intégration continue
  7. 7. DevOps - Livraison continue
  8. 8. DevOps - Déploiement continu (Nexus)(
  9. 9. ○ Spécifications ○ Gestion de code ○ Tests fonctionnels ○ Métriques et gouvernance ○ Construction des livrables ○ Déploiement ○ Tests de performance Mise en oeuvre de la démarche DevOps
  10. 10. Mise en oeuvre de la démarche DevOps ○ Spécifications ○ Gestion de code ○ Tests fonctionnels ○ Métriques et gouvernance ○ Construction des livrables ○ Déploiement ○ Tests de performance
  11. 11. DevOps - Behaviour Driven Development ○ Spécifications des User Stories décrites selon : ○ Des exigences ○ En tant que <rôle> ○ Je veux que <fonctionnalité> ○ Afin de <bénéfice> ○ Des scénarios / exemples ○ Given (Etant donné) <un contexte> ○ When (Lorsque) l'utilisateur effectue certaines <actions> ○ Then (Alors) on doit pouvoir constater telles <conséquences>
  12. 12. DevOps - Behaviour Driven Development - Exigence ○ En tant que client de l’application ○ Je veux pouvoir autoriser une autre application à accéder à mes informations personnelles ○ Pour pouvoir bénéficier des services proposées par cette dernière
  13. 13. DevOps - Behaviour Driven Development - OAuth Authorization Code Grant
 
 +----------+
 | Resource |
 | Owner |
 | |
 +----------+
 ^
 |
 (B)
 +----|-----+ Client Identifier +---------------+
 | -+----(A)-- & Redirection URI ---->| |
 | User- | | Authorization |
 | Agent -+----(B)-- User authenticates --->| Server |
 | | | |
 | -+----(C)-- Authorization Code ---<| |
 +-|----|---+ +---------------+
 | | ^ v
 (A) (C) | |
 | | | |
 ^ v | |
 +---------+ | |
 | |>---(D)-- Authorization Code ---------' |
 | Client | & Redirection URI |
 | | |
 | |<---(E)----- Access Token -------------------'
 +---------+ (w/ Optional Refresh Token)

  14. 14. DevOps - Behaviour Driven Development - Spock def "given a valid client and an authenticated user, when asking for an authorisation, a valid token should be generated and granted to the client for the authenticated user and the user agent should be redirected back to the client using the redirection URI provided by the client and including an authorisation code” (){
 given:
 createUser()
 request.method = 'POST'
 request.setParameter(OAuth.OAUTH_RESPONSE_TYPE, 'code')
 request.setParameter(OAuth.OAUTH_CLIENT_ID, CLIENT_ID)
 request.setParameter(OAuth.OAUTH_REDIRECT_URI, URLEncoder.encode('http://localhost/eboutique', 'UTF-8'))
 request.setParameter(OAuth.OAUTH_USERNAME, USERNAME)
 request.setParameter(OAuth.OAUTH_PASSWORD, PASSWORD)
 when:
 controller.authorize()
 then:
 HttpServletResponse.SC_FOUND == response.status
 String redirectUrl = response.redirectedUrl
 assertNotNull(redirectUrl)
 Map<String, String> parameters = parametersAsMap(redirectUrl)
 assertNotNull(parameters)
 String code = parameters['code']
 assertNotNull(code)
 Token token = Token.findByClientIdAndValue(CLIENT_ID, code)
 assertNotNull(token)
 assertTrue(!token.hasExpired())
 assertEquals(EXPIRES, token.expiresIn)
 User u = User.findByLogin(USERNAME)
 assertEquals(u, token.user)
 assertTrue(StringUtils.isEmpty(token.scope))
 assertTrue(StringUtils.isEmpty(token.state))
 }
  15. 15. DevOps - Behaviour Driven Development - jbehave # EmptyFavoritesRepository.story Scenario: Empty Favorites Repository Given empty Favorites Repository When there is nothing added to the repository Then favorite book is null public class EmptyRepositorySteps {
 private FavoritesRepository repository = new DefaultFavoritesRepository();;
 @Given("empty Favorites Repository")
 public void givenEmptyFavoritesRepository() {
 }
 @When("there is nothing added to the repository")
 public void whenThereIsNothingAddedToTheRepository() {
 }
 @Then("favorite book is null")
 public void thenFavoriteBookIsNull() {
 assertThat(repository.getFavorite(Book.class)).isNull();
 }
 }
  16. 16. DevOps - Behaviour Driven Development - fitnesse ○ Définition sous la forme de tableaux (decision table) des données en input et des résultats attendus
  17. 17. DevOps - Behaviour Driven Development - fitnesse ○ Développement de fixtures pour appeler directement le code public class Division {
 private double numerator, denominator;
 
 public void setNumerator(double numerator) {
 this.numerator = numerator;
 }
 
 public void setDenominator(double denominator) {
 this.denominator = denominator;
 }
 
 public double quotient() {
 return numerator/denominator;
 }
 }

  18. 18. Mise en oeuvre de la démarche DevOps ○ Spécifications ○ Gestion de code ○ Tests fonctionnels ○ Métriques et gouvernance ○ Construction des livrables ○ Déploiement ○ Tests de performance
  19. 19. DevOps - Gestion de code - Git flow ○ develop : branche principale des développements ○ features : nouvelles fonctionnalités ○ release : versions déployées sur un serveur de staging ○ master : code déployé en production ○ hotfix : correction de bugs constatés en production
  20. 20. ○ Spécifications ○ Gestion de code ○ Tests fonctionnels ○ Métriques et gouvernance ○ Construction des livrables ○ Déploiement ○ Tests de performance Mise en oeuvre de la démarche DevOps
  21. 21. DevOps - Contraintes d’intégration ○ Base de données ○ Intégration avec d’autres SI ○ …
  22. 22. DevOps - Mock de base de données - liquibase ○ Définition des base de données supportées, des tables à créer et du jeu de données à injecter <?xml version="1.0" encoding="UTF-8"?>
 <databaseChangeLog …>
 <preConditions>
 <dbms type="h2,oracle" />
 </preConditions>
 <include file="db.changelog-tables.xml"/>
 <include file="db.changelog-data.xml"/>
 </databaseChangeLog> <?xml version="1.0" encoding="UTF-8"?>
 <databaseChangeLog …>
 <property name="now" value="sysdate" dbms=“oracle”/> …
 <changeSet id="1" author="smanciot">
 <preConditions onFail="MARK_RAN">
 <not><tableExists tableName="EXPORT_RECAPITULATIF_VENTE" /></not>
 </preConditions>
 <createTable tableName=“EXPORT_RECAPITULATIF_VENTE" …>
 </changeSet>
 </databaseChangeLog>
 <?xml version="1.0" encoding="UTF-8"?>
 <databaseChangeLog …>
 
 <changeSet author="smanciot" id="1">
 <insert dbms="h2"
 tableName=“EXPORT_RECAPITULATIF_VENTE" …>
 </changeSet>
 </databaseChangeLog>
  23. 23. DevOps - Mock de base de données - liquibase ○ Ajout de liquibase dans la chaîne de build (maven) <plugin>
 <groupId>org.liquibase</groupId>
 <artifactId>liquibase-maven-plugin</artifactId>
 <configuration>
 <changeLogFile>db.changelog-master.xml</changeLogFile>
 <url>${jdbc.url}</url>
 <driver>${jdbc.driver}</driver>
 <username>${jdbc.username}</username>
 <password>${jdbc.password}</password>
 </configuration>
 <executions>
 <execution>
 <phase>process-test-classes</phase>
 <goals>
 <goal>update</goal>
 </goals>
 </execution>
 </executions>
 </plugin>
  24. 24. DevOps - Mock de base de données - liquibase ○ Tests sans création d’objets mockés "all sales imported" should "be updated" in {
 val rows: Int = retrieveNumberOfRows(MUT, s"SELECT count(*) FROM $EXPORT_RECAPITULATIF_VENTE WHERE EXPORTED=0").getOrElse(0)
 assert(rows > 0)
 
 import akka.stream.scaladsl.Source
 
 val i = new ImportStreaming(system)
 import i._
 val sourceUnderTest: Source[Int] = loadRows(Seq(EXPORT_RECAPITULATIF_VENTE)) via importRows
 val future = sourceUnderTest.runFold(0)(_ + _)
 val result: Int = Await.result(future, 5*60*1000.millis)
 assert(result > 0)
 logger.info(s"imported successfully $result rows")
 assert(retrieveNumberOfRows(MUT, s"SELECT count(*) FROM $EXPORT_RECAPITULATIF_VENTE WHERE EXPORTED=0").getOrElse(1) == 0)
 }

  25. 25. DevOps - Mock de services soap - soapui ○ Définition du service soap à mocker à partir du contrat d’interface (wsdl) ○ Définition des réponses en fonction des inputs
  26. 26. DevOps - Mock de services soap - soapui ○ Ajout de soapui dans la chaine de build (maven) <plugin>
 <groupId>eviware</groupId>
 <artifactId>maven-soapui-plugin</artifactId>
 <version>4.5.1</version>
 <executions>
 <execution>
 <id>proxySCVD</id>
 <phase>process-test-classes</phase>
 <goals>
 <goal>mock</goal>
 </goals>
 <configuration>
 <projectFile>${project.basedir}/src/test/resources/SCVD-soapui- project.xml</projectFile>
 <port>${soapui.port}</port>
 <noBlock>true</noBlock>
 </configuration>
 </execution>
 </executions>
 <dependencies …>
 </plugin>
  27. 27. DevOps - Mock de services rest - Servlet @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
 throws ServletException, IOException {
 OutputStream output = null
 String url = req.getRequestURL().toString()
 String identifiant = parseURL(url, '/pres/v1/pdc/')
 if(!identifiant){
 resp.sendError(400)
 }
 else{
 try{
 output = resp.outputStream
 def inputStream = TraceoMashup.class.getResourceAsStream(identifiant + '.xml')
 if(inputStream){
 resp.setHeader('Content-type', 'application/xml')
 byte[] buffer = new byte[1024]
 for (int length = 0; (length = inputStream.read(buffer)) > 0;) {
 output.write(buffer, 0, length);
 }
 output.flush()
 }
 else {
 resp.sendError(404)
 }
 }
 finally{
 if (output != null) output.close()
 }
 }
 }

  28. 28. DevOps - Mock de services rest - Servlet ○ Définition du descripteur de déploiement (war) <?xml version="1.0" encoding="ISO-8859-1"?>
 <web-app …>
 <servlet>
 <servlet-name>TraceoServlet</servlet-name>
 <servlet- class>fr.laposte.intra.courrier.ccmu.mashup.traceo.servlet.TraceoServlet</ servlet-class>
 </servlet>
 … <servlet-mapping>
 <servlet-name>TraceoServlet</servlet-name>
 <url-pattern>/traceo/pres/*</url-pattern>
 </servlet-mapping> …
 </web-app>

  29. 29. DevOps - Mock de services rest - Servlet ○ Ajout de jetty dans la chaine de build (maven) <plugin>
 <groupId>org.mortbay.jetty</groupId>
 <artifactId>jetty-maven-plugin</artifactId>
 <configuration>
 <webAppSourceDirectory>${project.basedir}/src/test/resources</ webAppSourceDirectory>
 <useTestScope>true</useTestScope>
 <webApp>
 <contextPath>${contextPath}</contextPath>
 <descriptor>${project.basedir}/src/test/resources/WEB-INF/web.xml</ descriptor>
 </webApp>
 <stopKey>stop</stopKey>
 <stopPort>${jetty.stopPort}</stopPort>
 <systemProperties>
 <systemProperty>
 <name>jetty.port</name>
 <value>${jetty.port}</value>
 </systemProperty>
 </systemProperties>
 </configuration>
 <dependencies …>
 </plugin>
  30. 30. Mise en oeuvre de la démarche DevOps ○ Spécifications ○ Gestion de code ○ Tests fonctionnels ○ Métriques et gouvernance ○ Construction des livrables ○ Déploiement ○ Tests de performance
  31. 31. DevOps - Aide à la gouvernance - sonarqube
  32. 32. Mise en oeuvre de la démarche DevOps ○ Spécifications ○ Gestion de code ○ Tests fonctionnels ○ Métriques et gouvernance ○ Construction des livrables ○ Déploiement ○ Tests de performance
  33. 33. DevOps - Hétérogénéité des plates forme
  34. 34. Docker - le conteneur intermodal
  35. 35. Docker - Valeurs ajoutées ○ Construction rapide, idempotent et automatique d’images (Dockerfile) pouvant être partagées (docker-registry) ○ Séparation des rôles : ○ Développeur : à la main sur le conteneur ○ Opérationnel : à la main sur le reste ○ gestion des logs ○ gestion des accès distants ○ configuration réseau ○ monitoring ○ … ○ Portabilité ○ Provisioning rapide (Another Union File System) ○ Performance : les avantages d’une VM (isolation des processus, interface réseau, …) sans les inconvénients (processus exécutés au sein de l’hôte, pas d’émulation de périphérique) ○ pouvoir notamment monter des jeux de test ou de nouvelles instances en fonction des besoins
  36. 36. Docker - Dockerfile (Exemple) image de base variables d’environnement copie de fichiers exécution de commandes points de montage port(s) d’écoute commande par défaut
  37. 37. Mise en oeuvre de la démarche DevOps ○ Spécifications ○ Gestion de code ○ Tests fonctionnels ○ Métriques et gouvernance ○ Construction des livrables ○ Déploiement ○ Tests de performance
  38. 38. DevOps - Déploiement Zero Downtime (1/2) ○ Pattern Blue/Green
  39. 39. DevOps - Déploiement Zero Downtime (2/2) ○ Pattern Canary
  40. 40. Ansible ○ Orchestration et automatisation des tâches d’administration système ○ provisioning ○ déploiement d’application
  41. 41. Ansible - Valeurs ajoutées ○ Simplicité d’exécution : pas besoin de maître ni d’agent sur les systèmes à administrer (ssh) ○ Mode Push ○ Simplicité d’apprentissage (YAML) ○ Performant : exécution des scripts en parallèle sur les machines cible ○ Extensible : python ○ DRY : rôles ○ Idempotent : chaque tâche est exécutée en garantissant que le système cible sur lequel elle s’applique se trouvera dans l’état désiré post exécution ○ Sécurisé : ansible-vault permet d’encrypter les fichiers de configuration spécifiques à chaque plate forme.
  42. 42. Ansible - Datalab
  43. 43. Ansible - Regroupement logique des machines ○ inventory.ini #
 # logical nodes
 #
 datalab-mesos-master1
 datalab-mesos-master2
 datalab-mesos-master3
 datalab-mesos-batch1
 datalab-mesos-batch2
 datalab-mesos-batch3
 datalab-mesos-middleware1
 datalab-mesos-middleware2
 datalab-mesos-realtime1
 datalab-mesos-realtime2 [master]
 datalab-mesos-master1
 datalab-mesos-master2
 datalab-mesos-master3
 [batch]
 datalab-mesos-batch1
 datalab-mesos-batch2
 datalab-mesos-batch3
 [middleware]
 datalab-mesos-middleware1 datalab-mesos-middleware2
 
 [realtime]
 datalab-mesos-realtime1
 datalab-mesos-realtime2
 [slave:children]
 batch
 middleware
 realtime
 master
 
 [mesos:children]
 master
 slave

  44. 44. Ansible - Découpage logique des playbooks ○ ansible-playbbook site.yml -i inventory.ini -vv ---
 
 - include: proxy.yml # proxy
 - include: zookeeper.yml # cluster zookeeper
 - include: hadoop.yml # cluster hadoop
 - include: mesos.yml # cluster mesos
 - include: mesos-dns.yml # mesos-dns
 - include: middleware.yml # middleware
 - include: batch.yml # batch node(s)
 - include: realtime.yml # realtime node(s)
 - include: chronos.yml # chronos
 - include: datalab.yml # marathon
 - include: registry.yml # docker registry
 - include: docker.yml # docker

  45. 45. Ansible - Définition des rôles variables par défaut tâches templates tâches partagées rôle
  46. 46. Ansible - Application des rôles ○ middleware.yml ---
 
 - name: Install mesos middleware node(s)
 hosts: middleware
 remote_user: $user
 roles:
 - {role: kafka}
 - {role: flume}
 - {role: spark} ○ hadoop.yml - name: Install and launch Hadoop cluster
 hosts: hdfs
 remote_user: $user
 pre_tasks:
 …
 - name: add group {{hdfs_group | default(hdfs_user | default('hdfs'))}}
 group: name={{hdfs_group | default(hdfs_user | default('hdfs'))}} state=present
 run_once: true
 delegate_to: "{{play_hosts[0]}}"
 sudo: yes
 when: not local_certificate.stat.exists
 …
 roles:
 - {role: hdfs, hdfs_configure: no}
 - {role: hdfs, hdfs_configure: yes}
 groupe de machines rôles tâches
  47. 47. Ansible - Spécificités des plates forme ○ définition physique des machines ○ datalab-mesos-master1 ---
 
 ansible_ssh_host: 192.168.33.60
 ansible_ssh_user: vagrant
 ansible_ssh_pass: vagrant
 
 zookeeper_id: 1
 
 mesos_standalone: yes
 
 hdfs_name_node_id: nn1

  48. 48. ○ Lancement d’un container - name: ensure kafka is running
 docker:
 image: "{{docker_registry_host}}/ubuntu14.04-jdk{{java_major_version}}- kafka:{{kafka_version}}"
 name: "kafka_{{(item|int) - 1}}"
 command: /start.sh
 ports:
 - "{{kafka_config_port}}"
 links:
 - zk:zk1
 volumes:
 - "{{kafka_log_dirs}}:{{kafka_log_dirs}}:rw"
 - "/var/run/docker.sock:/var/run/docker.sock"
 env:
 KAFKA_ADVERTISED_HOST_NAME: "{{ hostvars[inventory_hostname] ['ansible_eth1']['ipv4']['address'] }}"
 KAFKA_BROKER_ID: "{{(item|int) - 1}}"
 KAFKA_ZOOKEEPERS: "zk1:{{zookeeper_config_clientPort}}"
 state: reloaded
 restart_policy: "no"
 privileged: yes
 with_items: "{{range(1,(kafka_cluster_size+1))|list}}"
 sudo: yes
 register: start_kafka
 
 Ansible - Docker nom de l’image Variables d’environnement valorisation des points de montage
  49. 49. # vi: set ft=ruby :
 
 # All Vagrant configuration is done below. The "2" in Vagrant.configure
 # configures the configuration version (we support older styles for
 # backwards compatibility). Please don't change it unless you know what
 # you're doing.
 Vagrant.configure(2) do |config|
 
 config.vm.box_check_update = false
 … config.vm.define "mesos-batch3" do |datalab|
 datalab.vm.box = "centos/7"
 datalab.vm.hostname = "datalab-mesos-batch3.vm"
 datalab.vm.network "private_network", ip:"192.168.33.83"
 datalab.vm.synced_folder "./", "/vagrant", disabled:true
 datalab.vm.synced_folder "./", "/home/vagrant/sync", disabled:true
 datalab.vm.provider "virtualbox" do |vb|
 vb.name = "datalab-mesos-batch3"
 vb.cpus = 1
 vb.memory = 1024
 end
 datalab.vm.provision :ansible do |ansible|
 ansible.inventory_path = "vagrant-inventory.ini"
 ansible.playbook = "datalab.yml"
 ansible.extra_vars = { user:"vagrant"}
 ansible.sudo = true
 ansible.limit = 'all'
 ansible.verbose = 'vv'
 end
 end
 
 end
 Ansible - Vagrant box vm network provisioning vagrant inventory playbook
  50. 50. ○ Spécifications ○ Gestion de code ○ Tests fonctionnels ○ Métriques et gouvernance ○ Construction des livrables ○ Déploiement ○ Tests de performance Mise en oeuvre de la démarche DevOps
  51. 51. DevOps - Tests de performance - Gatling ○ Génération des tests à partir d’une archive HTTP, en utilisant un proxy, un fichier de logs serveur, … ○ Description du comportement des utilisateurs (pause, rendezVous, exec, …) ○ Injection de données dans les scénarios (csv, json, jdbc, redis, …) ○ Contrôle de l’injection des utilisateurs (atOnceUsers, rampUsers, …) ○ Assertions (responseTime, requestsPerSec, …) ○ Vérification des réponses (check)
  52. 52. DevOps - Tests de performance - Gatling ○ Génération de métriques
  53. 53. Dev Ops Continuous delivery platform VCS 1 4 3 uat Build 5 6 docker registry 7 2 8 Schéma de mise en oeuvre
  54. 54. Rappel des principaux composants ○ Docker-registry : disposer d’une référentiel privé des images construites par la plate forme de livraison continue permettant leur déploiement sur n’importe quel serveur - “build once deploy anywhere” ○ SonarQube : disposer de métriques permettant de mesurer en continu la qualité du code produit ○ artifactory / nexus : pouvoir disposer d’un référentiel de composants permettant de contrôler, stocker et gérer les binaires produits tout au long du cycle de vie du projet ○ Fitnesse : pouvoir mettre en oeuvre des tests d’acceptance automatisés et ainsi s’assurer de la conformité du code produit au regard des fonctionnalités attendues ○ Gatling : pouvoir effectuer des tests de performance ○ Ansible : pouvoir construire les images docker, sécuriser les déploiements effectués sur chacune des plates forme (avec ou sans docker) et ainsi pouvoir livrer en continu
  55. 55. Questions ?
  56. 56. Plus d’informations sur blog.ebiznext.com et github.com/ebiznext

×