Автоматизація деплою стеку моніторингу за допомогою 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-бібліотек
\<code bash\>
# Встановлення 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
\</code\>
Створення робочої папки та файлів Ansible
Ми зберігаємо всі конфігурації Ansible у /home/osvex/ansible/.
1. Файл inventory (де виконувати):
Це наш список серверів. Оскільки Ansible керує сам собою, ми використовуємо localhost.
\<code ini\>
# /home/osvex/ansible/inventory
[monitoring]
localhost ansible\_connection=local
\</code\>
2. Файл deploy_monitoring.yml (що робити):
Це “плейбук”, або інструкція для Ansible. Він оновлює Git-репозиторій та перезапускає Docker Compose.
\<code yaml\>
# /home/osvex/ansible/deploy\_monitoring.yml
- hosts: monitoring
become: no \# Не отримувати sudo, працювати від імені osvex
tasks:
- name: 1. Оновити код моніторингу з Git
# Використовуємо вбудований git модуль
git:
repo: '[email protected]: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' \# Папка, з якої запускати
\</code\>
Крок 2: Налаштування Jenkins (Оркестратор) в Docker
Jenkins запускається у власному ізольованому Docker-контейнері.
docker-compose.yml для Jenkins
Це безпечна конфігурація. Ми НЕ використовуємо user: root і НЕ прокидаємо docker.sock. Єдиний зв'язок зі світом — це “домашня” папка Jenkins.
\<code yaml\>
# /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
\</code\>
Встановлення прав на папку Jenkins
Оскільки Jenkins тепер працює від імені користувача jenkins (UID 1000), ми повинні надати йому права на “домашню” папку:
\<code bash\>
sudo chown -R 1000:1000 /srv/docker/jenkins/
\</code\>
Необхідні плагіни 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:
\<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 повинен “довіряти” серверам, до яких він підключається.
\<code bash\>
# На хост-сервері виконайте:
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
\</code\>
Налаштування GitHub Webhook
У Репозиторій -\> Settings -\> Webhooks додайте новий Webhook:
* Payload URL: https://jenkins.osvex.com/github-webhook/
* Content type: application/json
Крок 4: Фінальний Jenkinsfile (Мозок)
Цей файл лежить у корені вашого Git-репозиторію моніторингу. Він описує всю логіку пайплайну.
\<code groovy\>
# /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 [email protected] \
“cd /home/osvex/ansible && ansible-playbook -i inventory deploy_monitoring.yml”
'
}
}
}
}
Блок post-дій
post {
success {
echo 'ЧУДОВО: Пайплайн Ansible успішно виконано.'
}
failure {
echo 'ПОМИЛКА: Пайплайн впав. Перевірте логи.'
}
}
}
\</code\>
—–
===== Фінальний потік роботи (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 і завершує пайплайн з зеленим кольором.