13 décembre 2016

Quoi d'neuf Docker ? ... ben rien justement

Il y a quasiment un an jour pour jour je me lançais dans l'aventure Quoi d'neuf Docker, avec le soutien inespéré de nombreux internautes pour mener au bout une campagne de Crowdfunding, suivie d'une série de vidéos pour lesquelles j'ai pu tester différents styles et en même temps en apprendre beaucoup sur Docker.

Force est de constater que, depuis la dernière vidéo diffusée en Juillet, la chaîne montre un encéphalogramme plat. Il est donc temps pour moi de déclarer sa mort clinique.

Pour faire court, depuis Juillet j'ai changé de poste, et j'ai nettement moins de temps libre avec en plus de régulières réunions en soirée (merci les 9 heures de décalage horaire avec la côte Est). J'ai aussi de nouvelles contraintes familiales à considérer, et par dessus cela ces derniers temps des soucis qui me bouffent le peu qui me restait de "temps libre".

Disons les choses clairement, même si l'envie de filmer une nouvelle vidéo revient régulièrement, si ce n'est pas la préparation du contenu qui pose problème, si même mon public est encore assez sympa pour m'encourager, je sais que de longues heures de montage m'attendent, et que cela va s'éterniser.

J'ai ainsi un tiers de vidéo "docker-swarm" qui dort sur mon disque dur depuis deux semaines, et qui va rester dans cet état inachevé car je me rend bien compte que je ne trouverais pas le temps ni l'énergie pour en venir à bout.

Plutôt que de bâcler, je préfère renoncer, et laisser les nombreux Docker Captains qui en ont encore l'énergie vous abreuver des informations que vous attendez d'eux. Je me doute que quelques un seront déçus, mais rassurez vous d'ici quelques jours ce sera oublié.

Merci à tous ceux qui m'ont soutenu et encouragés pendant cette expérience très riche d'enseignements. 


30 octobre 2016

J'ay pris le temps d'e-lire

Je viens de finir le deuxième tome de "Prenez le temps d'e-penser", le bouquin de Bruce Benamran, célèbre pour sa chaine Youtube de vulgarisation scientifique dont le succès ne faiblit pas.

J'ai eu le plaisir de rencontrer brièvement Bruce (je me permet donc de l'appeler par son prénom) lors d'une séance de dédicace du tome 1. Le bonhomme est souriant et disponible, aussi j'espère qu'il  appréciera mon honnêteté dans ce billet - en supposant qu'il le lise, c'est un autre histoire, le Bruce étant très demandé je n'arrive pas bien à me représenter à quoi doit ressembler son agenda.

Pour commencer, un petit mot : Bruce est pour moi un modèle, ses capacités pédagogiques naturelles me laissent sans voix, le seul auteur qui m'ai laissé cette impression est Richard Feynman c'est dire. C'est en suivant ça chaîne que j'ai décidé de lancer la mienne, frustré par le format trop linéaire des conférences que je présente par-ci par là. Voilà.


Je vous livre donc mon avis de lecteur.

D'abord sur le Tome 1.




Bon commençons par dire que c'est un excellent bouquin à mettre entre toutes les mains. Sympathique, sur le ton de la conversation pleine de pointes d'humour, de références geek et autres détours qui rendent le texte très agréable, j'ai dévoré ce livre en 2 jours. Je m'attendais à ce qu'il reprenne des sujets et anecdotes déjà présentés en vidéo, aussi ce n'est pas un point qui m'a déplu, le contraire m'aurait en fait déçu, le livre étant ainsi la pleine continuité de la chaîne Youtube.

Je suis par contre un peu resté sur ma faim sur deux aspects : l'explication de la relativité du temps et de l'espace et un sujet foutrement compliqué, qui brutalise notre sens commun, et qu'il est bien délicat d'expliquer sans un tableau blanc et quelques schémas. Bruce à fait le choix de se concentrer sur du pur texte, ce qui rend ce chapitre étrangement difficile par rapport à la fluidité d'explication et aux analogies ingénieuses auxquelles il nous avait habitué. Bon clairement, je vois mal comment présenter le sujet autrement, je ne dis pas qu'on puisse faire tellement mieux ... mais de mémoire il me semble que j'avais plus tilté à la lecture de (l'excellent) Univers Elegant. Ou alors j'ai peut être juste eu le temps de digérer le truc ? Comme Bruce s'est en plus amusé à nous faire une révision des présidents de la 5ème république, je me demande s'il n'a pas fait exprès de nous mettre un chapitre destiné à être lu deux fois (ou plus) histoire qu'on soit bien imprégnés.

Second aspect, qui m'a fait retirer un dixième de point dans mon classement des livres indispensables que j'achèterais en triple pour les offrir à mes gamins, le chapitre sur la mécanique qui se présente comme une suite de concepts, annoncés comme un mal nécessaire. C'est très inhabituel de la part de Bruce qui met un point d'honneur à rendre tout sujet à la fois clair, amusant et immédiatement compréhensible.

Pour avoir été moi même auteur (Apache Maven - 1500 exemplaires vendu, j'aurais peut être du choisir un sujet un peu plus large) je sais aussi qu'il faut parfois savoir jongler avec les délais de l'éditeur et que - malheureusement - certains chapitres en souffrent. Tout le monde n'est pas un George R.R. Martin... Bon ceci dit ce n'est qu'une spéculation appuyée sur du vent, peut être que Bruce voulait faire ça comme ça et puis c'est tout, lui seul le sait et il fait ce qu'il veut de toute manière, et le succès des ventes du livre semble montrer que ça n'a gêné personne...

Donc en résumé, une oeuvre qui est un morceau de choix pour tout lecteur intéressé un temps soit peu à la science, et à laquelle j'ai trouvé quelques critiques juste par ce que je suis un éternel insatisfait.


Passons au Tome 2



Dans ce tome, on attaque (entre autre) des sujets qui annoncent une sacré migraine : mécanique quantique, big bang, cosmologie, trou noirs et théorie de cordes...

Et là, je retrouve le Bruce que j'apprécie : AUCUN chapitre n'a relevé pour moi un quelconque point négatif. Malgré le sujet pourtant ardu et profondément imbitable pour le sens commun,  Bruce arrive à nous préparer avec soin et à présenter chaque sujet, toujours avec ce fabuleux mélange d'humour, d'histoire des sciences, et d'analogies - et quand on parle de mécanique quantique, faut avoir une sacré imagination pour en trouver.

Je me dis que pour ce tome 2, Bruce était plus rodé, confiant, peut être moins pris avec la fin de la tournée de l'eXoConférence ? Avec la chaine en anglais j'en doute, mais bon. En tout cas, c'est un vrai régal. Et oui, sur ce coup là je n'ai rien à redire, pas le moindre petit truc à relever. Mince alors. Je vais le relire pour être sur...

Ah si : énorme déception d'apprendre qu'il n'y aura pas de tome 3. Sur sa chaîne Bruce ne se contente pas de présenter les sciences dures (i.e physique fondamentale) mais aussi beaucoup d'autres sujets, traités avec le même soin et toujours des références approfondies, concernant la biologie, le fonctionnement étonnant du cerveau, abordant parfois des problèmes qui touchent à la sociologie, ou bien des aspects méconnus de mécanique, enfin bref ça part dans tous les sens pour le plus grand plaisir des abonnés. Les deux bouquins abordent aussi ces sujets, mais dans une moindre mesure. Il y aurait donc matière pour un tome 3, 4, ... Mais bon, l'auteur fait ses choix, c'est le principe d'un auteur, c'est lui qui décide.

Donc bref, j'ai adoré ce bouquin et je suis extrêmement déçu d'avoir raté la dédicace à Rennes cette semaine - j'étais en vacances dans le Finistère, avec la crève en prime :'( - qui m'aurait donné l'occasion de féliciter Bruce de vive voix pour ce deuxième acte de son oeuvre. Vous l'avez deviné, je suis un fan, j'ai même tenté d'emprunter son style dans une de mes vidéos (après m'être tenté à imiter Karim, Fred ou François) ... comme quoi c'est pas si simple


Je profite de ce billet pour faire savoir à ceux qui ont raté l'info (?) que Bruce a mis à jour son site vitrine e-penser.com qui propose maintenant des annonces et du contenu exclusif.

Donc bref, pour noël ou n'importe quel autre prétexte, n'hésitez pas à sortir 19,90€ (x2) pour faire des heureux.



13 septembre 2016

Docker-Slaves 1.0 released

This week is JenkinsWorld, and I won't be there ... but this doesn't mean I won't be part of it.

I'm pleased to announce Docker-slaves-plugin has reached 1.0.

Docker-slaves was created on year ago, as Yoann and I joined forces during DockerHackDay, with complementary ideas in mind to re-invent Jenkins in a Docker world. We are proud we were able to develop a working prototype within 24 hours and won 3rd prize on this challenge !


What makes Docker slaves such a revolution ?

Docker-related Jenkins plugins so far use a single docker container to provide a Jenkins agent (aka "slave"), which will host a build. Such a container is running a Jenkins remote agent and as such has to include a JRE, and allow connection from master or connect to master by itself. In both cases, this introduces significant constraints on the Docker image one can use. We want this to disappear.

With Docker-slaves, you can use ANY docker image to run your build.


To communicate with remote agent, Jenkins establish a communication channel with slave. On ssh slave, this communication uses the ssh connection as a tunnel. Other slave launcher uses various tunneling techniques or explicit port allocation to create this channel. But docker also has an interactive mode to run a container, which let us establish a stable (encrypted) connection with a remote container. Running `docker run -it` is very comparable to running a ssh client to connect to a remote host. So we use this capability to create the remoting channel directly on top of docker's interactive mode.

SSHD in docker container is evil. Docker-slaves don't need one, and does not require your master to expose JNLP on the Internet  


Docker is not just about container, it's also about containers. docker-compose is a popular tool and demonstrate need to combine containers together to build useful stuff. We think a build environment has the same requirement. You need maven to build your project, but you also need a redis database and a web browser so you can run Selenium functional tests. Just create 3 containers, and link them together ! This is exactly what Docker-slaves does, so you can define your build environment as a set of containers. 

Docker-slaves let you compose your build environment 


... and you can even define those containers using a Dockerfile you store in SCM ! If you love infrastructure as code, you'll be happy to get both your source code, continuous deployment pipeline script, and build environment stored all in your project SCM with plain Dockerfiles. Docker-slaves will build the required image on demand and run the build inside this container.

Docker-slaves bring Continous-Delivery-as-Code to next level


Docker slave also adds a transparent "remoting" container so Jenkins plumbing is well setup and all Jenkins plugins work without any change.  This includes Pipeline plugin. This plugin used to require a classic jenkins slave as node() to run build step, and this node to host a docker daemon if you want to run anything docker related. With docker slaves, just write your Jenkinsfile without need for a single classic Jenkins executor.

dockerNode("maven:3.3.3-jdk-8") {
    sh "mvn -version"
}

How does this compare to docker-pipeline's docker.inside ? There's no need for a host jenkins Node here, nor a local Docker daemon installed on your jenkins slaves. You can rely on docker swarm to scale your build capacity.

Docker-slaves do embrace Pipeline


Last but not least, Jenkins docker-related plugins use to start with a fresh, new slave, which require to run a full SCM checkout and populate project dependencies. Docker-slaves uses a volume as build workspace, so this one is persistent between builds. There is huge room for improvement here, with assistance for docker's volume-drivers, typically to provide snapshot capability so you can browse workspace for a specific build (to diagnose a build failure) or replicate workspace on cluster.

Docker-slaves workspace is persistent


If you have opportunity to give it a try, please send me feedback @ndeloof


UPDATE:
For some odd reason (who said "conspiracy" ?) docker-slaves 1.0 was not published in update center (yet). Will need to investigate with Jenkins infra team, but with Jenkins World they are all higly busy this week.


20 juin 2016

DockerCon : quand docker-swarm laisse la place à docker swarm

tl:dr; 
docker 1.12 = docker 1.11 + swarmKit + server-side docker-compose 


Dans ma dernière vidéo je vous parlais du changement d'architecture de Docker 1.11 et du fait que le démon docker ne fait "plus grand chose" - à part l'authentification et la gestion des images, quelques bricoles quoi.

Il faut croire que, comme la nature, l'équipe Docker a horreur du vide, puisqu'elle s'est empressée de remplacer ce déficit de fonctionnalités dans la version 1.12 (Release Candidate 2) annoncée ce matin en keynote de la DockerCon - et oui, j'étais au courant avant, nananèreu

Dcoker-swarm est mort, vive docker swarm


Vous aviez sans doute vu passer l'annonce de swarmKit, un projet issu de l'architecture de docker-swarm mais plus générale (on parle ici de "tâches", pas forcément de conteneurs docker). En fait ce projet est reparti de la page blanche, en reprenant ce qui a bien marché dans docker-swarm et en choisissant d'autres pistes pour ce qui marchait moins bien.

Typiquement, oubliez votre etcd / consul et le zookeeper qui va bien pour gérer un cluster swarm. Jusqu'ici, swarm avait besoin d'un service externe "clé/valeur" pour stocker la configuration du cluster. En plus de compliquer le setup pour assurer de la haute disponibilité, cela introduisait pas mal de délais dans le traitement asynchrone de la transmission de ces infos. 

SwarmKit utilise Raft, protocole d'élection d'un noeud maître, et son implémentation par etcd. Plus besoin de service externe, un cluster swarm se suffit à lui même out-of-the-box pour distribuer ses métadonnées et élire son noeud "leader". 

Mais l'annonce de SwarmKit n'était que la partie visible de l'Iceberg, qui d'ailleurs à trompé pas mal de monde, car comme toujours les évolutions de Docker sont visibles sur le projet open-source pour qui sait lire entre les lignes des Pull-Requests.

Docker 1.12 annonce donc l'intégration native de swarmKit, pour former un cluster swarm sans quoi que ce soit d'autre que le démon Docker. Cette nouvelle feature n'est pas active par défaut (la compatibilité restant la première priorité). Il vous faudra explicitement passer en "mode swarm":  docker swarm init

Docker 1.12 introduit aussi le concept de services, et permet de déployer N instances d'un conteneur sur le cluster (voir, sur tous les noeuds du cluster - parfait pour l'exploitation), de gérer leur re-schedule automatique en cas de défaillance, le load-balancing de ces N instances, les mises à jour en rolling-upgrade, etc. Bref, ce que vous faisiez jusqu'ici avec docker-swarm ou avec votre orchestrateur docker préféré (sic), vous pourrez le faire en natif avec le docker engine de base, dans le cadre d'un cluster swarm - le nom reste, je reconnais que ça peut être source de confusion, mais bon en même temps au final c'est le même concept.

Le load balancing c'est une nouveauté importante qu'il va falloir que je teste plus en profondeur. S'il est toujours possible d'utiliser le DNS avec la liste des IP associées à un service, ce qui suppose que votre code client gère ça correctement (sic), la nouvelle approche consiste à faire du load balancing en se basant sur IPVS (i.e passer par le noyau Linux). Les interactions exactes entre un service déployé de cette façon, les conteneurs qui lui permettent de tourner, et les réseaux / ports associés sont encore assez flous pour ce qui me concerne, cela nécessitera quelques tests plus appuyés.

De son côté, le projet docker-swarm, s'il va vivre encore un moment (support client oblige) va rapidement être dépassé par ce support natif dans docker-engine.

Compose se fait tailler un short

Seconde annonce majeure : l'ajout du concept de "service“ à l'API docker, avec des réplicas et un load balancing natif sur le cluster swarm.

Ca parait abstrait comme ça ? En pratique, vous allez déployer non plus un conteneur (même si vous pouvez encore) mais un "service" utilisant une image : 
docker service create --name foo --network bar ma_super_appli:1

Sur TOUS les noeuds de votre cluster swarm, et sur l'overlay network bar indiqué, vous pourrez discuter avec ce conteneur. Et si vous augmentez le nombre d'instances :
docker service update foo --replicas 5
.. docker se chargera de faire du round-robin sur ces conteneurs pour distribuer la charge. Evidemment il y a toutes les possibilités de contraintes / affinités / labels de swarm pour jongler finement lorsque c'est nécessaire. 

Pour faire simple, jusqu'ici vous utilisiez docker-compose pour lancer une grappe de conteneurs. Rassurez-vous, vous allez sans doute continuer à faire ça en développement, et le format docker-compose.yml n'est pas remis en question. Par contre, sur un cluster swarm docker-compose est exposé à une limite :

Docker-compose utilise l'API docker pour faire de l'orchestration, mais un déploiement compose n'est pas atomique. Comprenez que si vos deux premiers conteneurs trouvent leur place sur un noeud, et que le troisième ne rentre pas faut de resources disponibles, et bien votre déploiement échoue, point barre. En gros, docker-compose est un orchestrateur côté client, en mode optimistic transaction.

Docker 1.12 introduit le concept de "bundle", dont le format est encore très récent et sujet à évolutions (i.e ne vous attardez pas dessus pour le moment), qui définit un groupe de containers et comment les lier ensembles.



Oui, c'est tout pareil que docker-compose. D'ailleurs, docker-compose bundle vous permettra de générer une spécification de bundle à partir de votre fichier docker-compose.yml, il ne s'agit donc pas de remplacer compose, mais plutôt de le booster en lui fournissant une API à la hauteur de ses ambitions. 

Ce bundle (un fichier JSON à ce stade, mais ça peut encore bouger), vous le passerez à votre démon docker via la commande docker deploy. La différence avec compose, c'est que le déploiement se fait alors "côté serveur", avec la sélection des noeuds en connaissance de cause.

Contrairement à docker-swarm, docker-compose va par contre subsister puisque son mode de fonctionnement continue à être pertinent en mode "classic" (non-swarm) - typiquement sur le poste de développement - et assurer la liaison avec le format de bundle.

BREF

docker-swarm vient de se prendre un balle, et docker-compose s'est fait couper les jambes par l'annonce de Docker 1.12. Ce qui est intéressant ici, c'est de voir que ces deux outils, conçus sur la base de l'API docker, avec ses contraintes et limites, voient au final leur fonctionnalité coeur intégrée dans docker-engine. Et vont donc pouvoir renaître en inventant de nouveaux usages et patterns, lesquels seront peut être un jour intégrés à leur tour... 

Ce cycle peut paraître surprenant quand on investi sur un outillage qui peut devenir obsolète au détour des annonces d''une keynote, mais il montre la dynamique raisonnée de l'écosystème Docker : si une fonctionnalité démontrer son intérêt, elle finit par être prise en charge nativement dans l'engine, vidant l'outil de sa raison d'être première, mais au final montrant que l'approche était bonne, et ouvrant la voie pour le cycle suivant.




A ce stade 1.12 n'est qu'une Release Candidate, et l'effet d'annonce pour la DockerCon a limité la période de test par la communauté (très occupée à s'accaparer SwarmKit). La version 1.12, bien qu'activement testée par de nombreux partenaires, va mettre donc encore quelque semaines à murir, sous les assauts d'une communauté qui ne va pas se priver de la secouer dans tous les sens pour vérifier que
  1. ça continue de marcher comme avant 
  2. le nouvelles fonctionnalités tournent dans la vraie vie comme indiqué dans la doc
Dans tous les cas, Docker 1.12 va changer pas mal de choses dans votre façon de déployer Docker, en intégrant les concepts de clustering et de déploiements composites au coeur de docker-engine.




31 mai 2016

Docker Cleanup

Most Docker newcomers are disappointed when,  at some time, after various experiments with Docker, they hit a no space left on device issue. Docker indeed do store all containers, images and volumes in /var/lib/docker, which can quickly grow to gigabytes.

One can find tons of blog post about how to cleanup this folder. Here I'd like to give my own tips, and to explain them in detail, so you don't run random command found by Googling the Internet.

/var/lib/docker is used to store :


  • docker images
  • docker container descriptors
  • docker networks descriptors
  • docker volumes
  • containers' layers (depends on the storage driver you used. Typically AUFS)

Terminated containers

I use docker a lot to experiment unix commands, so use to run docker run --it ubuntu bash. When you run a container without the --rm option, container still exists on disk after the command complete. So doing this will create tons of containers, and layers for things I modified on container's filesystem. For this reason I created an alias docker-run to ensure I don't forget this option. But this option can't be used with -d (run in background) so I can't use it when I want to run some backend service for testing purpose. 

As the end of the day, I have tons of stopped containers that I don't use anymore, and will just consume disk in /var/lib/docker. So I use this command to run some cleanup :

docker rm -v $(docker ps --filter status=exited -q)

this command do list all exited containers (thanks to status filter), and only dump their ID (-q). This ID list is used by the remove command to cleanup containers, including volumes they where using.

Unused volumes

Volumes ? Yes, when you run a container which has been built with a VOLUME command in it's Dockerfile, docker do implicitly create a volume on disk, and may copy data from container image in this volume. This can result in significant disk consumption. Removing a container with -v option do force docker to remove such volumes. This doesn't apply to bind mount volumes, only to volumes created by docker daemon.

If you already removed your containers without using -v, volumes remain orphaned in /var/lib/docker. You can remove them as well using :

docker volume rm $(docker volume ls -q -f 'dangling=true')

the "dangling" filter do select volumes that aren't referenced by any container.

Note: one can find many scripts to do comparable cleanup by directly making changes to /var/lib/docker. Those script where written before docker volume command was introduced in 1.9. Don't use them. Directly hacking your docker daemon storage isn't a good idea when you have a clean API for this purpose.

Unused images

You can also use a comparable dangling filter with images, this one will detect image layers that are not referenced by a tag, which in many cases is the result of running docker builds.

docker rmi $(sudo docker images -f "dangling=true" -q)


what about obsolete / unused images ?
You can find some script to detect images which aren't used by a container on your system. For production environment this can make sense, but for my workstation this would remove mostly all docker images, as most container I run don't keep running all day long.

Docker doesn't track image use by containers, this issue is tracking attempt to change this, so writing a garbage collector would be simpler. So far I'm using https://github.com/ndeloof/docker-gc to collect image usage based on docker events. Not perfect, but does the job.


Hope this helps.


27 avril 2016

I'm now a Docker Captain

I'm now a Docker Captain

Captains is a Docker program to organize their best advocates around the world, give them first class informations and contacts in Docker community, help them to experiment and spread the world with great Docker related content.

Thanks to Docker captain program, we got access to Docker4Desktop before it was publicly announced, we get online webinars with engineering, and we now have a cool logo !

I'm pleased to have been selected as a Captain, even my Youtube Channel Quoi d'Neuf Docker is limited to French audience (maybe I should launch an english spoken one ?).

Java has Java Champions program, I never have been invited to join, despite my awesome Apache Maven book and talks at major conferences, seems it's easier to become a Docker star :P






25 avril 2016

cfp.io

I'm very excited to announce the launch of a long term project of mines: cfp.io


TLDR; Are you event organizer ? Need a free call-for-papers? Contact us, we will host it for you.

History

As a conference organizer, I've been handling call-for-papers for a while, and have actually worked on developing 3 of them (sic). 


  • We started in 2012 with a simple google form to collect speakers proposals. This was a poor experience, but did the job. Anyway as developers we decided we need a dedicated tool to offer a better service.
  • In 2013 we created our own CFP, and worked on it during the pre-event period so it match our needs. Main issue took place in 2014 when we tried to restart it from the initial collect phase, as the later changes had unexpected impacts (soc)
  • In 2015, DevoxxFrance offered to share his custom CFP application codebase. We forked it, and adapted to our needs. The codebase is written in Scala, and just for this reason I hardly was able to found volunteers to help us on this topic. Also, this application do cover lot's of Devoxx specific things, hidden in codebase. We ended with few speakers not being registered, as Devoxx do only offer a pass to the first two speakers, and we have labs with up to four of them :'(
  • In 2016, we forked DevFest Nantes Call for Papers application. This one was written in Java/Spring/Angular, had a nice look and feel, so was a great candidate. We noticed many glitches in backend, so decided to fix them ... and after few months had it mostly fully rewritten. Anyway, this was a smooth migration, and 4 volunteers where able to make it a great app.

Our CFP worked like a charm, and was then forked by NCfrats.io for their own need.

So, is this the definitive CFP we need ?

No: main issue here is to maintain forks of each others. As a sample, we discovered a security issue with our CFP, fixed it, but as this happened two weeks before the event, we didn't took time to let DevFest guys know about it (sorry guys). Also, people at NCrafts could introduce interesting features, and even git make it easy to backport such code, this could quickly become a hard task to keep everything in sync.

We believe a better approach is to colocate our Call-for-papers. a CFP is a low traffic application, limited data volume, and limited complexity. It's very easy to make our codebase multi-tenant, and we plan to offer free hosting for call for papers on our server. Each tenant will get access as https://{{my_awesome_event}}.cfp.io and will be able to manage his own stuff, without need to bother with infrastructure.


As code is open-source (AGPL) we will welcome contribution to offer additional features. If you have designed an integration with third party web service, then please contribute this new feature. Other platform users will then get notified about this new feature and can chose to use it as well. We expect this to be the best way for cfp.io to become the place to be for event organizers, covering all aspects of event management.

Emerging features

A side effect of co-hosting call for papers is to build sort of a speaker social network :

As a speaker, I have to copy/paste my bio and favorite talk abstract on various events' call-for-papers. With cfp.io, I can just reuse my bio, and select a talk I already proposed at eventA so I can apply to eventB. I also can discover events I didn't heard about, just because their CFP is hosted by the platform.
As an event organizer, I can check a speaker already talked at other events, and maybe this specific talk was recorded and available online. This will be a great assistance for program committee to select speakers.

Business model

Do we plan to create a company here ? No. we are a non-profit organization, and this is all just for fun ! We are just geeks, trying to make something cool and useful. Our "business plan" is for each hosted conference to get a free pass. Some of them will be use for our own pleasure to join great events, some of them might be sold to pay for the server, or to help us pay for travel.

If you are event organizer, feel free to contact us to get your CFP setup on our infra - we plan to make this automated as well on a self-service basis, but this isn't implemented yet.

24 avril 2016

Docker Slaves Jenkins plugin has been released !

At Docker Hack Day 2015, Yoann an I created Docker Slaves Plugin, an alternative way to rely on Docker for Jenkins to get build nodes. This initial implementation was the summary of a summer hacking Jenkins APIs and internal design, it was very helpful for us to suggest required changes in jenkins-core and offer a more flexible approach.

How does Docker-slaves differ from other Jenkins' Docker plugins ?

No prerequisite on Docker images

Jenkins uses a Java agent on build machine to manage build operations from master remotely. As a side effect, plugins like docker, amazon-ecs or kubernetes -plugins do require the Docker image configured to host builds to have a JVM, expected permissions, and sometime even a ssh daemon running.

We think this is a non-sense. You should not have to bake Jenkins specific images. Especially, if you don't code in Java but use Jenkins for CI, growing your Docker images by 200Mb of JDK is terrible.

We already explored this goal with Docker Custom Build Environment Plugin but this one also has some contraints : relying on bind mount, it require your Jenkins "classic" build node to have a local docker daemon installed. It also suffers some technical limitations :'(

Docker Slaves Plugin let you use any arbitrary image.

More than just one Docker image

Docker, amazon-ecs and kubernetes -plugins all rely on running a single docker image for the build. They some way admit a common misunderstanding aobut containers, considering them as ligthweight virtual machines. As a result, you can find some docker images to include tons of build tools and also start a selenium environment, like cloudbees/java-build-tools

Why try to get all this shit in a single docker image ? Couldn't we combine a set of more specialized docker images into a group ("pod") of containers configured to work together ?

We used this exact approach. Every build will executre with at least 2 containers :
  1. a plumbing 'jenkins-slave' container to run required Jenkins slave agent
  2. your build container
  3. some optional additional containers, for sample selenium/standalone-firefox to run browser-based tests, or a test database, or ... whatever resource your build require.
All those containers are set to share build workspace and network, so they can work all together without extra configuration.



Docker Slaves Plugin let you define build environment and resources as a set of containers.

Build specific Docker executor

Jenkins use to maintain a pool of slaves, which can be automatically provisioned by a Cloud provider. When a job is executed, such a slave get the task assigned, creates a log for the build, and start executing. After completion, the slave goes back to available pool. Docker-plugin and few other do hack this lifecycle so the slave can't be reused, and enforce a fresh new provisioned node.

This has an odd effect : when the docker infrastructure has issue to run your container, and so the slave doesn't come online, Jenkins will try to run another slave. Again and again. You won't get notified about failure as your build didn't even started. So, wafter few hours when you connect to Jenkins, you'll see hundred disconnected slaves and your build pending...

We wanted to reverse the Slave :: Build relation. We also wanted the slave environment to be defined by the job, or maybe even by content of the job's repository at build time - typically, from a Dockerfile stored in SCM. 

When docker-slaves is used by a job, a slave is created to host the build but it's actual startup is delayed until the job has been assigned, and a build log created. We use this to pipe the container launch log in the build log, so you can immediately diagnose an issue with docker images or Dockerfile you used for the build.

Docker Slaves Plugin creates a one-shot executor, as a main element of your build.

Jenkins Remoting

Jenkins communicates with the slave agent using a specific "remoting" library, comparable to Java RMI. It relies on this one so the master can access remote filesystem and start commands on slave.

But we use Docker, and docker client typically can be considered a way to run and control remote commands, relying on docker daemon as the remote agent. 

Docker Slaves bypass Jenkins Remoting when master has to run a command on slave. It relies on plain docker run for this purpose. We still need Remoting as it is also used for plugins to send Java code closures to be executed on slave. This is the reason we have a jenkins-slave container attached to all builds, which you can ignore, but is required for all Jenkins plugins to work without a single change. 

Docker Slaves Plugin reduce Jenkins Remoting usage.

Pipeline Support

Last but not least, Docker Slaves to fully embrace Jenkins Pipeline. Being main component for Jenkins 2.0, we could not just let Pipeline integration for further implementation effort.

Docker Slaves do introduce dockerNode Pipeline DSL, as an alternative to node used to assign a classic Jenkins slave. dockerNode takes as parameter the set of container images to be ran, then act as a node and you can use all your Jenkins Pipeline construct to script your CI/CD workflow.

dockerNode(image: "maven:3.3.3-jdk-8", sideContainers: ["selenium/standalone-firefox"]) {
  git "https://github.com/wakaleo/game-of-life"
  sh 'mvn clean test'
}

Docker Slaves Plugin embrace Pipeline.

What's next ?

There's still some point we need to address, and probably some bugs as well, but Plugin is working fine already. If you give it a try, please send us feedback on your usage scenario.

Something we want to address as well is volumes management. We re-attach the jenkins-slave container on later builds so we can retrieve a non-empty workspace. But we'd like to fully manage this as a volume and manage it's lifecycle. Especially, we'd like to experiment use of docker volume plugins to improve user experience. For sample, use of Flocker would allow us to snapshot workspace on build completion. This could be useful to offer post-build browsing of the workspace (for diagnostic on failure for sample) or to ensure a build starts from the last stable workspace state, which will offer pre-populated SCM checkout and dependencies, without the risk to get a corrupter environment from a build failure.

We also would like to investigate adapting this approach on container orchestrator like Kubernetes. Not sure they offer the adequate flexibility, maybe only a subset of the plugin could be enabled on such an environment, but makes sense to give it a try.

As a resume, still some long hacking nights in perspective :)

In the meantime, please give it a try, and let us know if it would be helpful for your Jenkins usage.



04 mars 2016

Google Summer of Code

Ca faisait un bail, pas vrai ?

J'écris ce billet pour faire savoir que je participe cette année au Google Summer of Code en tant que mentor.

GSoC est un programme de Google qui consiste à mettre des étudiants entre les mains de mentors sur des projets open-source reconnus. Après un premier mois d'immersion, ils doivent bosser deux mois pendant l'été sur le projet, et leur contribution est évaluée par leur mentor et Google pour valider leur participation. Google rémunère alors les étudiants qui ont rempli leur contrat.



Ce n'est donc pas un stage, encore moins avec une belle convention de stage comme on les aime en France. Par contre c'est passionnant et une excellente carte de visite. Donc ça peut être difficile à faire passer auprès de votre direction des études, mais ça vaut le coup de tenter de les dépoussiérer un peu !

Je propose un sujet dans le cadre de Jenkins : "Jenkins et Docker sont dans un bateau ..."

L'idée est de tordre un peu Jenkins pour remplacer son mode synchrone, basé sur un mécanisme semblable à RMI, pour contrôler des process sur une machine de build distante.

A la place, nous voulons utiliser le support natif de Docker pour contrôler des process distant et de manière asynchrone - et sans se prendre un CVE sur la sérialization Java (sic).

Et bien sur, le tout de manière backward compatible (ben oui, c'est Jenkins) ce qui promet quelques heures de réflexion intense.



Bref, si vous êtes intéressé, commencez déjà par aller voir https://summerofcode.withgoogle.com/ pour comprendre le process du GSoC, ensuite on en discute sur la mailing list jenkins-dev !

26 janvier 2016

Quoi d'neuf sur Quoi d'neuf Docker ?

Salut  à tous,

dans mon dernier post - sur ce blog qui n'est plus très actif, je dois l'admettre ... - je vous parlais de la chaîne Youtube que j'ai montée pour partager mon enthousiasme sur Docker.

Depuis ce dernier billet, d'une part le crowdfunding Ulule s'est terminé avec succès (107%!), et j'ai comme convenu commencé à mettre en oeuvre les contreparties, dont la merveilleuse chanson du merci


J'ai aussi publiée trois épisodes, avec des niveaux successifs - du plutôt accessible "Docker 101" au significativement plus touffu "Le grand plongeon". Certains m'ont fait remarquer cette différence importante de niveau. Je compte mixer des vidéos plutôt techniques (pas trop rassurez vous, car ça me demande pas mal de préparation) avec des sujets plus légers.

En parlant de légèreté, une issue un chouille provocatrice que j'ai créée à provoqué un déferlement de créativité de la part des Francophiles et tout poils, et j'ai voulu leur rendre hommage avec une nouvelle vidéo - pas du tout technique celle-là : ET Si ... Docker était resté Français.

Vous l'aurez compris, cette chaîne est un soigneux mélange de genres, et est surtout pour moi l'occasion, comme je l'avais annoncé sur le projet Ulule, de mettre en pratique des idées et des technique de tournage/montage vidéo. Je m'essaye à copier tant bien que mal le style de plusieurs Youtubeur que j'affectionne, pas forcément toujours avec le résultat escompté mais qui ne tente rien...

Bref, Quoi d'neuf Docker est lancé, et bien lancé (j'ai une TODO-list assez conséquente) et j'ai beaucoup d'idées de mise en scène à expérimenter :D Votre aide sur le crowdfunding m'a ouvert de nouvelles portes avec un magnifique Canon 70D et un objectif très lumineux, de quoi occuper quelques heures d'apprentissage.

Par ailleurs, la chaîne compte déjà plus de 700 abonnés - oui, 700, même sur un sujet aussi ciblé - et je commence à rêver du Youtube Space Paris, réservé aux chaînes ayant plus de ... 1000 abonnés.

Je n'ai donc pas à vous dire ce qu'il vous reste à faire...

Et comme certains d'entre vous n'ont pas vu le Ulule à temps et veulent tout de même contribuer à la chaîne (sic), j'ai mis en place un Tipee, en gros un crowdfunding sans limite de temps. Je n'attend pas particulièrement à ce que cela m'apporte grand chose, mais qui sait, cela pourra participer à financer du matériel plus spécifique, et/ou des frais de déplacement - DockerCon Seattle, je pense à toi

Merci à tous pour votre soutien, vos encouragements, et rendez-vous très très bientôt (enfin, si le tournage de ce soir se passe bien ...)




12 décembre 2015

Un chaîne Youtube consacrée à Docker

Comme le prouvent les vidéos que nous publions chaque année pour faire la promotion du BreizhCamp, je prend un grand plaisir à manipuler la vidéo comme média de communication.

Je suis impressionné par le succès des chaînes Youtube des pointures du Net Français : JoueurDuGrenier, e-Penser, Axolot, Salut les Geeks ou Antoine Daniel apportent tous à leur manière une expression libre sur le web avec un talent certain.

Je n'ai pas la prétention de me comparer à ces références, mais le format employé m'attire sans conteste. Aussi, je lance une chaîne Youtube, sur un sujet de niche : Docker ...

"de niche" parce que pas du tout grand public. Oublions donc tout de suite les millions de vues, promesse de toucher un chèque signé "Youtube". L'idée est ici de présenter Docker et son écosystème, comme je le fais en conférence, mais en exploitant le média vidéo, c'est à dire pas sous forme de conférence filmée, linéaire, mais en exploitant les possibilités données par le montage et la mise en scène.



La chaîne est encore naissante et a donc pour le moment une URL à chier, il faudra attendre 500 abonnés pour régler ça, mais pour ça il faut déjà proposer du contenu.

Ce contenu est déjà en préparation, mais je veux profiter de cette occasion pour aller plus loin que ce que j'ai produit jusqu'ici, en particulier en raison des limitations de la caméra que j'ai à ma disposition via le BreizhCamp. J'aimerais passer au tournage sur boitier Reflex, profiter de l'expérience en photo de plusieurs collègues pour choisir les bons objectifs et trouver des astuces de cadrage, etc.

Bref, il va falloir investir, et pour cela je fais appel aux bonnes volontés, via un financement participatif sur Ulule : http://fr.ulule.com/neuf-docker/

Je prépare un premier épisode pilote en tant que "proof of concept" et pour montrer ce que j'ai en tête, en espérant que cela déliera les portefeuilles. J'ai placé le premier niveau de contribution à 5€ en espérant que cela motivera ceux qui ne sont pas des connaissances directes, comme on dit "les petits ruisseaux font les grandes rizières"

Bref, à vot' bon coeur.


UPDATE
Je viens de publier un épisode pilote, pas vraiment technique, mais qui donne une idée de ce que j'ai en tête. j'espère qu'il vous amusera.



04 décembre 2015

Docker Garbage Collector

When you play a bit with Docker, you end up after some time with a very classic filesystem full issue.

The first time you hit this issue, you learn the docker rm command and start using --rm option to launch containers. The issue here is container aren't destroyed when stopped/killed. Most of us do even have some cleanup alias/script to run something like

docker rm $(docker ps --filter status=exited -q)


You also can hit such an abusive disk usage issue as you get lot's of obsolete image stored on your disk after you tested various things pulled from DockerHub. Same cause usually has the same effect, so you add to your script some :

docker rmi $(docker images | grep “^” | awk ‘{print $3}’)


(based on https://gist.github.com/ngpestelos/4fc2e31e19f86b9cf10b)

So, what's next ?
First issue with such a script is you have to run it by yourself when something goes wrong.
Second issue is such a script do remove untagged images, but not tagged ones you won't use anymore. Some other script could remove all unused images, but will then in many cases force you to re-pull few images you use on a daily basis, but weren't running at the time you ran the cleanup.

To avoid such an issue, I've created a small tool : docker-gc

This tool do listen docker daemon for destroy events, so it knows when a container is removed, and can capture the image it used. This information is used, when the gc process list the unused images, to determine which one where used recently and should be kept - as I assume you will reuse the same image on a regular basis - and which one weren't used for a long time and should be removed.

I'm sure there's many ways to improve the actual GC algorithm efficiency.

For convenience, tool is distributed as a docker image (what else ?) as ndeloof/docker-gc, just need to bind mount docker unix socket so it can interact with DockerHost daemon.

docker run -d -v /var/run/docker.sock:/var/run/docker.sock ndeloof/docker-gc


As a cool project needs a cool logo, I created one using a Jellyfish as a mascot to cleanup docker's ocean. 


Please note docker legal terms totally prohibit such a logo usage, so don't do such crazy logo hijack if you don't want Solomon's advocates to knock at your door. I'll welcome Laurel's pull-request to suggest another one :P

27 novembre 2015

a Dockerfile-based Continuous Delivery Pipeline

I've seen a bunch of project with a Dockerfile to package some app into a production docker image. Most of them do rely on some pre-existing binary they just ADD / curl into the image. This demonstrates some missing piece in the equation, as this binary has to be built from source, and as such you loose the traceability of your built image.

On the other side, some try to setup a full "build from source" Dockerfile, but as a result end with source code and many unnecessary dependencies and intermediate files present in the image: compiler, test libraries, binary intermediate objects, etc. This isn't pleasant, and makes your docker image bigger.

#7115 is a proposal to offer a multi-step Dockerfile, which could solve this issue but introduce some significant complexity in Dockerfile syntax. Also, this is still discussed and I don't expect this to be implemented in a near future.

So, here's my way to handle such a Continuous Delivery Pipeline based on Dockerfiles.


Here is my "build phase" Dockerfile, which I name by convention Dockerfile.build :

FROM maven:3.3.3-jdk-8

ADD / /work
WORKDIR /work

ENV NODE_VERSION 4.2.2

RUN curl -SL "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" | tar xz -C /usr/local --strip-components=1 

RUN npm install -g bower gulp
RUN npm install
RUN bower --allow-root install
RUN gulp build
RUN mvn package

CMD cp /work/target/*.war /out/app.war

This Dockerfile do define my build environment, relying on Maven and NodeJS to build a modern java application. Such a Dockerfile is designed to fix the build requirements and offer an isolated, reproducible build script, not to create an actual docker image to be ran. But I also added a CMD, which role is to let me export the built binary to a pre-defined location. So I can run :

docker build -f Dockerfile.build -t build .
docker run -v $(pwd):/out build

I also tried to output the war to stdout, so I can run docker run build > app.war,  but got some odd extra character in the stream, and didn't investigated more. I could also rely on docker cp to extract binaries form a container created from build image.

Doing this, I'm building from source and after completion get the application binary for a further step. Next step is for me to create my deployment docker image, using Dockerfile.prod :

FROM jetty:9
ADD application.war /var/lib/jetty

And my full pipeline execution script become

docker build -f Dockerfile.build -t build .
docker run -v $(pwd):/out build
docker build -f Dockerfile.prod -t application .

I could just push the build application image to my repository, but can also have further steps to run it with required middleware (database, etc) and execute some additional automated tests.

For this purpose I rely on docker-compose, to setup the test environment and execute my test suite

test:
  build: .
  dockerfile: Dockerfile.tests
  links: 
    - application
    - selenium

selenium:
  image: selenium/standalone-firefox

application:
  image: application
  ports:
    - "80:8080"
  links:
    - database

database:
  image: mysql

Running docker-compose up will (build and) run my test suite based on selenium acceptance tests.

Last step is just to tag and push the image to my registry.

A future improvement is for me to find a cool way to integrate this in Jenkins as a declarative syntax, vs a plain shell script. Wait and see.

20 novembre 2015

DockerCon'15 Lego Moby Dock

I went to DockerCon Europe'15, and will post some feedback about this conference on this blog later next week, but in the meantime I'd like to share with you a major information from Docker Inc :

They updated the Lego Moby Dock design !

Last year at DockerCon Europe, they offered all keynote attendees a lego set to build a small docker whale. You could then pick up "containers" to plug on it from sponsors booth. Was lot's of fun.


At Barcelona, they did the same, but used a more advanced Moby Dock model, bigger and with rounded body. This one is another proof of nice Lego design expertise, but as the previous model I'm disappointed by the tail design. Due to it's shape and angle with whale body it's hard to find adequate lego brick for this job.



Back from Barcelona, I spent some time (don't tell my boss) searching in kid's legos for the adequate block. Here is the result :

  

Tail is a bit to big compared to original design, but looks better imho. As I wasn't able to find where to send a pull-request for this, here is the instructions for you to do the same.

You'll need those extra block :



  • Remove existing tail, drop the 2x1 plate you won't need. 
  • Plug the two roof tile 45° blocks (304023) into the special angular 1x1 brick (407023). One on the standard mounting hole, the other on the back, which on this brick is a square hole with adequate weight to plug a brick. 
  • Add the two opposite slopping block from original set to complete the tail.


I made a lego digital designer model as this isn't such a trivial thing to explain this :)



If you can't find the angle brick, you also can use a 1x1 brick with two round slots (4583862) and plug the upper tail in opposite side.

I also made larger containers, to mimic the Docker logo. They're a bit too large for the model, but look nice. Just need to get some profile 2x1 brick (4210636) for the adequate container look.


Building instruction is left as an exercise to the reader :)






06 novembre 2015

Learning Go (from Java)

Ca fait un moment que je me dis qu'il faut que j'apprenne à coder en Go.


Pourquoi ?

Déjà, pourquoi apprendre un autre langage ? 15 ans à faire du Java pour en comprendre les rouages et l'écosystème, pourquoi changer ? J'ai par exemple suivi le cours Scala sur coursera, qui m'a permis plus de comprendre les concepts fonctionnels que d'apprendre à faire du Scala, que je n'ai jamais pratiqué ensuite. Et voilà que Java 8 vient saupoudrer un peu de fonctionnel dans un langage objet impératif. Donc oui, connaître un autre langage aide à mieux appréhender les nouveautés et les différences entre langages, et donc ce qui et bien ou ce qui manque à notre langage de prédilection.

Pourquoi Go ? Go est à la mode, surtout depuis que le monde sait que Docker est fait avec. Mais ce n'est pas qu'un effet de mode. Go est un langage assez bas niveau, sans pour autant être aussi pénible que du C. Typiquement, il a un garbage collector. Il mixe donc des concepts plutôt bas niveau avec une approche moderne. Il n'a pas d'héritage mais uniquement de la composition et des interfaces. Go est donc un langage très opinionated et c'est ça qui m'intéresse. Les choix qui sont fait dans Go imposent une façon de concevoir le code, et c'est découvrir ce que cela implique qui m'intéresse.

Par contre, pour être significatif il faut avoir un projet sous le coude. Professionnellement ce n'est pas évident. Si on parle de Jenkins 2.0 il n'est pas pour le moment question de tout recoder en Go. Du coup j'ai pris un petit projet, le backend du système de vote du BreizhCamp, soit un serveur REST avec 5 endpoints. Le recoder en Go est un exercice concret sans nécessiter des jours de travail pour avoir un résultat.

Premiers pas

Commencez bien sur par "a tour of go", le tuto officiel de Go. Ca donne les bases et de premier petits exercices pour se faire à la syntaxe. 

Bon alors soyons honnête, quand on vient du monde Java, l'éditeur de texte vi on se sent un peu à poil avec. Donc pour la suite prenez tout de suite IDEA avec le plugin Go, ça vous simplifiera la vie et ça vous évitera des prises de tête.

Niveau littérature, il existe aussi plusieurs bouquins - dont des gratuits - qui sont très bien.

Première chose à noter dans Go, le langage vient avec un outillage assez complet : gestion de dépendance (même si elle est naïve), build, test, packaging. Pas besoin donc de réfléchir à quel outil de build utiliser. Ca permet de démarrer vite et de prendre pied rapidement dans un projet existant.

Deuxième chose que je note, Go se débarrasse de nombreux problèmes de formatage. D'une part gofmt gère l'indentation du code pour vous (et de manière intelligente), ensuite le compilateur ne vous laisse pas le choix et refuse certaines mises en formes (comme mettre l'accolade sur la ligne suivante). Les structures sont aussi prévues pour éviter les délimiteurs qui font merder vos commits : typiquement, en Java, quand on ajoute un élément à une liste, on modifie la ligne d'au dessus pour y ajouter un ','. En Go, soit il n'y a pas de délimiteur de fin de ligne, soit ce caractère doit être présent sur chaque ligne, même la dernière, supprimant ce "défaut". 

text := LinesOfText{
 []byte("Now is the time"),
 []byte("for all good gophers"),
 []byte("to bring some fun to the party."),
}

Le compilo fait aussi de l'inférence de type et tout ce genre de choses qui font de Go un langage peu verbeux comparé à Java, sans pour autant être un langage dynamique : la compilation vous rappellera à l'ordre, pas besoin d'attendre un crash en production. Et du coup IDEA vous propose également la complétion du code, et ça moi j'aime.

Enfin, la compilation Go est super rapide. Un cas d'usage très simple de Go, c'est pour le scripting : la compilation est tellement rapide qu'on peut écrire ses scripts en go et les lancer avec un go run truc.go. Ca permet de s'y mettre tranquillement, et potentiellement ce code pourra être regroupé et compilé dans un binaire portable qui vous servira de SDK interne.

Le compilo TGV c'est entre autre la raison pour laquelle la gestion des dépendances repose sur un bête git clone, recompillant donc tout à chaque fois (comme en Erlang d'ailleurs). Ca marche bien, mais on récupère donc le HEAD de chaque dépendance, pas une version bien identifiée. En termes Maven, tout est en SNAPSHOT :) On trouve donc des outils alternatifs, mais bon pour démarrer ce n'est pas un gros soucis, au pire vous aurez l'impression de faire du NodeJS... Go 1.6 devrait gérer des objets binaire par package, ce qui ouvre la voie pour une gestion un peu plus stricte.

Au fil des heures

Premier projet en Go pour moi donc, et j'ai pu plier ça en deux soirées, content du résultat. Les librairies standard de go sont bien foutues, ce qui me fait constater que le plus gros du travail d'un développeur Java est de trouver la lib qui marchera là ou le standard java.xx.yy est juste bon à jeter. Qui utilise java.util.logging - à part Jenkins, mais ça compte pas ? Ne soyons pas aveugle, c'est l'avantage d'un langage jeune, et avec le temps les même travers risquent d'apparaître. Cependant, le principe de Go - produire un binaire unique et autonome - permet de dégager du code obsolète, ce que tente de faire JigSaw depuis des années.

Bref, après quelques heures on a un truc qui fonctionne, on a donc atteint le niveau "je suis ok avec la syntaxe et les API de base". Parce que la syntaxe est pas complètement naturelle pour un dev Java, entre autre je bute encore régulièrement sur l'inversion de l'orde paramètre : type

J'ai donc un truc qui marche.

J'ai ensuite repris mon code morceau par morceau en utilisant des libs plus adaptées (drone/routes par exemple pour les services REST plutôt que du net/http standard). Il n'y a pas encore pléthore de librairies, tout en ayant du choix, c'est donc le bon moment pour s'y mettre sans se noyer dans la masse.

Là on découvre l'écosystème, on regarde le code des librairies qui nous apprennent plein de trucs qu'on ne connaissait pas. Clairement, une fois la barrière syntaxique franchie, lire le code des autres est un excellent moyen d'appréhender le langage. Au final mon code fait rapidement un "divisé par deux" et au passage plusieurs reprises structurelles pour corriger des erreurs de jeunesse. Autrement dis, je fais des progrès.



Enfin, j'ai voulu faire mon David Gageot en écrivant des tests (oui, le vrai David écrit ses tests en premier, mais bon hein ho). Là aussi, on a peu de librairies disponibles mais tout de même de quoi rendre les choses sympathiques.

Tester, c'est ici surtout l'occasion de découvrir les patterns Go pour rendre le code testable, dans un contexte ou nous n'avons ni programmation orientée objet, ni injection de dépendance, ni librairie de mock dynamiques. Et bien ça se fait plutôt bien :P Là la littérature disponible et divers blogs m'ont bien aidé pour expérimenter et comprendre les approches possibles. Et là ça fait du bien d'avoir un peu de bouteille parce qu'on reconnait tout de suite certains patterns d'autres langages/frameworks, et on connait leurs limites, donc on peut comparer/confirmer/se faire rapidement une opinion.



Objectif atteint donc à 100%
Note: oui, je met des images de beauf sur ce billet, vous plaignez pas j'aurais aussi bien pu poser en bikini.

Et donc ?

Bref, passer à Go n'a pas été très difficile, bien moins que mes heures de Scala, en rien à voir avec mes déprimantes tentatives en Ruby (sic). Evidemment j'ai un niveau Padawan 101, mais c'est déjà intéressant et ça m'encourage à pratiquer plus.

Vous l'aurez compris, si vous avez quelques heures de libre, je vous conseille de vous y mettre !









21 octobre 2015

First experiment with Tutum

I heard about Tutum from the time CloudBees was still a PaaS company and I considered them a newcomer competitor. I just read today announcement they have been acquired by Docker Inc, so wanted to know more. 




Tutum is actually not a PaaS but a deployment orchestrator and infrastructure manager you plug to your IaaS account(s). As I'm using Google Compute and this provider isn't supported, online help guided me to "bring your own node" option. This one installed an agent and immediately appeared connected on Tutum web UI.

First impression is important in IT for adoption, and Tutum do offer an awesome UX. Within few seconds I had my account setup and have found the adequate configuration informations. Need to admit they made an impressive work here.

So I have my infra setup and ready to host my app. Next step for me is to reproduce my environment, as I'm using docker-compose for local testing. 

Kubernetes or Amazon ECS both do offer the concept of running a set of containers as a single entity. Tutum has comparable concepts with Services (N replicas of a docker image) and Stacks (composition of services).  But all of them do rely on custom descriptor I would have to keep in sync and can't test locally. But according to announcement blog, Tutum also do support docker-compose so I could just use my existing setup, especially as my application does not require horizontal scaling nor replicas. 

After looking into details, Tutum stack syntax is actually the same (maybe a subset/superset ?) or docker-compose yaml syntax. 

So, I can see two significant benefits of Tutum :

1. no IaaS lock-in. I can rely on support Cloud providers or run my app on my own nodes, but still will benefit node management by Tutum. This looks to me like a real "private PaaS" i.e. my own hardware but still "as-a-service" experience.

2. same bits from dev to production. Both my docker image and stack definition are used on my development laptop and on my production service. So I can reproduce what happens on production at any time.

Need to experiment more, but looks very promising so far.


How to run 2500 webservers on a Raspberry Pi

If you didn't saw the announcement, I'm part of the winner team for DockerCon RPi Challenge. This blog post is about giving some details on our setup to get such a high number of webservers on a small device.

Some might thing you have to make your Docker image as small as possible, but this isn't actually the case. The image will result into space on disk for /var/lib/docker but not memory consumption. Also, a big process loaded into memory would only consume memory once, then kernel will share code page between equivalent processes, so hundred of them would only consume memory once. My first idea was to build a webserver to include the html and image content into source code. But then Yoann explained me sendfile can be used to fully delegate this to kernel and make the process even simpler. For Java developers, consider sendfile as some kernel-level IOUtils.copy(File, OutputStream).

We used hypriot's nano http image. This one is a webserver developped in assembly code to just serve files from disk using kernel sendfile call. Such a program as a minimal memory footprint and a 1-depth stack. The memory allocation for kernel to handle such a process can then be as compact as possible.

Next step was to run some tests and tweak Docker to run as much webservers as possible. We applied various strategies, without any methodology but just apply various recipes we had in mind and check the result (it takes hours to run thousand servers...)

Free memory

We tweaked the Raspberry and OS to reduce memory usage. Some low level tweaks allow to disable useless features at boot, some system level one are used to disable linux feature we don't need for this challenge.

Swap !

Yoann tried to explain me what zRAM is and I probably didn't got it right, but the general idea is that classic swap on disk is incredibly slow, and is only your last chance to free memory. A better, modern approach is to compress memory, which CPU can do very efficiently, a lot faster than accessing disk (especially on a RPi as disk is a SD card).

So our setup do use 5 zram 4 of them for swap (on per CPU, to allow concurrent access) + one for /var/lib/docker filesystem

What? Yes, we use a RamDisk for /var/lib/docker, even we did all those efforts to reduce memory usage... Main issue for this challenge is that running a test and start thousands containers takes hours. Having /var/lib/docker on the SD card made it terribly slow. If we had to get further on the challenge we would have used an external USB SSD disk.

Tweak docker command

Web servers are started by docker from a script. We selected docker options to reduce resource consumed by each web server. Especially, running with a a dedicated IP stack per container involve a huge resource usage, so a key hack was to run with --net=host. We also disabled log driver so docker don't have to collect logs and as such uses less resources. This seem to not work as expected (read later)

Tweak docker process

Linux also allows to tweak the way a process is managed in kernel, we used it to ensure docker run with minimal required resources and use swap

Tweak docker daemon config

Docker is ran by systemd on hypriot OS image, so we had to tweak it a few to unlock limitations. My naive understanding of Linux was that being ran as root, docker deamon could do anything. This isn't the case and it actually can't run more than few dozen processes with default configuration.

Docker daemon has many options we used to reduce it's memory usage.  Generally speaking we tried to disable everything that is not required to run a webserver with docker engine. logs, network, proxies. We expected this to prevent Docker daemon to run threads to collect logs or proxy signals to the contained processes.

2499 Limit

Then we hit the 2499 limit, with this in daemon.log :

docker[307]: runtime: program exceeds 10000-thread limit


Go language did introduce a thread limit to prevent misuse of threading. 10000 was considered enough for any reasonable usage. I indeed would not consider running so much thread a correct design, but here we hit such a limit because docker daemon do run 4 threads per container. It's not yet clear to me what those threads are used for. 

Using Go thread dump (SIGQUIT) I noticed some of them are related to logging, even we ran with --log-driver=none as an attempt to get further. I guess docker design here is to always collect then dispatch to "none" log driver which is NoOp, not to fully disable logging feature.

 So, 2499 is our best official score considering the RpiDocker Challenge rules.


More

We also wanted to know the upper limit. We made experiments running the plain httpd webserver without docker, and were able to run 27000 of them on the Raspberry. Docker daemon actually grows in memory usage and at some point as some bad impact on the system so you can't run more process. Please note this isn't relevant for arguments against docker on production system, until your business is to run thousands containers on a extra small server.

So, we hacked docker source code to force the MaxThread limit to 12000, built ARM docker executable and ran the script. We were able to run ~2740 web servers before we reach our first, real OOM

[21112.371259] INFO: rcu_preempt detected stalls on CPUs/tasks:

[21112.377124]  Tasks blocked on level-0 rcu_node (CPUs 0-3):

What's next ?

We'd like to better understand Docker threading model, and discuss this issue with docker core team. Using Non-Blocking IO might be an option to rely on a minimal set of threads. I have no idea yet how Golang do handle NIO, I just know it's a pain in Java so I wouldn't do it until I have good reasons to...