Affichage des articles dont le libellé est jenkins. Afficher tous les articles
Affichage des articles dont le libellé est jenkins. Afficher tous les articles

21 septembre 2015

Introducing docker-slaves jenkins plugin

I was at DockerHackDay with Yoann on Thursday, and we implemented together a hack we had in mind for a while without time to actually work on it. So, 48 hours later we are proud to announce: 

Jenkins Docker Slaves Plugin

Why yet another Jenkins / Docker plugin ? Actually, there's at least 3 of them, including one I created last year, but all of them do rely on Docker as plain old virtual machines.



For this projet, we wanted to embrace Docker and the container paradigm. Don't run more than one process in a container. Have containers to communicate through links you explicitly setup. Rely on volumes for persistent data.

Docker Slaves plugin do workaround some Jenkins API that haven't been designed to manage Containers. 

The most obvious of them is the Cloud API, which uses a NodeProvisioner to determine when a new node is required, and when to shut it down. This API has been designed for virtual machines, as costly resources which are slow to setup and as such have to be kept online for few builds. Containers are lightweight, start in milliseconds, and there's no reason to reuse one vs create a fresh new dedicated one for another task. 



Another API mismatch is how Jenkins do launch commands on build executor. Jenkins do rely on the slave agent to some way run `System.exec()`. So Jenkins remoting act as a remote process executor. But what's Docker after all ? It's a remote process launcher (with some extra features) ! So we just bypass the Jenkins Remote Launcher to run a plain `docker run` from Jenkins master. In future, we could run this in detached mode, then Jenkins would not even need to stay online as the job is running, and could be restarted... 

Last but not least, there's no need to use the same container to run all commands. This actually prevent some plugin to apply new environment variables setup by build wrappers, or require some terrible hacks as a workaround. Our plugin is just launching a fresh new container for all command, so can setup the adequate environment. The UI does not (yet) offer this option, but one could imagine user can run some build steps with a docker image and some later steps with another one.

This also means running some background process as part of the build, which used to be a hack in build script, with various cleanup issues - Xvnc plugin, I'm looking at you - isn't necessary anymore. If you want to run Selenium tests, then just run a Selenium container side by side with your build container(s), and thanks to shared network setup you can run selenium tests without any extra configuration.




See the plugin repo README for more details, give it a try, and let you know how it goes !

14 septembre 2015

Moving my demo to Docker

Last Thursday I went to local Java User Group for the very first run of my new talk "(Docker, Jenkins) -> { Orchestrating Continuous Delivery }".

I've planned for this talk since june, but actually started to work on it on ... Tuesday, and got demo setup on Thursday in the morning :-\ As an expected result, the demo all failed, while the talk was mostly appreciated afaict.

How to make my demo more reproducible ? Hey, this is what the conference is talking about after all : setup reproducible build environment using Docker containers ! So let's use the same technique to host the demo itself.

The demo is using Cloudbees Jenkins Enterprise docker image, jetty to deploy built web apps, and docker registry to deploy docker images. I could run them by hand, but sounds better to rely on docker-compose to handle all the plumbing !

# Jenkins master, running on default http 80 port
jenkins:
  image: cloudbees/jenkins-enterprise
  ports:
    - "80:8080"
    - "50000:50000"
  volumes:
    # JENKINS_HOME, from host with pre-defined demo jobs
    - ./jenkins-home:/var/jenkins_home
    # Required host stuff so jenkins can run `docker` command to start containers
    - /var/run/docker.sock:/var/run/docker.sock
    - /usr/local/bin/docker:/usr/local/bin/docker
  volumes_from:
    # We "deploy" to jetty with a plain `cp`
    - webserver    
  links:
    - webserver
    - docker-registry
  user: jenkins:100 # 'docker' group, required to access docker.sock  

# Jetty web server to run tests, staging and production
webserver:
  image: jetty:9
  ports:
    - "8080:8080"
  volumes:
    - ./webapps:/var/lib/jetty/webapps

# Our private docker registry
docker-registry:
  image: registry
  ports:
    - "5000:5000"




The demo relies on a set of preconfigured jobs, so jenkin-home is bind mounted from the demo root directory. I had to configure bunch of .gitignore rules so I can share this config but not the build history and all other local jenkins stuff.

Webserver webapps directory could not be bind mounted, just relying on volumes, but then I get a permission error when Jenkins jobs tries to copy the war to jetty's volume. This could be fixed if we have #7198 resolved.

As the demo do run some docker tasks, I'm bind-mounting docker unix socket and cli executable in jenkins container, so it can build and start new containers. Docker Workflow plugin demo do use Docker-in-Docker for this, but I wanted to avoid using this hack (also read this). But a side effect is I need to configure the jenkins user with adequate permission so it can access the docker daemon socket, which means it has to be in the docker group. I'd like to use user: jenkins:docker, but the later doesn't work as --user do expect either a numeric ID, or user name for a declared user in the container, but not a host user/group name (I haven't found a related docker issue).

Last but not least, docker demo failed. I eventually understood the issue comes from bind mounted volumes.

JENKINS_HOME is set in jenkins container as /var/jenkins_home; this path is bind mounted from current directory /Users/nicolas/demo/jenkins-home. When docker-workflow creates as container to run continuous delivery pipeline steps inside containers, it tries to bind mount this exact same directory, but with my setup it does this on a side container (not a nested one, as in the original demo). As a result, this build container get some /var/jenkins_home/job/demo/workspace bind mounted, expecting to get there the project source files; but such a file doesn't exists on host, resulting in JENKINS-28821. This could be fixed if workflow can detect it's running inside a container, and uses --volume-from. I'll investigate such a fix. In the meantime, I've created a symlink on host as an ugly workaround.

Ok, so this was not such a trivial thing, and there's few things to get polished, but with this setup I now can share my demo, cleanup my environment with git clean -fdx, and get it up and running with a simple docker-compose up.

25 octobre 2012

POTD - extension filter plugin

Le point fort de Jenkins c'est son incroyable écosystème de plugins. Le système est entièrement bâti sur des points d'extensions et de nombreux composants qui viennent y contribuer.

Un soucis que je rencontre parfois chez des clients c'est qu'un plugin apporte une fonctionnalité intéressante, mais aussi une implémentation d'un point d'extension qui s'avère contre-productive dans un contexte spécifique.


Exemple avec JENKINS-15440 : le plugin subversion contribue au point d'extension "MailAddressResolver" en cherchant dans les projets SVN de l'instance si l'un d'eux pointerait vers sourceforge ou java.net, ce qui permet de déduire l'e-mail du committer. On sent l'idée initiale, mais sur une grosse instance Jenkins d'entreprise :

  1. le code n'est jamais sur sourceforge ou java.net. D'ailleurs de nos jours plus personne n'utilise ces services, ce code est donc purement là pour garantir la compatibilité
  2. ce parcours de tous les projets pénalise les performances sur une instance avec des centaines de jobs.

La solution ? Ne pas utiliser subversion et le plugin associé ! C'est d'ailleurs pour cela qu'on ne l'intègre pas dans Jenkins Enterprise - non je déconne, c'est à cause de la license de svnkit.

Il y a évidement plusieurs façons de corriger ce bug, mais en attendant j'ai pensé à un contournement qui s'applique à de nombreux autres cas. Ce genre de "fonctionnalité" n'a pas forcément de sens pour tout le monde, peut être pénalisante ou dangereuse selon l'utilisation qu'on a de Jenkins. Il existe pourtant un point d'extension qui permet de filtrer les extensions (attention, StackOverflowError en vue).

Comme "Project Of The Day" j'ai donc crée le plugin Extension Filter (whaou, mais où donc vais-je chercher tout ces noms super originaux ?) qui permet de configurer les extensions et descripteurs à désactiver sur une instance Jenkins.

Ce plugin permet donc d'alléger Jenkins des points d'extension que vous n'utilisez pas et qui peuvent pénaliser votre instance. Il permet aussi d'inhiber des composants selon leur contexte. Par exemple, retirer de la configuration globale hudson.plugins.mercurial.MercurialInstallation, pour empêcher vos utilisateurs de configurer Mercurial et les obliger à passer sous Git, ou bien interdire à hudson.task.Maven$DescriptorImpl de proposer un BuildStep dans les projets de type free-style, pour imposer l'utilisation de jobs maven. On peut même désactiver la configuration du plugin lui-même comme ça personne ne pourra plus changer la conf :)

Je vous laisse imaginer des cas d'usage un peu plus sérieux pour des éléments de configuration que vous considérez superflu ou "dangereux" pour vos utilisateurs.


08 octobre 2012

Large-Scale Automation with Jenkins

Pour la première journée de conférences de JavaOne (qui suit les keynotes du dimanche) j'attaque avec CON6256 - il y a tellement de conférences qu'organiser un planing est un challenge en soit !

Cette session, c'est tout simplement celle de mon collègue Kohsuke, sur l'utilisation avancée de Jenkins.  Il faut croire que je n'ai pas eu ma dose avec la JenkinsConf de la veille :P La salle est bien pleine, malgré l'heure matinale.

Kohsuke présentait donc en une heure l’utilisation de Jenkins pour l’automatisation du processus de développement, introduisant de manière progressive les plugins adaptés pour porter un « pipeline » complet.


En premier lieu, il présente les paramètres de job puis le parameterized build trigger plugin. Derrière ce nom à rallonge peu expressif se cache un plugin majeur qui permet de définir des jobs très génériques et de les chainer de manière efficace en jouant sur leurs paramètres. Après une rapide démo, Kohsuke présente le plugin join en insistant sur ses limites, utilisable uniquement pour les cas simples, et laissant le suspens pour la suite.

En jouant sur ces plugins, KK montre comment découper un job long en plus petits traitements plus faciles à paralléliser et à distribuer sur une infrastructure de machines « courantes ». Kohsuke présente ensuite la notion de promotion, utilisant cette fois le résultat du job comme déclencheur d’une promotion, qui active alors un processus de QA. Ce mécanisme permet de lier les jobs de deux équipes (Dévelopeurs et Qualiticiens) tout en laissant à chacun toute la liberté nécessaire sur la configuration du job.

Pour aller plus loin dans la mise en place d’un pipeline, KK aborde la problématique de la transmission d’un binaire entre jobs. Le plugin copy-artifact est présenté, il permet en effet de récupérer le binaire archivé par un job, sous sa forme de « dernier build stable » ou même de « résultat du build qui vient de déclencher ce job » (upstream). Il montre également l’utilisation des fingerprints pour identifier un binaire facilement dans l’instance jenkins et créer ainsi des références entre jobs sans configuration lourde. Kohsuke présente enfin le plugin maven-repository-server, qui transforme votre Jenkins en repository maven, permettant ainsi de faire facilement référence au binaire upstream de manière maven-compliant, ce qui est délicat avec le plugin copy-artifact. Je vous recommande également cet excellent plugin si vous ne le connaissez pas, afin de découper un job maven massivement multi-module comme certains les aiment en enchainement de jobs plus légers.
Petite anecdote : KK venait juste d’installer le plugin en question sur son instance de test avant le début de la session, ce qui amha était quelque peut risqué :). 

Afin de simplifier la configuration de la chaine de jobs qui commence à apparaître, KK présente le build-flow plugin, puis en fait une démo sans oublier de me faire un clin d’œil en passant mon nom comme paramètre du build.



J’apprécie la publicité gratuite, à moins que ce soit un encouragement pour que je prenne le temps pour faire avancer ce plugin dans le bon sens. Nous avons eu par la suite d’intéressantes discussions sur les possibles évolutions du plugin, tant en termes d’expérience utilisateur (validation du DSL) que d’extensibilité par d’autres plugins.
Kohsuke présente aussi le plugin Jenkow, déjà exposé à la JenkinsConf, qui utilise une approche différente, assynchrone à l’extrême, en déléguant tout le chainage des jobs à un moteur BPM. Avantage de ce plugin, la configuration du flux de jobs se fait en mode purement graphique dans Eclipse, puis le résultat est pushé dans jenkins via un repo git virutel. Idée intéressante à développer également pour le build-flow via l’introduction d’un fichier décrivant le DSL que l’IDE sait interpréter pour assister la saisie.

Enfin, Kohsuke aborde le problème de visualisation du résultat de tous ces jobs. Il présente d’une part la vue « project relationship » qui utilise les fingerprints pour tracer les relations entre job, ce qui peut devenir délicat avec un même binaire qui passe de job en job pendant les étapes du pipeline. Il présente également le plugin job dependency graph permettant de visualiser les liens entre jobs, et qui gère même les relations créées par le copy-artifact, puis le build-pipeline dont il fait une démonstration sur la base de son exemple précédent.



Le plugin build-flow comporte une tentative (pour l’instant pas très concluante) de visualiser les relations entre build, dans l’idée que deux exécutions successives peuvent faire intervenir des jobs très différentes - contrairement à ce que le build-pipeline présuppose. Je vais probablement extraire ce code dans un plugin dédié et le rendre générique. J'utilise pour l'instant jsPlumb qui permet de tracer simplement les liens entre jobs, et je regarde du côté de JGraphx pour l'algorithme de layout permettant de positionner les jobs -- s’il y en a parmi vous que cela intéresse et/ou qui connaissent bien le tracé de graphes acycliques orientés :) …

05 mai 2011

Hudson/Jenkins, episode V : l'empire contre attaque

Dans l'épisode précédent, Sonatype s'était allié à Oracle pour supporter Hudson, tandis que la rébellion s'organisait pour développer Jenkins avec le succès qu'on a pu constater.

Aujourd'hui, Oracle annonce vouloir donner Hudson à la fondation Eclipse (avec le soutien de Sonatype et VMWare), acceptant ainsi au final les conditions qui étaient réclamées par la communauté lors de la "crise" :
  • disposer d'un modèle de gouvernance sans prédominance d'une société
  • libérer le nom "hudson" de toute emprise en le léguant à un organisme indépendant

Ces conditions, à l'époque, se sont heurtées à un "non" sans appel de la part d'Oracle. Aujourd'hui, sans doute calmé par le succès de Jenkins fàce à un Hudson qui a du mal à exister autre part que sur le blog de Sonatype qui met en avant sa version "pro", Oracle change son fusil d'épaule.

On pourrait presque imaginer les deux branches fusionner à nouveau dans un grand moment de réconciliation, mais c'est assez peu probable.

D'une part, cette décision arrive bien tard. Jenkins a évolué depuis la scission, la communauté a pris ses aises et choisi son modèle de gouvernance. Il n'est pas du tout évident que celui de la fondation Eclipse soit aussi souple :P

D'autre part, la querelle avec Oracle a laissé des cicatrices; s'il ne s'agit pas de régler ses comptes, les principaux acteurs se voient mal travailler main dans la main comme si de rien n'était.

Enfin, passer le code de Hudson dans la fondation Eclipse ne se fera pas en deux minutes. Le processus d'incubation de la fondation est très strict (pour ne pas dire lourdingue), en particulier sur les aspects propriété du code et compatibilité des licences. C'est pour cela d'ailleurs que l'IDE Eclipse n'a pas de support SVN natif, l'implémentation Java SvnKit étant sous licence LGPL. Sans parler d'ailleurs du code pour lequel Oracle n'a pas a priori la propriété intellectuelle (pensez aux contributions de Kohsuke après qu'il ai quitté Oracle).

L'idée de voir Jenkins hébergé par la fondation Apache a été évoqué à un moment pour donner plus de visibilité au projet et lui assurer un cadre juridique solide. De la même façon, Jenkins devrait passer par l'incubateur Apache et résoudre les mêmes soucis de propriété intellectuelle et de licences.

Au final, cette contre-attaque est délicate à pronostiquer. Avec les moyens de Oracle + Sonatype + VMWare et la force de communication liée à l'aura de la fondation, Hudson peut rester sur les rails et progresser de manière intéressante. Dans le même temps, Jenkins démontre sa capacité à avancer vite et bien, avec :

  • un nouveau processus de release à deux vitesses, avec une version "stabilisé" par tranche de 3 mois n'incluant que les corrections majeures
  • plus de soin dans la gestion de la compatibilité, avec un mécanisme de test des plugins sur la version N+1 (action menée par notre compatriote Frédéric Camblor)
Il nous reste à attendre le prochain épisode. Je ne pense pas que le Jedi veuille bien revenir pour détruire l'étoile noire, et les deux outils continueront probablement à vivre côte à côte pendant longtemps. En tout cas, nous aurons assisté à un formidable gâchis depuis l'intervention de l'empire et de son allié dark vador (je vous laisse mettre des noms en fàce par vous même).

01 février 2011

Hudson et Jenkins sont dans un bateau ...

C'est chose faite, la communauté des développeurs Hudson a choisi de quitter définitivement Oracle et de forker / renommer (tout dépend du point de vue) le projet en Jenkins (http://www.jenkins-ci.org).



Les choses sont déjà suffisamment compliquées, voici que Sonatype prend position et apporte son soutien ... à Oracle Hudson :
"

One problem that we've encountered frequently in the past with Hudson
is stability after upgrades.  

This will be one of the areas of primary focus for Sonatype and when the rename happens 
today we will begin the process of merging most of our stabilization work back to Hudson. 
`This will take a bit of time because we stepped off the train to decide how and who we 
wanted to continue working with. I think this whole situation is unfortunate, but ultimately 
Kohsuke has the right, like everyone else, to do what he feels is right. I honestly do not 
believe what has happened is in the best interest of users, but this is my opinion and only 
time will tell.

If anyone is interested in the work to be done on Hudson the java.net lists should be up, the 
@hudsonci twitter account will be very active, and I'll have a series of blog posts about the 
work Sonatype is planning to contribute, a critique of the current architecture, and proposed 
roadmap. While I'm sure we're not going to be very popular in the short term, continuing the 
Hudson with Oracle is what we feel is best. Our goals and motives have not changed since 
the first time I posted about Sonatype's potential involvement. We care about the IP, the 
provenance of the code, the stability of the core, helping to create a new architecture while 
maintaining backward compatibility, create great Maven integration and create a commercial 
product. We've done a lot of work for enterprise users and we hope to share this with the 
Hudson community as soon as we can.

I believe it is truly regrettable what has happened, but life goes on and I'm sure both projects 
will do well catering to their users.

"

Jason met le doigt sur un élément clé : la stabilité et l'architecture de Hudson. C'est un critère important pour son utilisation en entreprise sur des projets stratégiques. Il faut reconnaitre que le modèle de développement de Hudson est particulièrement ouvert et manque parfois d'un cadre strict. Cela n'a pas empêché le projet de progresser très vite et de s'enrichir de fonctionnalités avancées, et ça a toujours été une volonté affichée pour réduire au minimum la barrière de contribution. Par contre, ça peut ne pas rassurer un DSI (vous me direz, c'est le même qui a commandé des licences Websphere 7, mais bon ...).

L'offre Sonatype Profesionnal intègre un Hudson validé et supporté ("Matrix"), il ne fait donc aucun doute que Sonatype a des évolutions techniques à proposer pour stabiliser et améliorer le projet. Devant le vide laissé par le départ de la communauté des développeurs pour Jenkins, ils vont ainsi se retrouver premier contributeur au côté d'Oracle, une place de project-lead inespérée.

Evidemment, rien n'est gagné : la communication autour du changement de nom a été large et Jenkins va continuer d'avancer au rythme qu'on lui connait. D'un autre côté, les clients d'Oracle ou de Sonatype seront sensibles à l'argumentaire de qualité technique et de stabilité d'un élément clé de leur forge logicielle. Sonatype va donc devoir mettre les bouchées doubles pour démontrer une plus-value et sa capacité à améliorer Hudson. Jenkins étant contraint de conserver les APIs existantes, les nombreux plugins ne sont pas remis en cause (dans l'immédiat), aussi Sonatype va pouvoir se focaliser sur le coeur Hudson et sur une intégration Maven 2/3 particulièrement poussée. Le niveau technique des développeurs ne fait aucun doute, tout va donc se jouer dans le timing et l'art de communiquer auprès de la communauté d'utilisateurs.

Pas facile de prédire ce que cela va donner... en espérant que ça ne va pas tourner au troll "audit de code" ou que sais-je pour démontrer qu'un projet est techniquement supérieur à l'autre.

On vit une époque formidable.