Oct 18 2020
Ajout d’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é peut être trouvée 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