Розбіжності

Тут показані розбіжності між вибраною ревізією та поточною версією сторінки.

Посилання на цей список змін

Порівняння попередніх версій Попередня ревізія
Наступна ревізія
Попередня ревізія
devops:jenkins [14/11/2025 22:56] osvexdevops:jenkins [14/11/2025 23:00] (поточний) osvex
Рядок 1: Рядок 1:
-Гаразд, це чудова ідея. Зберегти фінальну, робочу конфігурацію як "шпаргалку" — це найкращий спосіб закріпити знання.+====== Автоматизація деплою стеку моніторингу за допомогою Jenkins + Ansible + Git ======
  
-Оскільки ви будете використовувати DokuWiki, я підготую статтю, використовуючи її синтаксис (він дуже схожий на Markdown, але з деякими відмінностями, особливо у заголовках та кодових блоках).+Ця стаття — шпаргалка з налаштування безпечного CI/CD пайплайну "Push-to-Deploy".
  
-Ось готова стаття-шпаргалка, яка описує **тільки** наш фінальний, професійний сетап.+**Мета:** Автоматично оновлювати та перезапускати Docker Compose стек моніторингу на сервері щоразу, коли відбувається git push у main гілку.
  
 ----- -----
  
-## (Скопіюйте цей текст і вставте його на вашу сторінку DokuWiki)+===== Архітектура рішення =====
  
-`====== Автоматизація деплою стеку моніторингу за допомогою Jenkins + Ansible + Git ======`+Ми використовуємо модель із **поділом обов'язків** для максимальної безпеки та гнучкості:
  
-Ця стаття — шпаргалка з налаштування безпечного CI/CD пайплайну "Push-to-Deploy".+* **Git (GitHub):** Єдине "джерело правди" для всіх конфігурацій.
  
-**Мета:** Автоматично оновлювати та перезапускати Docker Compose стек моніторингу на сервері щоразу, коли відбувається `git push` у `main` гілку. +* **Ansible (на хост-сервері):** "Виконавець" (CD). Він встановлений на самому сервері sim-serv і єдиний, хто має доступ до Docker та файлів проєкту. Він виконує інструкції (плейбуки).
- +
------ +
- +
-`===== Архітектура рішення =====` +
- +
-Ми використовуємо модель із **поділом обов'язків** для максимальної безпеки та гнучкості:+
  
-  * **Git (GitHub):** Єдине "джерело правди" для всіх конфігурацій. +* **Jenkins (в Docker):** "Оркестратор" (CI). Він ізольований у своєму контейнері **без** доступу до docker.sock і **без** root прав. Його єдина задача — "слухати" GitHub і, у разі змін, "дзвонити" по SSH на хост-сервер, наказуючи Ansible виконати плейбук.
-  * **Ansible (на хост-сервері):** "Виконавець" (CD). Він встановлений на самому сервері `sim-serv` і єдиний, хто має доступ до Docker та файлів проєкту. Він виконує інструкції (плейбуки). +
-  * **Jenkins (в Docker):** "Оркестратор" (CI). Він ізольований у своєму контейнері **без** доступу до `docker.sockі **без** `rootправ. Його єдина задача — "слухати" GitHub і, у разі змін, "дзвонити" по SSH на хост-сервер, наказуючи Ansible виконати плейбук.+
  
 ----- -----
  
-`===== Крок 1: Налаштування Ansible (Виконавець) на хост-сервері =====`+===== Крок 1: Налаштування Ansible (Виконавець) на хост-сервері =====
  
-Все це виконується на сервері `sim-serv(наприклад, з-під користувача `osvex`).+Все це виконується на сервері sim-serv (наприклад, з-під користувача osvex).
  
-`==== Встановлення Ansible та Docker-бібліотек ====`+==== Встановлення Ansible та Docker-бібліотек ====
  
 \<code bash\> \<code bash\>
Рядок 38: Рядок 30:
  
 sudo apt update sudo apt update
 +
 sudo apt install -y software-properties-common sudo apt install -y software-properties-common
 +
 sudo add-apt-repository --yes --update ppa:ansible/ansible sudo add-apt-repository --yes --update ppa:ansible/ansible
 +
 sudo apt install -y ansible sudo apt install -y ansible
  
Рядок 45: Рядок 40:
  
 sudo apt install python3-docker sudo apt install python3-docker
 +
 \</code\> \</code\>
  
-`==== Створення робочої папки та файлів Ansible ====`+==== Створення робочої папки та файлів Ansible ====
  
-Ми зберігаємо всі конфігурації Ansible у `/home/osvex/ansible/`.+Ми зберігаємо всі конфігурації Ansible у /home/osvex/ansible/.
  
-**1. Файл `inventory(де виконувати):**+**1. Файл inventory (де виконувати):**
  
-Це наш список серверів. Оскільки Ansible керує сам собою, ми використовуємо `localhost`.+Це наш список серверів. Оскільки Ansible керує сам собою, ми використовуємо localhost.
  
 \<code ini\> \<code ini\>
Рядок 60: Рядок 56:
  
 [monitoring] [monitoring]
 +
 localhost ansible\_connection=local localhost ansible\_connection=local
 +
 \</code\> \</code\>
  
-**2. Файл `deploy_monitoring.yml(що робити):**+**2. Файл deploy_monitoring.yml (що робити):**
  
 Це "плейбук", або інструкція для Ansible. Він оновлює Git-репозиторій та перезапускає Docker Compose. Це "плейбук", або інструкція для Ansible. Він оновлює Git-репозиторій та перезапускає Docker Compose.
Рядок 73: Рядок 71:
 ----- -----
  
-  - hosts: monitoring +- hosts: monitoring
-    become: no  \# Не отримувати sudo, працювати від імені osvex+
  
-    tasks:+becomeno \# Не отримувати sudo, працювати від імені osvex
  
-      - name1. Оновити код моніторингу з Git+tasks:
  
-        # Використовуємо вбудований git модуль+- name: 1. Оновити код моніторингу з Git
  
-        git: +Використовуємо вбудований git модуль
-        repo: '[email protected]:osvex/monitoring.git' +
-        dest: '/home/osvex/docker/monitoring' \Шлях до проєкту на хості +
-        version: 'main' +
-        accept\_hostkey: yes +
-        force: yes+
  
-      - name2. Перезапустити стек моніторингу (Docker Compose v2)+git:
  
-        # Використовуємо звичайну команду, оскільки модуль v1 не підтримує v2+repo: '[email protected]:osvex/monitoring.git'
  
-        ansible.builtin.command: +dest: '/home/osvex/docker/monitoring' \# Шлях до проєкту на хості 
-        cmd: docker compose up -d --build --remove-orphans + 
-        chdir: '/home/osvex/docker/monitoring' \# Папка, з якої запускати+version: 'main' 
 + 
 +accept\_hostkey: yes 
 + 
 +force: yes 
 + 
 +- name: 2. Перезапустити стек моніторингу (Docker Compose v2) 
 + 
 +# Використовуємо звичайну команду, оскільки модуль v1 не підтримує v2 
 + 
 +ansible.builtin.command: 
 + 
 +cmd: docker compose up -d --build --remove-orphans 
 + 
 +chdir: '/home/osvex/docker/monitoring' \# Папка, з якої запускати
  
 \</code\> \</code\>
Рядок 101: Рядок 107:
 ----- -----
  
-`===== Крок 2: Налаштування Jenkins (Оркестратор) в Docker =====`+===== Крок 2: Налаштування Jenkins (Оркестратор) в Docker =====
  
 Jenkins запускається у власному ізольованому Docker-контейнері. Jenkins запускається у власному ізольованому Docker-контейнері.
  
-====  `docker-compose.yml`  для Jenkins ==== `+==== docker-compose.yml для Jenkins ====
  
-Це **безпечна** конфігурація. Ми **НЕ** використовуємо `user: rootі **НЕ** прокидаємо `docker.sock`. Єдиний зв'язок зі світом — це "домашня" папка Jenkins.+Це **безпечна** конфігурація. Ми **НЕ** використовуємо user: root і **НЕ** прокидаємо docker.sock. Єдиний зв'язок зі світом — це "домашня" папка Jenkins.
  
 \<code yaml\> \<code yaml\>
Рядок 116: Рядок 122:
  
 services: services:
 +
 jenkins: jenkins:
 +
 image: jenkins/jenkins:lts-jdk17 image: jenkins/jenkins:lts-jdk17
 +
 container\_name: jenkins container\_name: jenkins
 +
 restart: unless-stopped restart: unless-stopped
  
-```+\\
 # Секція 'user: root' видалена для безпеки # Секція 'user: root' видалена для безпеки
  
 # Порти прокидаються через реверс-проксі (Traefik) # Порти прокидаються через реверс-проксі (Traefik)
 +
 # ports: # ports:
-  - "8090:8080" + 
-  +# - "8090:8080" 
 labels: labels:
-  - "traefik.enable=true" + 
-  - "traefik.http.routers.jenkins.rule=Host(`jenkins.osvex.com`)" +- "traefik.enable=true" 
-  - "traefik.http.routers.jenkins.entrypoints=websecure" + 
-  - "traefik.http.routers.jenkins.tls.certresolver=lets-encrypt" +- "traefik.http.routers.jenkins.rule=Host(jenkins.osvex.com)" 
-  - "traefik.http.services.jenkins.loadbalancer.server.port=8080" # Внутрішній порт Jenkins + 
-  - "traefik.http.services.jenkins.loadbalancer.server.scheme=http" +- "traefik.http.routers.jenkins.entrypoints=websecure" 
-  - "traefik.docker.network=shared_traefik"+ 
 +- "traefik.http.routers.jenkins.tls.certresolver=lets-encrypt" 
 + 
 +- "traefik.http.services.jenkins.loadbalancer.server.port=8080" # Внутрішній порт Jenkins 
 + 
 +- "traefik.http.services.jenkins.loadbalancer.server.scheme=http" 
 + 
 +- "traefik.docker.network=shared_traefik"
  
 volumes: volumes:
-  # Залишаємо ТІЛЬКИ цей один 'bind mount' для даних Jenkins + 
-  - /srv/docker/jenkins:/var/jenkins_home +# Залишаємо ТІЛЬКИ цей один 'bind mount' для даних Jenkins 
-   + 
-  # Всі інші volumes (docker.sock, /usr/bin/docker і т.д.) видалені+- /srv/docker/jenkins:/var/jenkins_home 
 + 
 +# Всі інші volumes (docker.sock, /usr/bin/docker і т.д.) видалені
  
 networks: networks:
-  - shared_traefik 
-``` 
  
 +- shared_traefik
 +
 +\\
 networks: networks:
 +
 shared\_traefik: shared\_traefik:
 +
 external: true external: true
 +
 \</code\> \</code\>
  
-`==== Встановлення прав на папку Jenkins ====`+==== Встановлення прав на папку Jenkins ====
  
-Оскільки Jenkins тепер працює від імені користувача `jenkins(UID 1000), ми повинні надати йому права на "домашню" папку:+Оскільки Jenkins тепер працює від імені користувача jenkins (UID 1000), ми повинні надати йому права на "домашню" папку:
  
 \<code bash\> \<code bash\>
 +
 sudo chown -R 1000:1000 /srv/docker/jenkins/ sudo chown -R 1000:1000 /srv/docker/jenkins/
 +
 \</code\> \</code\>
  
-`==== Необхідні плагіни Jenkins ====`+==== Необхідні плагіни Jenkins ====
  
 У Jenkins (через **Manage Jenkins -\> Plugins**) мають бути встановлені: У Jenkins (через **Manage Jenkins -\> Plugins**) мають бути встановлені:
  
-  * **GitHub Integration** (для тригерів та вебхуків) +* **GitHub Integration** (для тригерів та вебхуків) 
-  * **SSH Agent** (для використання SSH-ключів у пайплайнах)+ 
 +* **SSH Agent** (для використання SSH-ключів у пайплайнах)
  
 ----- -----
  
-`===== Крок 3: Налаштування "Мосту" (SSH-ключі та Webhook) =====`+===== Крок 3: Налаштування "Мосту" (SSH-ключі та Webhook) =====
  
-Ми створюємо два окремих SSH-ключа для двох різних завдань. Вони зберігаються у `/srv/docker/jenkins/.ssh/(що відповідає `/var/jenkins_home/.ssh/всередині контейнера).+Ми створюємо два окремих SSH-ключа для двох різних завдань. Вони зберігаються у /srv/docker/jenkins/.ssh/ (що відповідає /var/jenkins_home/.ssh/ всередині контейнера).
  
-`==== Ключ 1: Для підключення до GitHub (`id\_rsa`) ====`+==== Ключ 1: Для підключення до GitHub (id\_rsa) ====
  
-1.  **Налаштування Jenkins:** Перейдіть у **Manage Jenkins -\> Credentials -\> Global** та додайте `SSH Username with private key`: +1. **Налаштування Jenkins:** Перейдіть у **Manage Jenkins -\> Credentials -\> Global** та додайте SSH Username with private key:
-      * **ID:** `github-ssh-key` +
-      * **Username:** `git` +
-      * **Private Key:** (Вміст `id_rsa`) +
-2.  **Налаштування GitHub:** Перейдіть у **Репозиторій -\> Settings -\> Deploy keys** та додайте публічний ключ (вміст `id_rsa.pub`).+
  
-`==== Ключ 2Для підключення до хоста (Ansible) (`id\_rsa\_ansible`) ====`+* **ID:** github-ssh-key
  
-1.  **Налаштування Jenkins:** Перейдіть у **Manage Jenkins -\> Credentials -\> Global** та додайте `SSH Username with private key`: +* **Username:** git
-      * **ID:** `ansible-ssh-key` +
-      * **Username:** `osvex` (ваш логін на хост-сервері) +
-      * **Private Key:** (Вміст `id_rsa_ansible`) +
-2.  **Налаштування хост-сервера:** Додайте публічний ключ (вміст `id_rsa_ansible.pub`) до списку довірених для користувача `osvex`: +
-    \<code bash\> +
-    cat /srv/docker/jenkins/.ssh/id\_rsa\_ansible.pub \>\> /home/osvex/.ssh/authorized\_keys +
-    chmod 600 /home/osvex/.ssh/authorized\_keys +
-    \</code\>+
  
-==== Налаштування  `known\_hosts`  (у Jenkins) ==== `+* **Private Key:** (Вміст id_rsa) 
 + 
 +2. **Налаштування GitHub:** Перейдіть у **Репозиторій -\> Settings -\> Deploy keys** та додайте публічний ключ (вміст id_rsa.pub). 
 + 
 +==== Ключ 2: Для підключення до хоста (Ansible) (id\_rsa\_ansible) ==== 
 + 
 +1. **Налаштування Jenkins:** Перейдіть у **Manage Jenkins -\> Credentials -\> Global** та додайте SSH Username with private key: 
 + 
 +* **ID:** ansible-ssh-key 
 + 
 +* **Username:** osvex (ваш логін на хост-сервері) 
 + 
 +* **Private Key:** (Вміст id_rsa_ansible) 
 + 
 +2. **Налаштування хост-сервера:** Додайте публічний ключ (вміст id_rsa_ansible.pub) до списку довірених для користувача osvex: 
 + 
 +\<code bash\> 
 + 
 +cat /srv/docker/jenkins/.ssh/id\_rsa\_ansible.pub \>\> /home/osvex/.ssh/authorized\_keys 
 + 
 +chmod 600 /home/osvex/.ssh/authorized\_keys 
 + 
 +\</code\> 
 + 
 +==== Налаштування known\_hosts (у Jenkins) ====
  
 Jenkins повинен "довіряти" серверам, до яких він підключається. Jenkins повинен "довіряти" серверам, до яких він підключається.
Рядок 202: Рядок 242:
  
 ssh-keyscan -t rsa github.com \>\> /srv/docker/jenkins/.ssh/known\_hosts ssh-keyscan -t rsa github.com \>\> /srv/docker/jenkins/.ssh/known\_hosts
 +
 ssh-keyscan -t ed25519 github.com \>\> /srv/docker/jenkins/.ssh/known\_hosts ssh-keyscan -t ed25519 github.com \>\> /srv/docker/jenkins/.ssh/known\_hosts
 +
 ssh-keyscan -t rsa 172.17.0.1 \>\> /srv/docker/jenkins/.ssh/known\_hosts \# IP хоста зсередини Docker ssh-keyscan -t rsa 172.17.0.1 \>\> /srv/docker/jenkins/.ssh/known\_hosts \# IP хоста зсередини Docker
 +
 \</code\> \</code\>
  
-`==== Налаштування GitHub Webhook ====`+==== Налаштування GitHub Webhook ====
  
 У **Репозиторій -\> Settings -\> Webhooks** додайте новий Webhook: У **Репозиторій -\> Settings -\> Webhooks** додайте новий Webhook:
  
-  * **Payload URL:** `https://jenkins.osvex.com/github-webhook/` +* **Payload URL:** https://jenkins.osvex.com/github-webhook/ 
-  * **Content type:** `application/json`+ 
 +* **Content type:** application/json
  
 ----- -----
  
-===== Крок 4: Фінальний  `Jenkinsfile`  (Мозок) ===== `+===== Крок 4: Фінальний Jenkinsfile (Мозок) =====
  
 Цей файл лежить у корені вашого Git-репозиторію моніторингу. Він описує всю логіку пайплайну. Цей файл лежить у корені вашого Git-репозиторію моніторингу. Він описує всю логіку пайплайну.
Рядок 224: Рядок 268:
  
 pipeline { pipeline {
 +
 agent any // Запускати на будь-якому агенті agent any // Запускати на будь-якому агенті
  
-```+\\
 stages { stages {
-     
-    // Етап 1: Отримання коду з Git (Jenkins робить це автоматично) 
-    stage('Checkout') { 
-        steps { 
-            echo 'Отримання коду з репозиторію...' 
-            checkout scm 
-        } 
-    } 
  
-    // Етап 2: Запуск розгортання через Ansible +// Етап 1: Отримання коду з Git (Jenkins робить це автоматично) 
-    stage('Deploy via Ansible') { + 
-        steps { +stage('Checkout') { 
-            echo 'Запуск плейбука Ansible на хост-сервері...' + 
-             +steps { 
-            // "Обгортаємо" команду в sshagent,  + 
-            // щоб надати їй ключ 'ansible-ssh-key' (де вказано логін 'osvex'+echo 'Отримання коду з репозиторію...' 
-            sshagent(credentials: ['ansible-ssh-key']) { + 
-                 +checkout scm 
-                // Виконуємо SSH-команду + 
-                // Ми підключаємось до 172.17.0.1 (IP хост-сервера зсередини Docker) +
-                // і запускаємо наш плейбук + 
-                sh ''' +
-                    ssh -o StrictHostKeyChecking=no [email protected]+ 
-                    "cd /home/osvex/ansible && ansible-playbook -i inventory deploy_monitoring.yml" +// Етап 2: Запуск розгортання через Ansible 
-                ''' + 
-            +stage('Deploy via Ansible') { 
-        + 
-    }+steps { 
 + 
 +echo 'Запуск плейбука Ansible на хост-сервері...' 
 + 
 +// "Обгортаємо" команду в sshagent, 
 + 
 +// щоб надати їй ключ 'ansible-ssh-key' (де вказано логін 'osvex'
 + 
 +sshagent(credentials: ['ansible-ssh-key']) { 
 + 
 +// Виконуємо SSH-команду 
 + 
 +// Ми підключаємось до 172.17.0.1 (IP хост-сервера зсередини Docker) 
 + 
 +// і запускаємо наш плейбук 
 + 
 +sh ''' 
 + 
 +ssh -o StrictHostKeyChecking=no [email protected]
 + 
 +"cd /home/osvex/ansible && ansible-playbook -i inventory deploy_monitoring.yml" 
 + 
 +''' 
 + 
 +
 + 
 +
 + 
 +} 
 } }
  
 // Блок post-дій // Блок post-дій
 +
 post { post {
-    success { + 
-        echo 'ЧУДОВО: Пайплайн Ansible успішно виконано.' +success { 
-    } + 
-    failure { +echo 'ЧУДОВО: Пайплайн Ansible успішно виконано.' 
-        echo 'ПОМИЛКА: Пайплайн впав. Перевірте логи.' +
-    }+
 } }
-```+ 
 +failure { 
 + 
 +echo 'ПОМИЛКА: Пайплайн впав. Перевірте логи.'
  
 } }
 +
 +}
 +
 +\\
 +}
 +
 \</code\> \</code\>
  
 ----- -----
  
-`===== Фінальний потік роботи (Workflow) =====`+===== Фінальний потік роботи (Workflow) ===== 
 + 
 +1. Ви робите git push зі змінами у docker-compose.yml або prometheus.yml. 
 + 
 +2. GitHub "ловить" цей push і надсилає Webhook на https://jenkins.osvex.com. 
 + 
 +3. Jenkins "прокидається", запускає пайплайн, завантажує Jenkinsfile. 
 + 
 +4. Етап "Deploy" підключається по SSH до [email protected] (до вашого хост-сервера). 
 + 
 +5. Jenkins виконує команду: ansible-playbook ... 
 + 
 +6. Ansible (на хості) виконує плейбук: 
 + 
 +* Заходить у /home/osvex/docker/monitoring і робить git pull. 
 + 
 +* Запускає docker compose up -d ... 
 + 
 +7. Jenkins отримує "успішний" статус від Ansible і завершує пайплайн з зеленим кольором.
  
-1.  Ви робите `git push` зі змінами у `docker-compose.yml` або `prometheus.yml`. 
-2.  GitHub "ловить" цей push і надсилає Webhook на `https://jenkins.osvex.com`. 
-3.  Jenkins "прокидається", запускає пайплайн, завантажує `Jenkinsfile`. 
-4.  Етап "Deploy" підключається по SSH до `[email protected]` (до вашого хост-сервера). 
-5.  Jenkins виконує команду: `ansible-playbook ...` 
-6.  Ansible (на хості) виконує плейбук: 
-      * Заходить у `/home/osvex/docker/monitoring` і робить `git pull`. 
-      * Запускає `docker compose up -d ...` 
-7.  Jenkins отримує "успішний" статус від Ansible і завершує пайплайн з зеленим кольором. 
  • devops/jenkins.1763160983.txt.gz
  • Востаннє змінено: 14/11/2025 22:56
  • повз osvex