Oct 18 2020
Enregistrer un Slave Jenkins avec Ansible
Nous avons vu précédemment comment ajouter un esclave Jenkins en appelant une API REST avec Curl. Automatisons ceci avec Ansible pour avoir un nouveau noeud disponible en quelques minutes!
Vous aurez tout d’abord besoin d’un utilisateur Jenkins et son token associé avec les bons droits. « Agent connect » et « create » devraient suffire. J’appellerai cet utilisateur « node » tout simplement. Connectez-vous sur Jenkins avec cet utilisateur et créez un nouveau token.
Les détails du nouveau noeud doivent être passés à l’URL REST. Intégrons ces paramètres dans un template Jinja2 comme ceci:
{
"name": "{{ jenkins_node }}",
"nodeDescription": "slave {{ jenkins_node }}",
"numExecutors": "{{ jenkins_numExecutors }}",
"remoteFS": "{{ jenkins_remoteFS }}",
"labelString": "{{ jenkins_label }}",
"mode": "EXCLUSIVE",
"": [
"hudson.slaves.JNLPLauncher",
"hudson.slaves.RetentionStrategy$Always"
],
"launcher": {
"stapler-class": "hudson.slaves.JNLPLauncher",
"$class": "hudson.slaves.JNLPLauncher",
"workDirSettings": {
"disabled": true,
"workDirPath": "",
"internalDir": "remoting",
"failIfWorkDirIsMissing": false
},
"tunnel": "",
"vmargs": ""
},
"retentionStrategy": {
"stapler-class": "hudson.slaves.RetentionStrategy$Always",
"$class": "hudson.slaves.RetentionStrategy$Always"
},
"nodeProperties": {
"stapler-class-bag": "true",
"hudson-slaves-EnvironmentVariablesNodeProperty": {
"env": [
{
"key": "JAVA_HOME",
"value": "{{ java_home }}"
}
]
},
"_comment:": {
"hudson-tools-ToolLocationNodeProperty": {
"locations": [
{
"key": "hudson.model.JDK$DescriptorImpl@JAVA-8",
"home": "/usr/bin/java"
}
]
}
}
}
}
Adaptez le modèle selon vos besoins, si vous souhaitez un agent SSH par exemple.
Les variables qui vont être remplacées dans le template peuvent être définies dans le fichier « default » suivant:
jenkins_slave_user: jenkins-slave
jenkins_token: xxxxxxde2152xxxxxxaa339exxxxxx48d6
jenkins_user: node
jenkins_url: https://jenkins.domain.lan
jenkins_node: "{{ansible_hostname}}"
jenkins_numExecutors: 4
jenkins_remoteFS: /home/jenkins-slave
jenkins_label: "label_1 label_2 label_3"
java_home: /usr/lib/jvm/java-8-openjdk-amd64/
jenkins_user se connectera au master et créera le nouveau noeud, en s’authentifiant avec le jenkins_token créé précédemment.
jenkins_slave_user est l’utilisateur système qui lancera le service Jenkins sur le node.
Nous pouvons maintenant ajouter une tâche Ansible à notre rôle. Nous appelons tout d’abord l’API REST:
- name: création du noeud sur le maître Jenkins
uri:
url: "{{jenkins_url}}/computer/doCreateItem?name={{ jenkins_node }}&type=hudson.slaves.DumbSlave"
method: POST
body_format: form-urlencoded
force_basic_auth: yes
user: "{{ jenkins_user }}"
password: "{{jenkins_token }}"
body: "json={{ lookup('template', 'node.json.j2', convert_data=False) }}"
return_content: yes
status_code: 200, 302, 400
register: webpage
J’ai ajouté le code de retour 400 au cas où le noeud existe déjà mais vous pouvez l’enlever si vous préférez que ca s’arrête dans ce cas. Je le passe en échec si l’erreur n’est pas ‘already exists’:
- name: continue au cas où l'agent existe déjà
fail:
when: >
webpage.status == '400'
and 'already exists' not in webpage.x_error
Le service agent Jenkins a besoin d’une clé du master pour démarrer. La clé est disponible dans la page de l’agent au format XML.
- name: récupération du contenu de la page de l'agent
uri:
url: "{{jenkins_url}}/computer/{{jenkins_node}}/slave-agent.jnlp"
method: POST
body_format: form-urlencoded
force_basic_auth: yes
user: "{{ jenkins_user }}"
password: "{{ jenkins_token }}"
return_content: yes
status_code: 200
register: slavepage
- name: récupération de la clé contenu dans le xml
xml:
xmlstring: "{{slavepage.content}}"
xpath: /jnlp/application-desc/argument
content: text
register: secretxml
La clé sera stockée dans le fichier /etc/default/jenkins-slave de l’utilisateur système qui est chargé au démarrage du service.
En voici le template:
JENKINS_USER="jenkins-slave"
JENKINS_WORKDIR=$(eval echo "~$JENKINS_USER")
JENKINS_URL={{ jenkins_url }}
JENKINS_NODENAME=$(hostname)
JENKINS_SECRET={{ jenkins_secret }}
JAVA_ARGS="-Xmx6g"
Ajoutez l’init script. Nous pouvons maintenant copier ces 2 fichiers:
- name: copie du fichier de paramètres de jenkins-slave
template:
src: jenkins-slave-default.j2
dest: /etc/default/jenkins-slave
owner: jenkins-slave
group: jenkins-slave
mode: 0600
vars:
jenkins_secret: "{{secretxml.matches[0].argument}}"
register: jenkins_config
- name: Copie de l'init script jenkins-slave
copy:
src: jenkins-slave-init
dest: /etc/init.d/jenkins-slave
owner: root
group: root
mode: 0755
Et nous nous assurons que le service est bien démarré:
- name: redémarrage et activation du service jenkins-slave si besoin
service:
name: jenkins-slave
enabled: yes
state: restarted
when: jenkins_config.changed
- name: démarrage et activation du service jenkins-slave
service:
name: jenkins-slave
enabled: yes
state: started
Ces étapes sont la base mais vous pouvez faire bien plus comme ajouter la création de l’utilisateur système Jenkins, ajouter votre propre autorité de certification si vous êtes sur une IP privée, et bien plus.
Voyez aussi comment accélérer Ansible et optimiser vos temps de déploiement.