Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jenkins persistent home support via "volumes-from" #8

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions mesos/jenkins/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ RUN chmod a+x /usr/local/bin/connect-slave.sh
COPY jenkins.sh /usr/local/bin/jenkins.sh
RUN chmod a+x /usr/local/bin/jenkins.sh

COPY gitconfig $JENKINS_HOME/.gitconfig
RUN chown jenkins:jenkins $JENKINS_HOME/.gitconfig

ENV REF_DIR /usr/share/jenkins/ref
ADD defaults.tgz $REF_DIR
COPY plugins.txt $REF_DIR/
Expand Down
2 changes: 1 addition & 1 deletion mesos/jenkins/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ MARATHON ?= localhost:8080
.PHONY = install push deploy clean

defaults.tgz:
tar zcvf $(@) *.xml init.groovy.d/
tar zcvf $(@) *.xml gitconfig init.groovy.d/

install: defaults.tgz
docker build -t $(TAG) .
Expand Down
25 changes: 21 additions & 4 deletions mesos/jenkins/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@

# Jenkins on Mesos

Jenkins is deployed on Mesos using a Docker image deployed through Marathon. The image contains some basic configuration and an init script that produces a fully-functioning server, including connected build slaves, OOTB.

### Building the image
## Building the image

First check out the source from GitHub so you can modify the base config to suit your deployment scenario:

Expand Down Expand Up @@ -31,7 +32,7 @@ JWiPlEoKa1Z3c

Replace the string "4Dm3fH39Geavs" in the `Dockerfile` with the output from the `openssl passwd` command.

#### Build
### Build

```
$ TAG=jenkins make clean install
Expand All @@ -51,13 +52,29 @@ Step 1 : FROM jenkinsci/jenkins:2.8
...
```

### Deploying the image
## Deploying the image

The image is deployed to Mesos with Marathon. An example `marathon.json` file exists in the source repository.

The main value to change in the `marathon.json` is the env var `JENKINS_CONFIG_REPO`, which should be set to an `org/repo` where the Jenkins configuration will be backed up. If using an existing repository, know that once the Jenkins server is running, you'll have to visit the configuration page and reload everything from SCM using the provided link.

#### SSH keys

### Running localy on marathon 127.0.0.1

Run ```make deploy```

### Running on remote marathon (other than 127.0.0.1)

As soon as a jenkins installation with all required plugins can crash sometimes, and running on remote marathon leades to unpersistent jenkins home directory. To make the system tolerant to jenkins restart several tricks should apply.

1 Edit ```marathon-remote.json.example``` to replace {{PERSISTENT_SLAVE_IP}} with IP of the mesos slave to use.
2 Edit ```marathon-remote.json.example``` to replace {{PERSISTENT_SLAVE_PORT}} with port number you want to use to mke URL PERSISTENT.
3 Connect with ssh to the slave you want to use for jenkins and create data only container ```jenkins-data``` with ```docker run -d -v /home/jenkins_home:/var/jenkins_home --name=jenkins-data --entrypoint=/bin/echo alpine "jenkins data-only container"```
4 Edit ```marathon-remote.json.example``` to replace {{JENKINS_DATA_CONTAINER}} with jenkins-data
5 Replace ```marathon.json``` with ```marathon-remote.json.example```


### SSH keys

Note that the provided JSON assumes that slaves have a user dedicated to Jenkins named `jenkins` and that a valid SSH key (that can access source repositories on GitHub) is contained in a `.tar.gz` file located in `/home/jenkins/` and named `ssh.tar.gz`. This file will be copied into the Jenkins server's `/var/jenkins_home` directory and will be used as the SSH key when syncing configuration and checking out source code.

Expand Down
2 changes: 1 addition & 1 deletion mesos/jenkins/connect-slave.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash
curl -sSL -XPOST -H "Content-Type: application/json" -d @- "http://marathon.mesos:8080/v2/apps" <<END
{
"id": "/jenkins/build/$3",
"id": "/jenkins/slaves/$3",
"cpus": 1,
"mem": 8192,
"instances": 1,
Expand Down
27 changes: 20 additions & 7 deletions mesos/jenkins/jenkins.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,29 @@ copy_reference_file() {
: ${JENKINS_HOME:="/var/jenkins_home"}
export -f copy_reference_file
touch "${COPY_REFERENCE_FILE_LOG}" || (echo "Can not write to ${COPY_REFERENCE_FILE_LOG}. Wrong volume permissions?" && exit 1)
echo "--- Copying files at $(date)" >> "$COPY_REFERENCE_FILE_LOG"
find /usr/share/jenkins/ref/ -type f -exec bash -c "copy_reference_file '{}'" \;

sed -i "s#\${JENKINS_CONFIG_REPO}#$JENKINS_CONFIG_REPO#g" $JENKINS_HOME/scm-sync-configuration.xml
cp -R $MESOS_SANDBOX/.ssh $JENKINS_HOME/.ssh
if [ "x$USE_PERSISTENT_JENKINS_HOME" == "x" ]; then
rm -f $JENKINS_HOME/.USE_PERSISTENT_JENKINS_HOME
echo "--- Copying files at $(date)" >> "$COPY_REFERENCE_FILE_LOG"
find /usr/share/jenkins/ref/ -type f -exec bash -c "copy_reference_file '{}'" \;
sed -i "s#\${JENKINS_CONFIG_REPO}#$JENKINS_CONFIG_REPO#g" $JENKINS_HOME/scm-sync-configuration.xml
cp -R $MESOS_SANDBOX/.ssh $JENKINS_HOME/.ssh
elif [ ! -f $JENKINS_HOME/.USE_PERSISTENT_JENKINS_HOME ]; then
echo "--- Copying files at $(date)" >> "$COPY_REFERENCE_FILE_LOG"
find /usr/share/jenkins/ref/ -type f -exec bash -c "copy_reference_file '{}'" \;
sed -i "s#\${JENKINS_CONFIG_REPO}#$JENKINS_CONFIG_REPO#g" $JENKINS_HOME/scm-sync-configuration.xml
cp -R $MESOS_SANDBOX/.ssh $JENKINS_HOME/.ssh
touch $JENKINS_HOME/.USE_PERSISTENT_JENKINS_HOME
fi

if [ [ ! -f $JENKINS_HOME/.gitconfig ] -a [ -f $JENKINS_HOME/gitconfig ] ]; then
mv -f $JENKINS_HOME/gitconfig $JENKINS_HOME/.gitconfig
fi

# if `docker run` first argument start with `--` the user is passing jenkins launcher arguments
if [[ $# -lt 1 ]] || [[ "$1" == "--"* ]]; then
eval "exec java $JAVA_OPTS -jar /usr/share/jenkins/jenkins.war $JENKINS_OPTS \"\$@\""
fi

else
# As argument is not jenkins, assume user want to run his own process, for sample a `bash` shell to explore this image
exec "$@"
exec "$@"
fi
88 changes: 88 additions & 0 deletions mesos/jenkins/marathon-remote.json.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
{
"id": "/jenkins/master",
"cmd": null,
"cpus": 2,
"mem": 4096,
"disk": 0,
"instances": 1,
"constraints": [
[
"hostname",
"CLUSTER",
"{{PERSISTENT_SLAVE_IP}}"
]
],
"container": {
"type": "DOCKER",
"volumes": [
{
"containerPath": "/var/run/docker.sock",
"hostPath": "/var/run/docker.sock",
"mode": "RW"
}
],
"docker": {
"image": "jenkins-mesos-local",
"network": "BRIDGE",
"portMappings": [
{
"containerPort": 8080,
"hostPort": {{PERSISTENT_SLAVE_PORT}},
"servicePort": 10002,
"protocol": "tcp",
"labels": {}
},
{
"containerPort": 0,
"hostPort": 0,
"servicePort": 10003,
"protocol": "tcp",
"labels": {}
}
],
"privileged": true,
"parameters": [],
"forcePullImage": false,
"parameters": [
{ "key": "volumes-from", "value": "{{JENKINS_DATA_CONTAINER}}" }
]
}
},
"env": {
"JENKINS_CONFIG_REPO": "jbrisbin/jenkins-mesos-softlayer",
"JENKINS_OPTS": "--prefix=/jenkins",
"USE_PERSISTENT_JENKINS_HOME": "yes"
},
"healthChecks": [
{
"path": "/jenkins/",
"protocol": "HTTP",
"portIndex": 0,
"gracePeriodSeconds": 300,
"intervalSeconds": 300,
"timeoutSeconds": 300,
"maxConsecutiveFailures": 25,
"ignoreHttp1xx": false
}
],
"portDefinitions": [
{
"port": 10002,
"protocol": "tcp",
"labels": {}
},
{
"port": 10003,
"protocol": "tcp",
"labels": {}
}
],
"fetch": [
{
"uri": "file:///home/jenkins/ssh.tar.gz",
"extract": true,
"executable": false,
"cache": false
}
]
}