====== Автоматизація деплою стеку моніторингу за допомогою Jenkins + Ansible + Git ====== Ця стаття — шпаргалка з налаштування безпечного CI/CD пайплайну "Push-to-Deploy". **Мета:** Автоматично оновлювати та перезапускати Docker Compose стек моніторингу на сервері щоразу, коли відбувається git push у main гілку. ----- ===== Архітектура рішення ===== Ми використовуємо модель із **поділом обов'язків** для максимальної безпеки та гнучкості: * **Git (GitHub):** Єдине "джерело правди" для всіх конфігурацій. * **Ansible (на хост-сервері):** "Виконавець" (CD). Він встановлений на самому сервері sim-serv і єдиний, хто має доступ до Docker та файлів проєкту. Він виконує інструкції (плейбуки). * **Jenkins (в Docker):** "Оркестратор" (CI). Він ізольований у своєму контейнері **без** доступу до docker.sock і **без** root прав. Його єдина задача — "слухати" GitHub і, у разі змін, "дзвонити" по SSH на хост-сервер, наказуючи Ansible виконати плейбук. ----- ===== Крок 1: Налаштування Ansible (Виконавець) на хост-сервері ===== Все це виконується на сервері sim-serv (наприклад, з-під користувача osvex). ==== Встановлення Ansible та Docker-бібліотек ==== \ # Встановлення PPA та самого Ansible sudo apt update sudo apt install -y software-properties-common sudo add-apt-repository --yes --update ppa:ansible/ansible sudo apt install -y ansible # Встановлення Python-бібліотеки для Docker (потрібно для модуля Ansible) sudo apt install python3-docker \ ==== Створення робочої папки та файлів Ansible ==== Ми зберігаємо всі конфігурації Ansible у /home/osvex/ansible/. **1. Файл inventory (де виконувати):** Це наш список серверів. Оскільки Ansible керує сам собою, ми використовуємо localhost. \ # /home/osvex/ansible/inventory [monitoring] localhost ansible\_connection=local \ **2. Файл deploy_monitoring.yml (що робити):** Це "плейбук", або інструкція для Ansible. Він оновлює Git-репозиторій та перезапускає Docker Compose. \ # /home/osvex/ansible/deploy\_monitoring.yml ----- - hosts: monitoring become: no \# Не отримувати sudo, працювати від імені osvex tasks: - name: 1. Оновити код моніторингу з Git # Використовуємо вбудований git модуль git: repo: 'git@github.com:osvex/monitoring.git' dest: '/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' \# Папка, з якої запускати \ ----- ===== Крок 2: Налаштування Jenkins (Оркестратор) в Docker ===== Jenkins запускається у власному ізольованому Docker-контейнері. ==== docker-compose.yml для Jenkins ==== Це **безпечна** конфігурація. Ми **НЕ** використовуємо user: root і **НЕ** прокидаємо docker.sock. Єдиний зв'язок зі світом — це "домашня" папка Jenkins. \ # /home/osvex/docker/jenkins/docker-compose.yml version: '3.8' services: jenkins: image: jenkins/jenkins:lts-jdk17 container\_name: jenkins restart: unless-stopped \\ # Секція 'user: root' видалена для безпеки # Порти прокидаються через реверс-проксі (Traefik) # ports: # - "8090:8080" labels: - "traefik.enable=true" - "traefik.http.routers.jenkins.rule=Host(jenkins.osvex.com)" - "traefik.http.routers.jenkins.entrypoints=websecure" - "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: # Залишаємо ТІЛЬКИ цей один 'bind mount' для даних Jenkins - /srv/docker/jenkins:/var/jenkins_home # Всі інші volumes (docker.sock, /usr/bin/docker і т.д.) видалені networks: - shared_traefik \\ networks: shared\_traefik: external: true \ ==== Встановлення прав на папку Jenkins ==== Оскільки Jenkins тепер працює від імені користувача jenkins (UID 1000), ми повинні надати йому права на "домашню" папку: \ sudo chown -R 1000:1000 /srv/docker/jenkins/ \ ==== Необхідні плагіни Jenkins ==== У Jenkins (через **Manage Jenkins -\> Plugins**) мають бути встановлені: * **GitHub Integration** (для тригерів та вебхуків) * **SSH Agent** (для використання SSH-ключів у пайплайнах) ----- ===== Крок 3: Налаштування "Мосту" (SSH-ключі та Webhook) ===== Ми створюємо два окремих SSH-ключа для двох різних завдань. Вони зберігаються у /srv/docker/jenkins/.ssh/ (що відповідає /var/jenkins_home/.ssh/ всередині контейнера). ==== Ключ 1: Для підключення до GitHub (id\_rsa) ==== 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) ==== 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: \ cat /srv/docker/jenkins/.ssh/id\_rsa\_ansible.pub \>\> /home/osvex/.ssh/authorized\_keys chmod 600 /home/osvex/.ssh/authorized\_keys \ ==== Налаштування known\_hosts (у Jenkins) ==== Jenkins повинен "довіряти" серверам, до яких він підключається. \ # На хост-сервері виконайте: 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 rsa 172.17.0.1 \>\> /srv/docker/jenkins/.ssh/known\_hosts \# IP хоста зсередини Docker \ ==== Налаштування GitHub Webhook ==== У **Репозиторій -\> Settings -\> Webhooks** додайте новий Webhook: * **Payload URL:** https://jenkins.osvex.com/github-webhook/ * **Content type:** application/json ----- ===== Крок 4: Фінальний Jenkinsfile (Мозок) ===== Цей файл лежить у корені вашого Git-репозиторію моніторингу. Він описує всю логіку пайплайну. \ # /home/osvex/docker/monitoring/Jenkinsfile pipeline { agent any // Запускати на будь-якому агенті \\ stages { // Етап 1: Отримання коду з Git (Jenkins робить це автоматично) stage('Checkout') { steps { echo 'Отримання коду з репозиторію...' checkout scm } } // Етап 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 osvex@172.17.0.1 \ "cd /home/osvex/ansible && ansible-playbook -i inventory deploy_monitoring.yml" ''' } } } } // Блок post-дій post { success { echo 'ЧУДОВО: Пайплайн Ansible успішно виконано.' } failure { echo 'ПОМИЛКА: Пайплайн впав. Перевірте логи.' } } \\ } \ ----- ===== Фінальний потік роботи (Workflow) ===== 1. Ви робите git push зі змінами у docker-compose.yml або prometheus.yml. 2. GitHub "ловить" цей push і надсилає Webhook на https://jenkins.osvex.com. 3. Jenkins "прокидається", запускає пайплайн, завантажує Jenkinsfile. 4. Етап "Deploy" підключається по SSH до osvex@172.17.0.1 (до вашого хост-сервера). 5. Jenkins виконує команду: ansible-playbook ... 6. Ansible (на хості) виконує плейбук: * Заходить у /home/osvex/docker/monitoring і робить git pull. * Запускає docker compose up -d ... 7. Jenkins отримує "успішний" статус від Ansible і завершує пайплайн з зеленим кольором.