Notre env. de dév. n’est plus un
bizutage !

Appuyez sur [s] pour ouvrir les notes présentateur dans une nouvelle fenêtre.

Utilisez la touche [ESPACE]
pour passer au slide suivant.

Three years ago,
in this galaxy...

Bienvenue !
Tu vas prendre en gros la semaine pour installer ton poste.

Moué…

Comme ils ont dû te dire, tu vas en avoir pour à peu près deux semaines à installer ton poste.

WAT?

Humph…

Un peu de contexte

TEA, The Ebook Alternative

Une équipe technique

Ce qui est fixé

(pour le moment)

  • Git, Github
  • Linux, Mac — PC portables
  • Amélioration continue
  • Production infogérée

Notre production

  • Linux, Varnish, Nginx, PHP, Ruby + JS, Go
  • MySQL, MongoDB, SolR + Redis, Elasticsearch, RabbitMq
  • Silex, Symfony 1.4, Rails 3+4, Magento, …
  • Plein d'outils propriétaires ou non

Nos environnements

  • 20+ projets
  • 10+ technos
  • Applications très liées

Dev à l’image de la prod ?

  • Architecture, services, versions
  • Isolation des fonctionnalités
  • Droits d’accès (fichiers, ressources)
  • Répartition machines

Automatisation

2012 - 2013

VirtualBox

Installation manuelle

Documentations

Peu (pas ?) à jour sur un wiki deux wikis

se contredisant !

Reverse de la prod

Collègue a pris son PC (fixe) et est venue en pair avec moi

… pendant une semaine.

Automatisation

2014

Quelques outils

  • VirtualBox
  • + Vagrant
  • + Provisionning : Chef

Vagrant

vagrantup.com

Vagrantfile

Vagrant.configure("2") do |config|
  config.vm.define "tea-demo" do |test|
    test.vm.box = "tea-wheezy-amd64"
    test.vm.hostname = "tea-demo"

    test.vm.network :private_network, ip: "192.168.3.10"
    db.vm.provider "virtualbox" do |v|
      v.customize ["modifyvm", :id, "--memory", 1024]
    end

    test.omnibus.chef_version = :latest
    test.vm.provision "chef_solo" do |chef|
      chef.cookbooks_path = "#{my_ws}/cookbooks"
      chef.add_recipe "tea-demo"
      chef.add_recipe "tea-plateforme"
    end
  end
end
                        

Chef

chef.io/chef

Cookbook chef

include_recipe "percona::server"

template "/etc/mysql/conf.d/tea.cnf" do
  source "tea.cnf.erb"
  owner "root"
  group "root"
  mode "0644"
end

service 'mysql' do
  action [:enable, :restart]
end

root_password = node["percona"]["server"]["root_password"];
sql_commands = "GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION; SET PASSWORD FOR 'root'@'%' = PASSWORD('#{root_password}');"
execute "mysql-allow-access-from-remote" do
  command %(/usr/bin/mysql -p'#{root_password}' -e "#{sql_commands}")
end
                        

Pour les données ?

Des scripts !

  • (bash) Import depuis la prod
  • (SQL) Nettoyage des données sensibles

Et donc ?

  • Cloner le repo git
  • Créer la VM
  • composer install
  • Les tests passent…
  • … peut-être ?

Et donc ?

  • Cloner le repo git
  • Créer la VM
  • composer install
  • Les tests passent…
  • ou pas !

Configuration

Complexe & chronophage

  • Avant : fichiers .dist
  • Maintenant : stow

Stow

Arborescence extraite de git

$ tree
.
|-- app
|   `-- config
|-- config
`-- config-dist
    `-- local
        |-- app
        |   `-- config
        |       `-- specifique-appli.txt
        `-- config
            `-- test.yml

Stow

$ stow --dir=config-dist --target=. local

Stow

Arborescence avec les symlinks

$ tree
.
|-- app
|   `-- config
|       `-- specifique-appli.txt
            -> ../../config-dist/local/app/config/specifique-appli.txt
|-- config
|   `-- test.yml -> ../config-dist/local/config/test.yml
`-- config-dist
    `-- local
        |-- app
        |   `-- config
        |       `-- specifique-appli.txt
        `-- config
            `-- test.yml

DNS ?

Communication entre services

  • Modifier les fichiers /etc/hosts
  • Avec des IPs en dur
  • Sur toutes les machines !

dnsmasq

Serveur DNS

  • Installé sur poste physique
  • Utilisé par toutes les machines
  • Centralise la configuration DNS

Objectif atteint !

Objectif atteint !


$ git clone mon-projet.git
$ vagrant up ma-vm
$ composer install
$ stow --dir=config-dist local

$ bin/atoum && bin/behat
                            

\o/

Docker

Découverte d'un nouvel outil

2014 - 2015

Principes

docker.com

  • Fichier de description : Dockerfile
  • Construction d'une image : docker build
  • Exécution d'un conteneur : docker run

Dockerfile + Chef

  • Vagrant / Docker
  • Ré-utilisation des recettes
  • Une équipe, une construction

Dockerfile + Chef

FROM docker-registry.staging.tea-ebook.com/base-wheezy:latest
MAINTAINER TEA, technique@tea-ebook.com

ADD ./chef/ /chef
RUN cd /chef && LANG="C.UTF-8" ↩
        /opt/chef/embedded/bin/berks install \
    && LANG="C.UTF-8" /opt/chef/embedded/bin/berks ↩
        vendor /chef/all-cookbooks \
    && (chef-solo -c /chef/solo.rb ↩
        -j /chef/solo.json || true)
                        

Orchestration ?

run.sh

{% verbatim %}CONTAINER_NAME='tea-backend'
IMAGE_NAME="$CONTAINER_NAME:70"
PHYSICAL_IP=$(/sbin/ifconfig "$BRIDGENAME" |filter_ip)

docker run \
    -v "$WORKSPACE/backend/":/var/www/BackendTEA/current:rw \
    -w /var/www/BackendTEA/current \
    -d \
    --dns "$PHYSICAL_IP" \
    --name "$CONTAINER_NAME" \
    "${IMAGE}"

CONTAINER_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' $CONTAINER_NAME)
echo "address=/backend.lxc/${CONTAINER_IP}" > "/etc/dnsmasq.d/$CONTAINER_NAME"
sudo /etc/init.d/dnsmasq restart{% endverbatim %}
                        

Registre interne

docs.docker.com/registry

  • Une personne construit une image
  • L'image est partagée pour tous
  • Gain de temps !
  • + facile pour rester à jour

Maintenance...

  • Manque de compétences Chef
  • Besoin rare
  • Recettes pas utilisées en prod

Dockerfile

Dockerfiles everywhere !

2016

Dockerfile

FROM docker-registry.staging.tea-ebook.com/base-jessie:latest
MAINTAINER TEA, technique@tea-ebook.com

# Activation dotdeb
RUN echo "deb http://packages.dotdeb.org jessie all" >> /etc/apt/sources.list \
    && wget https://www.dotdeb.org/dotdeb.gpg -O /tmp/dotdeb.gpg \
    && apt-key add /tmp/dotdeb.gpg \
    && rm /tmp/dotdeb.gpg \
    && apt-get update

# Installation PHP 7 + extensions
RUN apt-get update \
    && apt-get install -y --no-install-recommends php7.0-fpm php7.0-cli \
        php7.0-dev php-curl php-intl php-json php-mysql php-sqlite3 php-opcache \
    && apt-get clean
                        

Registre interne

  • Registre conservé
  • Seul changement = maintenance plus simple

En plus !

  • Validation de nouveautés
    • PHP 5.5 → 5.6 → 7.0
    • HTTP/2 sous nginx

En plus !

  • Intégration continue
    • Utilisation des mêmes images docker
    • Build de master
    • Puis des pull-requests

Expérimenter !

  • Vagrant, chef
  • Apache → Nginx
  • Docker, registry, compose
  • Versions de PHP et Ruby, MySQL, Elasticsearch…

WIP constant

  • Corrections, améliorations, création
  • Compromis : « façon de faire » vs « ce qui marche pour nous »

Notre env. de dév. n’est (presque)
plus un bizutage :-)

Futur

Encore du boulot !

Première mise en prod

3ème jour

2 semaines

3 jours pour installer mon poste ; je ne me suis pas senti productif.

Actions (semi) manuelles

  • OS et logiciels
  • git clone + stow + composer install + bundle install
  • Obtenir les images docker
  • Importer des données

Actions (semi) manuelles

  • Bien pour un développeur ?
  • Débutant ?
  • D'autres personnes ?
  • Ou quand on remplace des machines ?

Pas à pas

  • Passez un projet sous docker
  • Communiquez, formez vos collègues
  • Partagez : registre interne
  • Documentez !
  • Et passez au projet suivant ;-)

Pas toujours parfait

L’important, c’est d’avancer

Pascal MARTIN

blog.pascal-martin.fr
contact@pascal-martin.fr
@pascal_martin

TEA, The Ebook Alternative

php7avance.fr — @php7avance