====== Автоматизація деплою стеку моніторингу за допомогою 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 і завершує пайплайн з зеленим кольором.