dimanche 13 décembre 2015

Le voyage du Kimsufi en Docker (Etape 5) subsonic

Voila on attaque la dockerisation de Subsonic, on trouve déjà des images et des Dockerfile, donc ce n'est pas trop compliquer de s'en inspirer voir on pourrait les reprendre directement. Mais pour divers raisons je recompile Subsonic à partir des sources et puis je voulais compiler ffmpeg dans le container histoire de voir si le tout est plus performant. Mon mini Kimsufi souffre un peu avec l'encodage à la volée côté puissance c'est un peu léger.

Bien entendu c'est la dernière version de Subsonic, j'avais espéré la brancher à la base de donnée MariaDB (mysql) mais ce n'est pas encore pour cette fois... peut-être faire un fork du projet pour le migrer de JDBC à JPA et mettre à jour le lecteur en HTML5... mais ça c'est vraiment si je trouve du temps... à voir si y a pas déjà un énervé qui a lancé un projet sur GitHub.
Vu que Subsonic est un conteneur autonome, il y a juste un partage de volume pour récupérer la musique et patienter un peu pour que la base de données se remplisse.

Je n'ai vu de différence notable, mais l'avantage de passer par un container rend la migration plus sécurisée, en effet sur le serveur l'ancienne version de Subsonic est utilisable et n'a pas été écrasée. Si je n'avais pas utilisé Docker j'aurais du écraser ma précédente installation.
Voila un lien vers l'images dans docker hub : https://hub.docker.com/r/niclange/subsonic/

Sinon le fait d'utiliser une version compilée à partir des sources pour ffmpeg ça donne cela :
Version compilée :
real 10m53.476s
user 38m21.924s
sys 0m30.456s

Version installée avec subsonic :
real 14m23.775s
user 45m1.728s
sys 0m31.908s


mardi 17 novembre 2015

Counting IT version Alpha

Voila c'est fait... un peu de développement pour un peu de résultat. Un petit site qui n'a pas encore une grande utilité mais qui sait... avec quelques fonctionnalités de plus y a moyen ou pas que cela intéresse un peu de monde. Enfin l'objectif c'est de tester des nouvelles technologies :

Pour le frontal :
  • React Material
  • Design Lite
  • Google Web Starter Kit
J'ai parlé de tout cela dans un précédent billet.

Pour la partie serveur :
  • Google Application Engine (GAE) avec le développement d'un Endpoint.
  • OAuth de google, oui il faudra un compte google pour accéder à l'application
  • Le Datastore de Google avec Objectify
Et tout l'écosystème qui en dérive, stockage des données, authentification OAuth2, API management... et la console de google developer.

La bonne nouvelle c'est que cela marche assez facilement après quelques mises au point avec les outils et l'environnement de développement qui mock l'utilisateur, il faut donc prévoir un horrible code pour gérer cela :
     if (user.getEmail().equalsIgnoreCase( "example@example.com" ))
Oui en mode développement on a pas accès au vrai profile de l'utilisateur.

Sinon je n'ai presque rien à dire... le client javascript du GAE Endpoint est généré à la volé par les API google donc pas de soucis particulier pour générer des requêtes, tout est masqué en fait : 
     gapi.client.countingit.countersAPI.count({'counterId':12345,'countTime':date }).execute(
      function(resp) {
          if (!resp.code) {
              this.setState({data:resp.result});
          }
          else{
              console.error(resp, status, err.toString());
          }
        });
Et c'est assez simple à intégrer avec le fonctionnement de React. Le petit détail est de s'assurer que les API google client sont bien chargées et cela prend du temps avant de tenter des requêtes au serveur.
Bref beaucoup plus de souci entre MDL et React côté interface que côté serveur et appels de services REST.


mardi 27 octobre 2015

Développer un Frontal Web : Google Web Starter Kit & Material Design Lite & React

Parlons un peu de développement Web histoire de se changer les idées car dernièrement dans mes derniers projets professionnels je n'ai pas trop tâté du Web. Je suis côté cœur de SI : services métier, médiation, stockage des données... Mais de temps en temps il faut bien se replonger dans le développement Web car c'est un monde qui bouge beaucoup... et un peu trop vite, c'est quasiment impossible d'être à jour, le temps de réaliser un projet et déjà de nouvelles normes, de nouveaux frameworks... Personnellement j'ai raté pas mal d'étapes et c'est temps mieux, je me suis arrêté à Ext-JS (maintenant Sancha, quand c'était gratuit...) et à JQuery, JQueryUI. Bon tout ça existe toujours mais ils ont moins le vent en poupe. Et du coup j'ai sauté la période Bootstrap / AngularJS (qui va surement se relancer avec la version 2) et qui restent à la pointe et s'améliorent.

Donc je m'attaque au développement Web avec Material Design Lite (porté par les standard de Google) mixé avec React (le framework de Facebook), oui les deux mastodontes d'internet, pourquoi s'en priver c'est gratuit. Et je ne me lance pas dans un développement complexe qui pourrait nécessiter un Backbone.js mais à terme pourquoi pas c'est l’intérêt de React : ça ne ferme pas les portes. Et puis pour cadre tout ça le Google Web Starter Kit.

Material Design Lite

Commençons pas présenter MDL qui implémente le Material Design de Google, c'est très léger : du CSS et un javascript. Cela donne un cadre pour réaliser une interface web, c'est très pratique pour les ingénieurs comme moi qui sont très loin d'être des web designer, ici, on a qu'a choisir la couleur (oui c'est assez restrictif mais ça évite de faire un site qui pique les yeux), un template (ou pas) et les composants. Après ce framework n'est pas très complet aujourd'hui et il manque pas mal de composants, j'attend la version suivante !

React JS

React JS c'est un framework de génération de DOM HTML utilisant le syntaxe JSX qui permet d'écrire cela simplement. React promet simplicité et performance.
Bon c'est pas si simple car on perd les bases du déroulement de la page html et de son chargement. Bref il faut utiliser des astuces pour réaliser lancer les petits scripts nécessaires à MDL pour décorer les composants.

Google Web Starter Kit

Peut de développement dans ce kit, juste le packaging d'outils basés sur node.js pour avoir un platforme de développement web qui est vraiment efficace. On peut modifier le gulpfile.js pour prendre en charge le JSX avec Babel et le tour est joué.

Conclusion

Ces outils marchent PRESQUE ensemble out-of-the-box. C'est React (normal c'est l’intrus) qui fou la grouille.

Voila la solution pour MDL avec React :
var Header = React.createClass({
  componentDidUpdate: function() {
      // Décore tous les composant avec 'mdl-js-* class
      componentHandler.upgradeDom();
  },
Sans oublier l’utilisation d'un require(../material.min.js) pour être sur d'avoir la méthode accessible que browserify gérera...

Et pour le Web Starter Kit une petite modification du gulpfile.js pour prendre en compte JSX (mais je pense que dans la prochaine version ce sera inclus) : 
gulp.task('scripts', function () {
  return gulp.src('app/scripts/monApp.jsx')
  .pipe(babel())
  .pipe(browserify())
  .pipe(gulp.dest('app/scripts/'));
});
[...] 
// Build production files, the default task
gulp.task('default', ['clean'], function (cb) {
  runSequence('styles', ['scripts', 'jshint', 'html', 'images', 'fonts', 'copy'], cb);
});

Mise à jour 02/11/2015 :

Bon quelques soucis j'ai l'impression que le componentHandler.upgradeDom(); fait sauter les événements enregistrés par React... du coup j'ai ajouté react-native-listener. Je ne sais pas si c'est LA solution mais ça marche...

Mise à jour 05/11/2015 :

Pour le même problème que précédemment une solution est d'enregistrer l’événement à la suite :
componentHandler.upgradeDom();  
document.getElementById('myButton').addEventListener("click", this.props.handleClick);

Mise à jour 01/01/2016 :

Suite à la mise à jour de material design lite à la version v1.0.6 je n'ai pas plus besoin de react-native-listener pour la plupart des événements. Cela s'améliore de jour en jour.

lundi 12 octobre 2015

Considération sur l'Architecture en Microservices

Voila la nouvelle voie de l'architecture applicative ! Les microservices vont révolutionner votre SI et diminuer drastiquement les coûts, réduire les temps de développements bref que du bonheur. Mouais faut relativiser, c'est comme tout, faut-il encore bien le faire. Par ce que bon depuis le temps, je suis pas certain que nous les "nouvelles technologie" aient permis de retrouver la productivité, la performance et la fiabilité des bon vieux Mainframe !
Enfin bon moi je suis dans la nouvelle tech alors parlons un peu des microservices. Un petit tour sur Wikipedia et divers sources et on retient :
  • L'architecture en microservice est une architecture applicative que l'on peut rapprocher d'une architecture n-tiers.  
  • Elle n'est pas en concurrence avec une approche SOA car orienté application et non système d'information : seuls les microservice de "haut niveau" sont exposés au SI et ceci dans le respect des règles de la SOA.
Une telle architecture permettrait de donner de la flexibilité non plus au niveau d'un SI (où règne la SOA) mais au niveau d'un applicatif. Ainsi si une fonctionnalité est très consommatrice en ressource pourquoi ne pas la coder dans un technologie plus efficiente comme en GO ou en C ou encore clusteriser le service...  Cette flexibilité technologique aussi de construire un composant  de l'application avec par exemple une application NodeJS existante (genre NodeRed).

Côté humain, pour que cela fonctionne il vous faut une équipe de superman multi techno, et puis côté production c'est la panique alors une alternative est de passer le tout sous Docker... donc ça veut dire qu'en fin de développement une bonne part du travail de l'exploitation est réalisé. Alors là va falloir soit briser les barrières entre les développeurs et les exploitants, ce qui n'est pas évident... entre les uns qui subissent les bugs des autres, les autres disent que les uns veulent juste presser UN bouton... c'est pas gagné. OK ce qu'il vous faut c'est une équipe de super DevOps comme on dit, mouais va falloir les trouver les petits gars, piquer quelques ressource chez OVH et Google et c'est parti. C'est fou comme tout de suite ça devient moins réaliste.

Côté infrastructure, au lieu d'avoir un découpage par API au sein d'une application on a un découpage de service, de services exposés sur le réseau. Cela sous entend qu'ajouter un passage sur le réseau n'est pas un problème pour vous, bande passante démesurée et latence faible... bon aujourd'hui ça se trouve facilement. En suite vous aurez un surconsommation de mémoire et de CPU par rapport à une application monolithique :
  • Le passage par le réseau va nécessiter une sérialisation et dé-sérialisation (CPU) ce qui grosso-modo entraîne un pique x4 de la trace mémoire qui sera absorbé par les garbage collector ou autre gestionnaire de mémoire (CPU).
  • Mutualisation des API tiers dans un application monolithique et du serveur d'application (Jboss ou autre). 

Après une réalité économique est que les coûts du CPU, de la mémoire, du le réseau diminuent rapidement avec le temps alors que le coût de la main d'œuvre augmente (j'aimerais qu'il augmente un peu plus). Donc l'architecture en microservices a du sens. Bien utilisé certains pensent même que cela pourrait mettre à défaut la loi de Brooks, ce dont je doute mais c'est le rêve de tout chef de projet, parfois ils rêvent éveillés, mais attention au réveil le bilan est souvent lourd...

 

lundi 14 septembre 2015

Java Spring, J2EE et Java EE état de lieux

Java Spring, J2EE, Java EE sont les mots clés les plus trouvés dans le monde de l'informatique d'entreprise. Depuis les années 2000 les entreprises ont massivement investi dans la technologie JAVA.
Le cœur de cible de J2EE était de remplacer à moindre coût les infrastructures Mainframe dans lesquelles les entreprises se sentaient emprisonnées par les éditeurs sur des technologies vieillissantes et du matériel spécifique hors de prix. L'avènement de l'architecture PC pour les serveurs permit alors d'acquérir une puissance de calcul à un coût très compétitif mais il faut une technologie pour y développer des applications d'entreprise : J2EE.
Mais le passage vers J2EE ne tiendra pas vraiment ses promesses, pour divers raisons :
  • Alors que l'architecture des applications Mainframe est globalement mise en place et validée par la solution de l'éditeur et au final les développeurs sont dans un cadre qui permet de se concentrer sur l'implémentation du métier. Avec J2EE la complexité d'une application transactionnelle, répartie sur plusieurs machine doit être prise en compte par l'équipe de développement.
  • En plus de gérer des concepts compliqués l'implémentation des composant J2EE est tout aussi complexe.
  • J2EE un standard ouvert mais les implémentations sont le plus souvent payantes.
  • De plus c'est la révolution du Web, on veut des applications d'entreprise en client Web qui sont finalement beaucoup plus contraignantes et complexes à développer que les applications client lourd pour souvent un rendu utilisateur de moins bonne qualité.
Sur le tas de cendre, laissé par les développements J2EE, Spring démarre en flèche. Il modifie le paradigme et on parle de conteneur léger (Tomcat), en général elles sont montées en cluster de type silo.

Finalement Spring a pris une place majeur dans l'écosystème Java, à grossi, c'est enrichi et c'est complexifié... en même temps J2EE a évolué et changé de nom pour Java EE et s'est fait peau neuve pour devenir plus simple. Aujourd'hui ces 2 solutions sont sensiblement équivalentes mais Java EE est tiré par des serveurs d'applications d'entreprise (JBOSS, Weblogic, Websphere...) alors que Spring peut-être utilisé avec du pur Java SE et a un écosystème qui lui est propre.

Et maintenant que trouve-t-on sur le terrain ? De mon expérience,  je rencontre des applications développées sur Spring déployées sur des serveurs d'applications Java EE, et c'est quasiment systématique. Les développeurs ont acquis une expérience plutôt positive avec Spring mais au niveau de l'exploitation les serveurs restent Java EE car soit il y a un historique ou la nécessité d'avoir le support d'un éditeur.
En soit pas de souci les 2 technologies peuvent s'intégrer. Donc en général ce n'est pas un problème c'est juste étrange de ne pas exploiter certaines fonctionnalités fournies en standard par le serveur.
Mais ça devient plus problématique quand l'application développée sur Spring embarque des librairies sur lesquels ce base le serveur Java EE ou qui implémente les même fonctionnalité. En effet le serveur Java EE a été testé, certifié par une communauté ou un éditeur pour fonctionner avec ses propres librairies, c'est d'ailleurs une part importante de leur valeur ajoutée. Dans le cas où l'application apporte des librairies en conflit il faut s'attendre à des soucis au démarrage, pour passer outre il faudra démonter le serveur d'application (avec un peu de configuration dans le meilleur des cas, en modifiant dans le système de fichier dans le pire des cas) pour qu'il charge nos librairies à la place des siennes. Par ailleurs les exploitants fournissant le serveur n'auront alors aucune garantie sur la réelle configuration et une montée de version ne se fera pas sans surprise.
En générale avec des serveur d'application propriétaire (Websphere, Weblogic), il y a moins de risque de collision de librairie car il n'est pas évident d'embarquer les leurs par inadvertance vu qu'elles sont payantes et rarement fournies sans le serveur. Par contre pour les serveur open source (JBoss, Glassfish) il est fort probable qu'en embarquant Hibernate, Log4j, Jersey  un conflit se produise et ce n'est qu'un début. Sans parler des possibilités de monitoring de la console d'administration qui risque de ne plus être opérationnelle.
Mixer Spring et un serveur Java EE nécessite une petite étude préalable et il est possible que les développements finissent par être adhérents au serveur Java EE choisi lors de la phase de développement. Alors qu'une application Java EE devrait être (en théorie) portable d'une plateforme à une autre, sans parler de la taille des binaires à déployer, utilisant le serveur Java EE il y aura fort peu de librairies à embarquer et sur le terrain livrer un binaire de plusieurs centaine de Mo et quelques Mo ça change la vie.

mercredi 9 septembre 2015

RecUnitTest : enregistrer pour mocker

Un petit article pour présenter ce petit développement https://github.com/niclange/RecUnitTest toujours à base d'AOP et pour l'instant uniquement pour une application utilisant le framework Spring. Je compte bien faire une version JEE.

L'objectif de cette librairie et d'aider à réaliser des tests unitaires de non régression sans faire de mock avec une libraire de type EasyMock ou Mockito. Elles sont très bien mais c'est toujours coûteux de réaliser des mocks quand parfois on peut l'éviter.
Voici le scénario pour utiliser RecunitTest :
Vous avez un développement qui utilise par exemple des service tiers (web ou autre) voir une base de données (mais normalement avec DBUnit ce cas est couvert). Il peut jouer en local les tests unitaires de type "intégration" qui utilisent donc de vrais services tiers fonctionnels (mais dédiés aux développements) au cours de son exécution, il doit savoir préalablement que les environnements sont fonctionnels et en état pour réaliser les cas de test. Mais sur la PIC, typiquement avec un Jenkins les tests seront lancés n'importe quand et il est compliqué et coûteux de maintenir des environnements uniquement pour ces tests.
Bref l'idée est d'enregistrer le comportement des réponses des environnements tiers, lors d'un tire de test unitaire maîtrise, dans un fichier pour être à même de le rejouer sur la PIC. De plus pour de la non régression ce fichier pourrait être utilisé dans le cas où remonter des environnements nécessaires est coûteux.

Pour réaliser cela j'ai mise en oeuvre :
  • l'AOP Spring pour intercepter les méthodes à enregistrer et à rejouer.
  • J'utilise une base clé / valeur embarquée mapdb pour stocker les données dans un fichier.
  • Un parser JSON mais peut-être que je pourrais m'en passer...
Donc le développement est assez simple, la mise en œuvre complète sur un projet peut-être un peu plus complexe et nécessite de l'organisation. Je pense qu'il faut s'appuyer sur les profils maven (dans le pom) pour piloter la configuration de l'outil c'est à dire son mode : Record ou Play et le fichier de stockage qu'il faudra probablement pousser au travers du gestionnaire de configuration.

Je n'ai pas réalisé de tests avec un application massivement multi-thread mais j'ai essayé de prendre en compte cette problématique dans les développements. 


Bref il me reste encore à l'utiliser dans un cas réel et voir comment cela se passe pour donner plus de détails.

samedi 5 septembre 2015

Docker et ffmpeg optimisation compilation

Sur ma Debian wheezy je peux récupérer un obscure paquet ffmpeg.
>># ffmpeg -version 
ffmpeg version 1.0.10
built on Jul 25 2014 07:50:40 with gcc 4.7 (Debian 4.7.2-5) configuration: --prefix=/usr --extra-cflags='-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security ' --extra-ldflags='-Wl,-z,relro' --cc='ccache cc' --enable-shared --enable-libmp3lame --enable-gpl --enable-nonfree --enable-libvorbis --enable-pthreads --enable-libfaac --enable-libxvid --enable-postproc --enable-x11grab --enable-libgsm --enable-libtheora --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libx264 --enable-libspeex --enable-nonfree --disable-stripping --enable-libvpx --enable-libschroedinger --disable-encoder=libschroedinger --enable-version3 --enable-libopenjpeg --enable-librtmp --enable-avfilter --enable-libfreetype --enable-libvo-aacenc --disable-decoder=amrnb --enable-libvo-amrwbenc --enable-libaacplus --libdir=/usr/lib/x86_64-linux-gnu --disable-vda --enable-libbluray --enable-libcdio --enable-gnutls --enable-frei0r --enable-openssl --enable-libass --enable-libopus --enable-fontconfig --enable-libfdk-aac --enable-libdc1394 --disable-altivec --disable-armv5te --disable-armv6 --disable-vis --shlibdir=/usr/lib/x86_64-linux-gnu
libavutil 51. 73.101 / 51. 73.101
libavcodec 54. 59.100 / 54. 59.100
libavformat 54. 29.104 / 54. 29.104
libavdevice 54. 2.101 / 54. 2.101
libavfilter 3. 17.100 / 3. 17.100
libswscale 2. 1.101 / 2. 1.101
libswresample 0. 15.100 / 0. 15.100
libpostproc 52. 0.100 / 52. 0.100 
Et le tout sur un petit Atom ça fait pas de miracle. Je me suis dit qu'avec un peu de chance en mettant en oeuvre un container Docker, il y a moyen d'avoir à la fois une version compiler et à jour de ffmpeg sans pour autant pourrir mon serveur.
Oh miracle des images existent et de jolie fichier Dockerfile sont disponibles pour monter rapidement une image en partant des sources des divers librairies. Je suis parti de ce DockerFile, deux, trois vérifications et choix des librairies (un peu au hasard je dois bien l'avouer, je ne suis pas un expert en format vidéo et autre encoding), me voila avec une image permettant de lancer ffmpeg dans un container Docker.
Le docker retourne quand à lui (j'ai fait un alias) :
>># ffmpeg2 -version 
ffmpeg version 2.7.2
Copyright (c) 2000-2015 the FFmpeg developers built with gcc 4.9.2 (Debian 4.9.2-10) configuration: --prefix=/usr/local --extra-cflags=-I/usr/local/include --extra-ldflags=-L/usr/local/lib --bindir=/usr/local/bin --extra-libs=-ldl --enable-version3 --enable-libx264 --enable-gpl --enable-postproc --enable-nonfree --enable-avresample --enable-libfdk_aac --disable-debug --enable-small
libavutil 54. 27.100 / 54. 27.100
libavcodec 56. 41.100 / 56. 41.100
libavformat 56. 36.100 / 56. 36.100
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 16.101 / 5. 16.101
libavresample 2. 1. 0 / 2. 1. 0
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.100 / 1. 2.100
libpostproc 53. 3.100 / 53. 3.100 
Sans l'alias le commande ressemble à cela
docker run --rm -t -i -v /Video:/Video bb30ceac9f83 -ss 1418 -i "/Video/test3.avi" -b 1000k -s 640x360 -ar 44100 -ac 2 -v 0 -f flv -vcodec libx264 -preset superfast -threads 4 - > test3.flv 
On remarquera que le container est effacé suite à chaque exécution.
C'est le moment du petit Benchmark ente les 2 ffmpeg et avconv avec le command time :

ffmpeg host ffmpeg compile docker avconv docker avconv host
real 61m29.758s         real 51m16.200s                      real 57m51.491s             real 61m48.041s
user 156m1.020s user 0m31.176s user 0m35.628s user 156m6.080s
sys 1m55.872s sys 1m26.520s sys 1m32.788s sys 1m59.684s

Je n'ai pas comparé la qualité des fichiers ni même la taille, les option étant les mêmes je fais confiance. Conclusion : ça va plus vite ! Soit 16,6% plus rapide avec le docker. La commande time ne peut pas dire grand chose sur l'usage du CPU vu que cela s'exécute dans un container. En tout cas ce n'est pas négligeable tout ça peut être justifié par la montée de version, la compilation, les options...

lundi 24 août 2015

Le voyage du Kimsufi en Docker (Etape 3)

Là je m'attaque à la base de données MySql qui est utilisée essentiellement pour Seafile. Il y a bien au d'autre tests avec mais actuellement elle sert exclusivement à Seafile. Cela va limiter la difficulté à migrer.
Encore une fois je part d'une image officiel, celle de MariaDB. Oui t'en qu'a faire autant prendre du vrai opensource, en général Oracle ne prend pas très soin de ses rachats... alors j'anticipe les soucis futures avec MySQL. Un petit run de l'image officiel de MariaDB tout en modifiant le port histoire d'avoir les 2 bases de données actives :
docker run --name mariadb -e MYSQL_ROOT_PASSWORD=AAAAA --publish=3307:3306 -d mariadb 
Et le tour est joué encore plus simple qu'un apt-get install... après faut faire confiance aux images officiels.
Maintenant il s'agit de réaliser les import / export d'un instance à l'autre de créer les users nécessaires et d'attribuer les droits. Pour cela j'ai utilisé mysql-workbench qui est vraiment complet et sympa, ok c'est un produit Oracle, mais j'ai pas dit qu'ils ne savent pas développer.
Le truc est qu'il faut accorder les droit d'accès non pas en localhost pour la connexion avec seafile mais avec l'IP de l'interface Docker0.

Pour la configuration de la base de données pour Seafile voici les fichiers :
ccnet/ccnet.conf
seafile-data/seafile.conf
seahub_settings.py 
Et un petit restart :
./seafile.sh stop
./seahub.sh stop
./seafile.sh start
./seahub.sh start-fastcgi

Voila maintenant il reste le plus compliqué s'attaquer à des outils comme Seafile et Subsonic, je ne peux plus m'appuyer sur des repos Docker officiel, mais il y a pas mal d'images réalisées sur ces outils. On est pas à l'abri que cela se déroule simplement voir que cela soit trivial !!!

Sinon là c'est clair que le Monit voit de moins en moins de chose... mais cAdvisor de plus en plus !!

Petit détail il faut gérer le firewall (iptables) pour que l'interface docker0 puisse accéder au localhost !!

mardi 18 août 2015

Le voyage du Kimsufi en Docker (Etape 2)

Petit billet pour une petite étape pas de révolution mais de petites améliorations suite à divers lectures. Et la bonne surprise c'est qu'il y a beaucoup de ressources sur Docker, cette richesse rend l'utilisation de Docker vraiment simple car avec quelques recherches on trouve vite une solution à ses problèmes.
Ainsi j'ai mis en place supervisord dans mon container Nginx pour lancer php-fpm et nginx, oui je persiste et combine le serveur web et php dans le même container.

Voici nouveau Dockerfile :

FROM nginx
MAINTAINER niclange
RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y php5-fpm php5
RUN sed -i 's/;extension=gd.so/extension=gd.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=iconv.so/extension=iconv.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=mcrypt.so/extension=mcrypt.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=mysql.so/extension=mysql.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=sqlite3.so/extension=sqlite3.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=pgsql.so/extension=pgsql.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=ldap.so/extension=ldap.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=openssl.so/extension=openssl.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=pdo_pgsql.so/extension=pdo_pgsql.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=pdo_mysql.so/extension=pdo_mysql.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=pdo_sqlite.so/extension=pdo_sqlite.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/listen.owner = www-data/listen.owner = nginx/g' /etc/php5/fpm/pool.d/www.conf
RUN sed -i 's/listen.group = www-data/listen.group = nginx/g' /etc/php5/fpm/pool.d/www.conf
RUN sed -i 's/;listen.mode = 0660/listen.mode = 0660/g' /etc/php5/fpm/pool.d/www.conf
RUN touch /etc/supervisor/conf.d/supervisord.conf
RUN echo "[supervisord]" >> /etc/supervisor/conf.d/supervisord.conf
RUN echo "nodaemon=true" >> /etc/supervisor/conf.d/supervisord.conf
RUN echo "[program:nginx]" >> /etc/supervisor/conf.d/supervisord.conf
RUN echo "command = /usr/sbin/nginx" >> /etc/supervisor/conf.d/supervisord.conf
RUN echo "user = root" >> /etc/supervisor/conf.d/supervisord.conf
RUN echo "autostart = true" >> /etc/supervisor/conf.d/supervisord.conf
RUN echo "[program:php5-fpm]" >> /etc/supervisor/conf.d/supervisord.conf
RUN echo "command = /usr/sbin/php5-fpm" >> /etc/supervisor/conf.d/supervisord.conf
RUN echo "user = root" >> /etc/supervisor/conf.d/supervisord.conf
RUN echo "autostart = true" >> /etc/supervisor/conf.d/supervisord.conf
COPY nginx.conf /etc/nginx/nginx.conf
COPY users /etc/nginx/conf/users
COPY toto.crt /etc/ssl/private/
COPY titi.key /etc/ssl/private/
EXPOSE 80 443 442
CMD ["/usr/bin/supervisord"]



En suite j'ai mis en place cAdvisor, ceci juste en ajoutant un container Docker en suivant la documentation, soit une ligne de commande (à ajuster un peu) et bien entendu je l'ai mis derrière le nginx pour l'exposer en toute sécurité en https et tout. A noter que les liens internes ne semblent pas toujours bien gérés derrière le revers proxy mais on s'en sort quand même.
Et oui les petits containers se reproduisent déjà...
Les interfaces de cAdvisor sont très sympa mais ça m'a l'air d'être assez consommateur en CPU...


Sans remplacer Monit, auquel je tiens accord un peu, j'ai n'ai pas encore décidé de son abandon, et ce billet me donne un espoir.

Après une petite pensée pour Docker, on m'a fait remarquer ceci boycottdocker. Et tout cela m'a fait prendre conscience de toute un mouvement anti docker qui semble porté par des personnes très compétente, plus que moi en tout cas et cela a du sens. Mais je vais continuer avec Docker... parce que justement je n'ai pas besoin d'être un crack de l'admin système et que l'écosystème porté par Docker me plait par ça richesse et ça simplicité. Et je suis bien certain qu'en remontant mes manches avec LXC ou KVM je n'aurais pas de souci avec Monit ou pas...


mardi 4 août 2015

Le voyage du Kimsufi en Docker (Etape 1)

J'ai un petit serveur kimsufi avec quelques applications sympa et puis ça me permet de bidouiller un peu, de m'ouvrir à de nouveaux aspects de l'informatique qui dépassent ce que je réalise professionnellement.

J'ai donc un petit Nginx en frontal de divers applications comme Seafile, Subsonic, un Monit pour voir si tout tourne bien et réaliser un monitoring des ressources.

Et là je me dis pourquoi pas dockeriser tout ce petit monde.
On se demande bien pourquoi ? Quel est l'intérêt de consacrer de l'énergie pour tout mettre dans des containers Docker ?
Le premier est tout personnel : apprendre à utiliser cet outil et voir si ça vaut le coup de le mettre en place sur des projets professionnels avec un peu d'architecture en microservices.
En suite le serveur est sous Debian et réaliser une montée de version n'est pas si évident ainsi je peux créer des container dans un version plus récente de Debian sans modifier mon système hôte.
Cela peut faciliter la monté de version de Debian, la migration vers une autre machine, chez un autre hébergeur ou dans une infrastructure cloud...

Après que vais-je perdre ? A priori Monit ne permettra pas de manager les différents services dans les containers, ou à payer mmonit. Il va falloir passer à supervisord installé dans chaque container et un container pour supervisorctl et peut-être un cAdvisor en prime... De plus supervisord semble la solution préconisée pour lancer plusieurs processus dans le même container.
Et pas mal de temps... visionner les vidéos pour survoler les concepts et l'utilisation de Docker. Du temps pour installer Docker (et une petite montée de kernel pour que ça marche). Du temps pour faire les Dockerfiles et les commandes docker run... Du temps pour tester, modifier les conf et un peu d'astuce pour ne pas avoir une indisponibilité trop longue des divers services de mon kimsufi.

La stratégie de migration en Docker, là on a deux options un marathon de 48h ou y aller progressivement, container par container valider puis tous les containers.
Je prends la seconde option car je n'ai pas de fenêtre de 48h dans mon emploie du temps, juste une heure par-ci par-là. Donc le principe créer une image pour chaque service, et réaliser un run de chaque container puis réaliser les liens au travers d'un fichier docker-compose.yml
J'ai réalisé la 1er étape :



Sans trop de difficultés l'astuce est de réaliser le run du container nginx avec les options suivantes
--privileged=true --net=host 
Ainsi il n'y a pratiquement pas de modification à faire le la configuration de nginx. Par contre le processus nginx ne peut plus être supervisé par Monit... il reste les stats du container : 

CONTAINER CPU % MEM USAGE/LIMIT MEM % NET I/O 
nginx               0.00%   10.22 MB/2.08 GB      0.49%     0 B/0 B

Tranquille tout ça.

J'oubliais ça peut-être intéressant les Dockerfile :

FROM nginx
MAINTAINER niclange
RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y php5-fpm php5
RUN sed -i 's/;extension=gd.so/extension=gd.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=iconv.so/extension=iconv.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=mcrypt.so/extension=mcrypt.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=mysql.so/extension=mysql.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=sqlite3.so/extension=sqlite3.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=pgsql.so/extension=pgsql.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=ldap.so/extension=ldap.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=openssl.so/extension=openssl.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=pdo_pgsql.so/extension=pdo_pgsql.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=pdo_mysql.so/extension=pdo_mysql.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/;extension=pdo_sqlite.so/extension=pdo_sqlite.so/g' /etc/php5/fpm/php.ini
RUN sed -i 's/listen.owner = www-data/listen.owner = nginx/g' /etc/php5/fpm/pool.d/www.conf
RUN sed -i 's/listen.group = www-data/listen.group = nginx/g' /etc/php5/fpm/pool.d/www.conf
RUN sed -i 's/;listen.mode = 0660/listen.mode = 0660/g' /etc/php5/fpm/pool.d/www.conf
COPY nginx.conf /etc/nginx/nginx.conf
COPY users /etc/nginx/conf/users
COPY toto.crt /etc/ssl/private/
COPY titi.key /etc/ssl/private/
EXPOSE 80 443 442
Et oui j'ai ajouté php5-fpm mais je ne suis pas certain que cela soit pertinent.

vendredi 5 juin 2015

Combiner BitTorrentSync et Seafile

J'ai en place un serveur avec seafile, ça fonctionne bien, même très bien avec des fonctionnalités pertinentes. Bref c'est très pratique, mais BitTorrentSync est arrivé et le concept est aussi intéressant et peut répondre à une problématique : la synchronisation de 2 postes sur le même réseau local sans passer par le serveur sur internet.

Mais peut-on combiner les 2 produits pour synchroniser le même répertoire et bénéficier ainsi de tous les avantages :
  • BitTorrentSync :
    • utilisation du réseau local
    • pas de dépendance à un serveur central
  • Seafile :
    • un serveur central qui est presque toujours disponible (chez un hébergeur)
    • versioning et snapshot 
    • création de liens sécurisés pour partager accessibles tout le temps
    • interface web accessible
    • chiffrage côté serveur & coté client (option)

La réponse est oui, il peut y a voir quelques collisions de fichier mais Seafile semble bien s'en sortir en réalisant une duplication des fichiers qui lui posent problème. Mais le plus simple semble de mettre en pause la synchro Seafile lorsque que le répertoire se synchronise avec BitTorrent Sync.

Configuration des répertoires :


Ici le but est de synchroniser le répertoire "Ma Bibliothèque", le répertoire "save" est une sauvegarde de sécurité car les manipulations divers peuvent entraîner quelques pertes. "Seafile" est le répertoire de base de Seafile il n'est pas direchttp://seafile.com/en/help/ignore/tement synchronisé.

Voici les étapes :

  1. Mettre en place seafile et synchroniser 2 PC clients
  2. Ajouter un fichier seafile ignore : http://seafile.com/en/help/ignore/ avec le contenu suivant : .sync/
  3. Désactiver la syncho automatique
  4. Sur un premier PC installer BitTorrent Sync et partager le répertoier Ma Bibliothèque
  5. Installer BitTorrent Sync sur le second PC
  6. Vider le répertoire "Ma Bibliothèque" sur le second PC
  7. Là j'ai dû installer l'application Sync sur mon téléphone portable pour lier les 2 PC c'est le plus simple finalement
  8. Synchroniser avec BitTorrent Sync le second PC avec le répertoire "Ma Bibliothèque", là il devrait rapidement se synchroniser
  9. Activer la synchronisation de Seafile et vérifier que le répertoire .sync n'est pas synchronisé sur le serveur
Si tout marche cela devrait se stabiliser et aucune notification n’apparaît, si des notifications de synchronisation apparaissent c'est qu'un répertoire .sync/ est synchronisé, il peut aussi y avoir quelques collisions mais les fichiers sont faciles à identifier.

mercredi 28 janvier 2015

Logger les performances avec l'AOP dans une application n-tiers (Java)

La perf, un sujet incontournable, il sera mis tôt ou tard sur la table. Il faudra comprendre, améliorer, supprimer les points de contentions. Pour cela il est indispensable de réaliser des mesures. Un panel de solutions permettent de réaliser des mesures avec plus ou moins de finesse, dans diverses conditions.
Du temps d'exécution d'un test unitaire à un test de charge avec SoapUi ou JMeter, à une analyse de la jvm avec VisualVM ou Java Mission Control . Enfin en combinant tout ça on est certain d'arriver à une mesure fine et à identifier les axes d'optimisation. Mais à quel prix, ces outils on un coup non négligeable de mise en œuvre, et la traque prend du temps.

Une solution simple permettant de réaliser des rapports est la mise en place d'un logger par AOP s'appuyant sur l'architecture en couche (oui votre application est architecturée en couche). L'architecture en couche permettra l'utilisation de l'AOP de façon assez simple en interceptant les interfaces de chaque couche, et cela permettra de structurer le rapport. Cette approche est assez rapide et simple à mettre en oeuvre.

Pour cela j'ai développé un mini projet Log4Tiers (https://github.com/niclange/Log4Tiers) pour réaliser ces logs de performance, oui il est très simple et probablement beaucoup l'ont déjà implémenté. Il s'appuie sur Spring pour la mise en œuvre de l'AOP. On se place dans un contexte web, on va donc réaliser un log en tentant de suivre chaque appel au travers d'un identifiant (en rapport avec le thread), puis on identifiera chaque couche appelée et chaque méthode et les temps consommées.
Le plus complexe pour la mise en oeuvre est la configuration Spring de l'AOP.

Attention le fait de logger à un coût, et aura une impacte non négligeable, surtout si on log les éléments ayant une fine granularité, il faut donc en tenir compte, configurer la configuration AOP Spring en conséquence.

Vous trouverez un exemple complet dans la partie test unitaire du projet.
Je vais finir en ajoutant comment traiter le résultat du logger avec Excel.
On ouvre le fichier csv avec excel et on ajoute les entêtes des colonnes
En suite on peut réaliser un tableau croisé dynamique pour faire ressortir par exemple chaque appel :
Ou les couches de l'application :

A partir de là on peut réaliser toutes sortes de graphiques.


Sinon j'ai mis à jour le projet pour activer/désactiver les loggers par JMX.