jenkinsci/docker-swarm-plugin

Documentation?

Closed this issue · 10 comments

Thanks for the plugin guys but... how does one use this? Is there some documentation or simple examples? i.e. how do i deploy my own image to a machine in the docker swarm? A couple of Jenkinsfile examples would go a long way. A blog post even!

The documentation is the readme in this git repository. It is like any other cloud provider. Setup a label that jenkins shoudl listen for and in the cloud (swarm) provider, setup what docker image it should use. Feel free to point out where exactly you are hanging. From Jenkinsfile perspective, all you need is just a node ('<label>') where the label matches your setting in the cloud provider in Jenkins.

Yeah, sorry, where are the documents for "any other cloud provider" in Jenkins? I haven't used any other cloud providers with Jenkins, i'm working on premises and only have Docker Swarm, so you are saying i have to have experience with "any other cloud provider" in order to understand how to use this? How do i target a specific node in the swarm, how do i add a label to it? From what I gather you can't. When you say "setup what docker image it should use" what do you mean? Use for what? A pipeline? I can only have one image per swarm setup? you must mean something else, but what?

A few example Jenkins files might help. i.e. how to run a pipeline (or a step of one) in the swarm. Perhaps how to target specific resources in the swarm i.e. GPU machine etc

In the readme, there is:

The configuration options can be found at /configure (Configure System).

and

Next you need to add one or more agent templates. Make sure to set a label. A build requiring this label will run in a container spawned by the plugin.

Which pretty shortly describes what needs to be done.
Have you had a look at the configuration? I think it is more or less self explanatory.

I can try to explain the whole swarm concept in other words:

The idea of this plugin is that you connect Jenkins to one of the Docker Swarm Managers. After that, you define one or more Docker Agent Templates. That means, you define a label and a Docker Image (and some more metadata if wanted, like reservations). All that configuration is done in Manage Jenkins -> Configure System. After that is setup, any build that requires one of the labels defined in one of the Docker Agent Templates (in a pipeline for example with the following: node ('<label>')) will spin up the defined Docker Image and inject the Jenkins Agent jar and automatically connect it to the ``Jenkins Master`. The agent will then perform what is defined for that node and after that, destroy the container and therefore remove this temporary agent.

Does that make it more clear how it fundamentally works?

Ok, Thanks, that helps a lot,

I've setup it up and can see my swarm in the Docker Swarm Dashboard, but under Manage Nodes there is nothing because, if i follow you correctly, they are created dynamically.

But what I'm try to get at is what this plugin does not do. So you can't target specific machines in your cluster the whole swarm has only one label and any steps in a pipeline will be randomly assigned to a machine in the swarm?

It is correct that you don't see any nodes if nothing is running.
No, not the swarm has one label but each Image (Docker Agent Template) has a label. And if a job requests a node with a label, it will create an agent and run all the steps inside that node on that dynamic agent.
Here is an example:

node ('xxx-builder') {
    <steps for build>
    <steps for unit tests>
    <steps for package>
}
node ('xxx-runner') {
    <steps for deploy>
    <steps for integration tests>
}

This will first request a node that runs the Docker Agent Template with the label xxx-builder which obviously should contain all tools needed for building. Then it will run the steps for building, unit-tests and package on that dynamic node. After those steps, the node will be deleted.
Next it requests a node that runs the Docker Agent Template with the label xxx-runner which should contain everything that is needed to deploy and run the built application in the previous node.
Then it will deploy the application on that node and run the integration tests and then delete that node as well.

In general you do not care what specific machine is used (that is the idea behind a swam) so the swarm itself figures out where to deploy a Docker Service (a container running a specific image) best.
In case you really want to define exactly where a Docker Agent Template should run, you can define labels inside the Docker Swarm and use the Placement -> Constraints in the Docker Agent Template to define what Docker Swarm label that Image should use.

OK,
So to make sure i have this straight:

  1. Define a so called Docker Agent Template[DAT] which is a special Docker image with the Java Web Start (JNLP) in it + specifics for your building. This is setup in the Manage Jenkins -> Configure System which implies that one can not run any image you want on the agent/node via the Jenkins file it must be pre-configure beforehand which means you have configuration in both the Jenkins admin and the Jenkins file :(
  2. You define an agent in the pipeline/stage/step with the label of one of the DATs which then get deployed to an arbitrary node in the docker swam. Thus the assumption is that the swarm is homogeneous in terms of compute. Otherwise your saying the Docker Swarm labels can be used in the DAT setup (can't find any documentation on this anywhere?) somehow to target specific compute.

In my case I'm trying to develop a machine learning pipeline so the location of execution is very important as some machines in the swarm have GPU and others (i.e. the master) does not. With a small number of nodes (we have 4) it would seem like docker swarm is not the way to go and the more traditional Jenkins agent setup would be more flexible as I can setup node labels directly and run any docker image i define in the pipeline > agent? (I'm not sure about this last part as i haven't tried it). Or perhaps it just easier to run docker service create ... commands directly in the Jenkinsfile steps so at least i can use docker-compose files and deploy > placement > constraints normally...?

Thanks again for the explanation. Its made things much clearer!

Now we're getting close :) Although a few notes:

Define a so called Docker Agent Template[DAT] which is a special Docker image with the Java Web Start (JNLP) in it + specifics for your building.

Almost, the JNLP is not needed there, this will automatically be downloaded and run with the default command in the DAT. Only make sure that a compatible java runtime is installed in the Docker Image.

... which implies that one can not run any image you want on the agent/node

Yes, that is the idea behind a dynamic slave: You define the label and builds using that label use the defined image.

You define an agent in the pipeline/stage/step with the label of one of the DATs which then get deployed to an arbitrary node in the docker swam. Thus the assumption is that the swarm is homogeneous in terms of compute. Otherwise your saying the Docker Swarm labels can be used in the DAT setup (can't find any documentation on this anywhere?) somehow to target specific compute.

That is partially correct. You can have different nodes in the swarm. Lets say you have a node A with 8 cpus and a node B with 2 cpus. If you now want to run a build that approximately needs 2 cpus, you can set the cpu reservations in your DAT to 2000000000 (which equals 2 cpus). Now if you run multiple builds in parallel with that label, the Swarm will distribute max. 4 builds to the node A and max. 1 build to the node B. The same can be done with memory. If you do need to use a specific node for a specific build, you can use the placement constraints. So for example you add the Docker label gpu=yes to one of the Swarm nodes. You then define a Jenkins label and add the constraint node.labels.gpu==yes into the placement. Then a build using that Jenkins label will only be run on a node with that Docker label.

So in your case, it really depends. If you have only two different build types (one with GPU and one without), it would mean defining two DATs and using the labels from those two in your Jenkinsfile. If you have dozens of different build images you need to use, it might be easier to directly use Docker commands and hard-wire the 4 agents into the Jenkins master instead of dynamically creating them.

Thanks man, you've been awesome!

I would not want to steal the show here, but I would also like to get more data on the Documentation, especially on how to mount volumes. I have need to mount one NFS mount with all the slaves, and it seems to be more difficult than I expected, if I use "host binds", it will always take on the "bind", not "volume" option, any glues how to do it?

yeah, volumes in any virtualized network setup is a nightmare... but it is a bit off topic.