# Jenkins

# Установка

**Jenkins server, docker compose**

[Источник](https://www.cloudbees.com/blog/how-to-install-and-run-jenkins-with-docker-compose)

- Создать директорию jenkins\_compose ```bash
    mkdir jenkins_compose && cd jenkins_compose
    ```
- Создать compose файл ```
    nano docker-compose.yaml
    ```
- Скопировать в файл текст, сохранить и выйти ```
    services:
      jenkins:
        image: jenkins/jenkins:lts
        privileged: true
        user: root
        ports:
          - 8080:8080
          - 50000:50000
        container_name: jenkins
        volumes:
          - /home/${myname}/jenkins_compose/jenkins_configuration:/var/jenkins_home
          - /var/run/docker.sock:/var/run/docker.sock
    ```
- Запустить образ ```
    docker compose up
    ```
- С данной конфигурацией по [http://localhost:8080](http://localhost:8080) будет находиться web интерфейс. При первом старте в консоль будет выдан ключ инициализации, который нужно скопировать в web форму.
- Jenkins для обучения работает!

Для обучения на этом можно остановиться.

**Jenkins agent, docker compose**

- В директории jenkins\_compose создаем ключи ```
    ssh-keygen -t rsa -f jenkins_agent
    ```
- Перейти в Настроить Jenkins - Credentials

 [![jenkins_keys_1.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-02/scaled-1680-/jenkins-keys-1.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-02/jenkins-keys-1.JPG)

- Перейти в системное хранилище - глобальные параметры

[![jenkins_keys_2.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-02/scaled-1680-/jenkins-keys-2.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-02/jenkins-keys-2.JPG)[![jenkins_keys_3.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-02/scaled-1680-/jenkins-keys-3.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-02/jenkins-keys-3.JPG)

- Добавить способ авторизации со следующими настройками (ключ ввести вручную)

[![jenkins_keys_4.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-02/scaled-1680-/jenkins-keys-4.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-02/jenkins-keys-4.JPG)

- Теперь добавить в compose файл образ агента с открытым ключом ```
    services:
      jenkins:
        image: jenkins/jenkins:lts
        privileged: true
        user: root
        ports:
          - 8080:8080
          - 50000:50000
        container_name: jenkins
        volumes:
          - /home/${myname}/jenkins_compose/jenkins_configuration:/var/jenkins_home
          - /var/run/docker.sock:/var/run/docker.sock
      agent:
        image: jenkins/ssh-agent
        privileged: true
        user: root
        container_name: agent
        expose:
          - 22
        environment:
          - JENKINS_AGENT_SSH_PUBKEY=ssh-rsa...
    ```
- Почти все прошло по инструкции, кроме путей java и версии java. Второе было исправлено в compose (сейчас актуальная версия). А для установки корректного пути к JAVA нужно было найти в контейнере путь java ```bash
    sergey@sergey-VirtualBox:~$ docker exec -it 2b5036c4a35b /bin/bash
    root@2b5036c4a35b:/home/jenkins# env | grep JAVA
    JAVA_HOME=/opt/java/openjdk
    ```

И установить следующий путь в настройках агента: [![jenkins_keys_5.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-02/scaled-1680-/jenkins-keys-5.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-02/jenkins-keys-5.JPG)

- Агент поднялся!

# Jenkins -> k8s

[Видео по настройке взаимодействия](https://rutube.ru/video/fe8a5847f8201929ee2efcb828d5d220/)

[Описание плагина Kubernetes](https://plugins.jenkins.io/kubernetes/)

[Описание плагина Credentials](https://plugins.jenkins.io/credentials-binding/)

[Детальное описание Pod](https://devopscube.com/jenkins-build-agents-kubernetes/)

[Шпаргалка по k8s](https://wikival.bmstu.ru/doku.php?id=%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0_kubernetes#helm)

- Есть Jenkins вне кластера. Дополнительно установить плагин Kubernetes. Остальные нужные плагины подтянутся сами (Kubernetes client API, ...).

[![jenkins_k8s_1.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-02/scaled-1680-/jenkins-k8s-1.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-02/jenkins-k8s-1.JPG)

- Есть кластер k8s с доступным для Jenkins внешним адресом. Внутри кластера есть одна нода с доступом в Интернет. Доступ с ноды для приложенного pipeline критичен из-за скачивания исполняемых файлов, если эти файлы есть внутри кластера - все еще лучше.
- На кластере создаем namespace, пользователя jenkins, токен ```
    kubectl create namespace jenkins
    kubectl create sa jenkins -n jenkins
    kubectl create token jenkins -n jenkins --duration=8760h
    #здесь отобразится токен, его нужно сохранить, затем добавим в настройки Cloud
    kubectl create rolebinding jenkins-admin-binding --clusterrole=admin --serviceaccount=jenkins:jenkins --namespace=jenkins
    ```
- //еще не полностью понял// Под термином Cloud в Jenkins понимается поддерживаемые типы виртуализации/контейнеризации для создания динамических агентов. Т е авторизация и т д, настраиваемая в Clouds, используется только для создания динамического агента в соответствующем типе виртуализации и затем удаления его. Все. Агент создается пустой, все остальное нужно доделывать. При установке соответствующих плагинов (Docker, Kubernetes, Virtualbox) в списке появляются соответствующие типы облаков.
- Для использования в динамическом агенте настроим авторизацию. Настроить Jenkins - Credentials - System - Global credentials
- Выбрать тип Secret text, в поле Secret вставляем сохраненный токен, ID и Description обычно одинаковый.

 [![jenkins_k8s_2.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-02/scaled-1680-/jenkins-k8s-2.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-02/jenkins-k8s-2.JPG)

- Добавляем Cloud. Name это имя, любое. Kubernetes URL - адрес кластера, по которому Jenkins может подключиться. Credentials - созданный на предыдущем шаге.

[![jenkins_k8s_3.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-02/scaled-1680-/jenkins-k8s-3.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-02/jenkins-k8s-3.JPG)

- Справа есть кнопка Test connection Обязательно проверить соединение.
- Добавить стоит только адрес Jenkins сервера и Web Socket. Все остальное по умолчанию.

 [![jenkins_k8s_4.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-02/scaled-1680-/jenkins-k8s-4.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-02/jenkins-k8s-4.JPG)

- Настройка основы для динамического Jenkins клиента завершена.

Для работы с kubernetes нужен файл авторизации. Формат файла и настройки админа (для примера) можно посмотреть на кластере Kubernetes в

```
/etc/kubernetes/admin.conf
```

Сохраняем его в Credentials Jenkins и тип - файл. В данном случае ID textauth. [![jenkins_keys_6.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-02/scaled-1680-/jenkins-keys-6.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-02/jenkins-keys-6.JPG)

Важно, что рабочая директория Jenkins может (и скорее всего будет) отличаться от homedir пользователя

Pipeline:

```
pipeline {
  agent {
          kubernetes (kubernetesAgent(name: 'mini'))
  }
  
  stages {
    stage('Integrate Remote k8s with Jenkins ') {
      steps {
            sh "mkdir ~/.kube"
            withCredentials([file(credentialsId: 'textauth', variable: 'FILE')]) {
                sh 'cp $FILE ~/.kube/config'
                }
            sh "curl -LO 'https://dl.k8s.io/release/v1.32.2/bin/linux/amd64/kubectl'"
            sh "chmod +x kubectl"
            sh "./kubectl get nodes"
        }
    }
  }
}
```

# Разное

```
node('docker-agent-01') {
        stage ('Pulling repo and filling constants'){
            sh "rm *"
            git 'https://gitverse.ru/bobrobot/liteconnect_docker.git'
            withEnv(readFile('env.txt').split('\n') as List) {
                sh 'chmod +x replace_env.sh && ./replace_env.sh'
                }
            sh "cp env.txt .env"
    }
}
```

```
node() {
  stage('first') {
  withEnv(["PATH+HUIWAM=${HOME}/.local/bin"])
    {
        sh "printenv PATH"
    }
   sh "printenv PATH"
   }
}
```

```
withEnv([
    "PATH+EXTRA=/home/jenkins/.local/bin"])
{
    node() {
        stage('first') {
            sh "printenv PATH"
            }
    }
}
```

```
pipeline {
  agent {
            kubernetes (kubernetesAgent(name: 'mini'))
  }
  environment {
      PATH="${HOME}/.local/bin:${PATH}"
  }
  stages {
    stage('Integrate Remote k8s with Jenkins ') {
      steps {
            sh "printenv PATH"
             withCredentials([file(credentialsId: 'mysrc', variable: 'MYFILE')]) {
                sh 'cp $MYFILE new.sh'
                }
        }
    }
  }
  }
```

```
// для груви скрипта нужно упаковывать в withenv чтобы были видны определенные в скрипте параметры, 
//параметры из jenkins видны
//param_in_main - текстовый параметр,
//build_type - второй параметр. 
withEnv([
    'ENV1=It work ' + param_in_main, 
    'ENV2=ooo',
    'missingfname=thefilereallymissing.txt'])
{
    node('slave') {
        stage('first') {
            sh "mkdir ~/bin" 
            sh "printenv PATH"
            sh "echo $param_in_main" //обращение к параметру из параметров в jenkins
            sh "echo $ENV1" //обращение к составному параметру, определенному внутри скрипта
            sh "echo $ENV2" //обращение к независимому параметру внутри скрипта
            }
            
        stage('check type of pipeline'){
            if (build_type == 'prod') { //если проверяем вне sh - доллар не ставится
                sh "echo 'This is a prod'"
            }
        }
        
        stage('test exeptions'){
            try {
                sh 'rm $missingfname'
            }
            catch (exc) {
                echo 'Попытались удалить несуществующий файл ' + missingfname
            }
        }
        
        stage('check cycle'){
            sh 'mkdir "firstdir"'
            def fileNames = sh(returnStdout: true, script: 'ls').trim().split()
            for (item in fileNames) {
                echo "Processing item: ${item}"
                }
        }
    }
}
```

```
def buildPod = {
    def podYaml = """
kind: Pod
metadata:
  name: jenkins-agent
spec:
  containers:
  - name: my-jenkins-agent
    image: jenkins/inbound-agent:latest
    command:
    - cat
    tty: true
    volumeMounts:
    - mountPath: /var/run/docker.sock
      name: docker-sock
  volumes:
  - name: docker-sock
    hostPath:
      path: /var/run/docker.sock
"""
    return podYaml
}

def label = "jenkins-agent-${UUID.randomUUID().toString()}"

podTemplate(label: label, yaml: buildPod()) {
    node(label) {
        stage('Build') {
            container('my-jenkins-agent') {
                echo 'Start stage build'
                sh 'ls -al'
                echo 'End stage build'
            }
        }
        stage('Deploy') {
            container('my-jenkins-agent') {
                echo 'Start stage deploy'
                  try {
                    sh "rm my.txt"
                }
                catch(exc) {
                    echo "The ERROR!"
                    echo "${exc}"
                }
            }
        }
    }
}
```

# Интеграция Jenkins и GitVerse

**Настройка доступа в GitVerse**

Профиль -&gt; Управление токенами, создаем токен и сохраняем его

[![jenkins_gitverse_1.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-03/scaled-1680-/jenkins-gitverse-1.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-03/jenkins-gitverse-1.JPG)

**Добавляем токен доступ в Jenkins**

Home -&gt; Настроить Jenkins -&gt; Credentials Затем System -&gt; global credentials -&gt; Add credential

[![jenkins_gitverse_2.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-03/scaled-1680-/jenkins-gitverse-2.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-03/jenkins-gitverse-2.JPG)

Настройка доступа к GitVerse

Home -&gt; Настроить Jenkins -&gt; System

[![jenkins_gitverse_3.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-03/scaled-1680-/jenkins-gitverse-3.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-03/jenkins-gitverse-3.JPG)

Создаем в проекте Jenkinsfile

Создаем новый pipeline в Jenkins

[![jenkins_gitverse_6.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-03/scaled-1680-/jenkins-gitverse-6.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-03/jenkins-gitverse-6.JPG)

Устанавливаем github project

[![jenkins_gitverse_7.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-03/scaled-1680-/jenkins-gitverse-7.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-03/jenkins-gitverse-7.JPG)

В разделе Triggers установить GitHub hook trigger

[![jenkins_gitverse_8.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-03/scaled-1680-/jenkins-gitverse-8.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-03/jenkins-gitverse-8.JPG)

Устанавливаем тип Pipeline from SCM

[![jenkins_gitverse_9.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-03/scaled-1680-/jenkins-gitverse-9.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-03/jenkins-gitverse-9.JPG)

В первый раз сделать сборку вручную. После успешной сборки перейти в Settings пайплайна и нажать Save

Получилось собирать из Jenkinsfile в проекте, но webhook не поехал. Сервер снаружи виден. Поэтому пока оставим ручной запуск на исполнение.

# Ssh агент

<span style="color: rgb(224, 62, 45);">**SSH Agent plugin нахер в данном случае не нужен. Он необходим только для подключения внутри stage с существующего агента к другому серверу.**</span>

**Сервер, на котором будем выполнять команды:**

Добавить пользователя jenkins и добавить нового пользователя в группу sudo, docker (в случае моей задачи)

```
sudo adduser jenkins
sudo usermod -aG sudo jenkins
sudo usermod -aG docker jenkins
```

Авторизоваться на сервере под пользователем jenkins

Установить java

```
sudo apt update
sudo apt install fontconfig openjdk-17-jre
```

Создать приватный и публичный ключи для доступа к серверу по ssh пользователя jenkins.

```
  mkdir ~/.ssh && cd ~/.ssh
```

```
  ssh-keygen -t rsa -C "Access key for Jenkins slaves"
```

```
cat id_rsa.pub >> ~/.ssh/authorized_keys
```

Ключ из файла id\_rsa потребуется для настройки доступа Jenkins

**Jenkins web интерфейс:**

Настройки Jenkins -&gt; Credentials -&gt; System -&gt; Global credentials -&gt; Add credential [![jenkins_ssh_1.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-03/scaled-1680-/jenkins-ssh-1.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-03/jenkins-ssh-1.JPG)

В раздел ключ вставить текст из файла id\_rsa целиком (включая -----BEGIN... ------END...)

Перейти в Настроить Jenkins -&gt; Nodes и создать узел

 [![jenkins_ssh_2.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-03/scaled-1680-/jenkins-ssh-2.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-03/jenkins-ssh-2.JPG)

Параметры агента:

<table border="1" id="bkmrk-%D0%9F%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80-%D0%97%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D0%A3%D0%B4" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 31.131%;"></col><col style="width: 68.9882%;"></col></colgroup><thead><tr><td class="align-center">Параметр</td><td class="align-center">Значение</td></tr></thead><tbody><tr><td>Удаленная корневая директория</td><td>/home/jenkins/jenkins-agent</td></tr><tr><td>Метки</td><td>docker-agent-01</td></tr><tr><td>Host key verification strategy</td><td>Manually trusted key verification</td></tr></tbody></table>

[![jenkins_ssh_3.JPG](http://bobrobotirk.ru/uploads/images/gallery/2025-03/scaled-1680-/jenkins-ssh-3.JPG)](http://bobrobotirk.ru/uploads/images/gallery/2025-03/jenkins-ssh-3.JPG)

После настройки в узлах агент должен быть активен.

Тестовый pipeline

```
node('docker-agent-01') {
        stage ('second'){
            sh 'hostname'
    }
}
```

должен вывести хост агента.

В Jenkins текущая рабочая директория -

```
/home/jenkins/jenkins-agent/workspace/<имя pipeline>
```