Compare commits

...

No commits in common. "66471a8a89dfea4ec780782ee1ab3f340f8a623b" and "40e7acd0e8fade9c8e9de118e793757ae7aee44e" have entirely different histories.

20 changed files with 198 additions and 300 deletions

97
Jenkinsfile vendored
View File

@ -1,71 +1,100 @@
pipeline { pipeline {
agent any agent any
tools { tools {
ansible 'Ansible' ansible 'Ansible'
} }
environment { environment {
PSQL_PASSWORD = credentials('PSQL_pass') SSH_ROOT_PASSWORD = credentials('ssh_root_password')
VAULT_PASSWORD = credentials('ansible_vault_password') PSQL_PASSWORD = credentials('PSQL_pass')
ANSIBLE_HOST_KEY_CHECKING = 'False'
} }
parameters { parameters {
string(name: 'DB_SERVER_IP', defaultValue: '192.168.0.71', description: 'IP-адрес сервера')
string(name: 'SSH_USER', defaultValue: 'root', description: 'Имя пользователя для SSH подключения')
string(name: 'DB_USER', defaultValue: 'postgres', description: 'Имя пользователя базы данных') string(name: 'DB_USER', defaultValue: 'postgres', description: 'Имя пользователя базы данных')
string(name: 'DB_NAME', defaultValue: 'mydb', description: 'Имя базы данных') string(name: 'DB_NAME', defaultValue: 'mydb', description: 'Имя базы данных')
string(name: 'BACKUP_DIR', defaultValue: '/var/backups/postgresql', description: 'Директория для бэкапа') string(name: 'BACKUP_DIR', defaultValue: '/var/backups/postgresql', description: 'Директория для бэкапа')
string(name: 'TASKS', defaultValue: '', description: 'Список тегов задач для выполнения (setup,firewall,init,configure,database,user,backup)')
} }
stages { stages {
stage('Clone repository') { stage('Clone repository') {
steps { steps {
git branch: 'dev', url: 'http://192.168.0.70:3000/coursework/courseworkrep.git'
git branch: 'main', url: 'http://192.168.0.70:3000/coursework/courseworkrep.git'
} }
} }
stage('Decrypt SSH Key') { stage('Install PostgreSQL') {
steps { steps {
script { script {
def tempDir = '/tmp/' + UUID.randomUUID().toString()
env.TEMP_DIR = tempDir def tempDir = sh(script: 'mktemp -d', returnStdout: true).trim()
sh "mkdir -p ${tempDir}" def hostsFile = "${tempDir}/hosts.ini"
echo "Temporary directory created: ${tempDir}"
def decryptedKeyFile = "${tempDir}/id_ed25519"
def vaultPassFile = "${tempDir}/vault_pass" writeFile file: hostsFile, text: """
[postgres_servers]
${params.DB_SERVER_IP} ansible_user=${params.SSH_USER} ansible_password=${SSH_ROOT_PASSWORD} ansible_ssh_extra_args='-o StrictHostKeyChecking=no'
"""
sh "cat ${hostsFile}"
writeFile file: vaultPassFile, text: VAULT_PASSWORD
sh """ sh """
ansible-vault decrypt ./id_ed25519_vault --vault-password-file=${vaultPassFile} --output=${decryptedKeyFile} ansible-playbook -i ${hostsFile} install_postgresql.yml \
-e postgres_user=${params.DB_USER} \
-e postgres_password=${PSQL_PASSWORD} \
-e postgres_db=${params.DB_NAME}
""" """
env.DECRYPTED_KEY_FILE = decryptedKeyFile
sh "rm -rf ${tempDir}"
echo "Temporary directory ${tempDir} has been removed"
} }
} }
} }
stage('Run PostgreSQL Playbook') { stage('Setup PostgreSQL Backup with Cron') {
steps { steps {
script { script {
def tagsString = params.TASKS ? params.TASKS.split(',').join(',') : ''
ansiblePlaybook( def tempDir = sh(script: 'mktemp -d', returnStdout: true).trim()
playbook: 'playbooks/install_postgresql.yml', def hostsFile = "${tempDir}/hosts.ini"
inventory: "inventory.yml", echo "Temporary directory created: ${tempDir}"
extraVars: [
postgres_user: params.DB_USER,
postgres_password: PSQL_PASSWORD, writeFile file: hostsFile, text: """
postgres_db: params.DB_NAME, [postgres_servers]
backup_dir: params.BACKUP_DIR, ${params.DB_SERVER_IP} ansible_user=${params.SSH_USER} ansible_password=${SSH_ROOT_PASSWORD} ansible_ssh_extra_args='-o StrictHostKeyChecking=no'
ansible_ssh_private_key_file: env.DECRYPTED_KEY_FILE """
],
tags: tagsString
) sh "cat ${hostsFile}"
sh """
ansible-playbook -i ${hostsFile} backup_postgresql.yml \
-e postgres_user=${params.DB_USER} \
-e postgres_password=${PSQL_PASSWORD} \
-e postgres_db=${params.DB_NAME} \
-e backup_dir=${params.BACKUP_DIR}
"""
sh "rm -rf ${tempDir}"
echo "Temporary directory ${tempDir} has been removed"
} }
} }
} }
} }
post { post {
always { always {
script { echo "Pipeline completed"
if (env.TEMP_DIR) { }
sh "rm -rf ${env.TEMP_DIR}" failure {
} echo "Pipeline failed"
} }
success {
echo "Pipeline succeeded"
} }
} }
} }

View File

@ -1,61 +0,0 @@
# Проект по автоматизации настройки PostgreSQL
Этот проект предназначен для автоматизации установки, настройки и управления базой данных PostgreSQL с использованием **Ansible** и **Jenkins**. Он включает пайплайн Jenkins и Ansible плейбук с ролью для управления PostgreSQL.
## Структура проекта
- **Jenkinsfile** — скрипт для автоматизации пайплайна Jenkins, который позволяет клонировать репозиторий, расшифровывать SSH-ключи, запускать Ansible плейбук и выполнять определенные задачи роли PostgreSQL.
- **ansible.cfg** — конфигурационный файл Ansible, где указаны настройки по умолчанию для выполнения плейбуков.
- **inventory.yml** — файл инвентаря Ansible, который определяет хосты, на которых будут выполняться плейбуки.
- **playbooks/install_postgresql.yml** — основной Ansible плейбук для установки и настройки PostgreSQL.
- **roles/postgresql** — Ansible роль для управления PostgreSQL, которая содержит:
- **tasks/** — каталог с задачами:
- `setup.yml` — установка необходимых пакетов PostgreSQL.
- `open_firewall.yml` — настройка правил брандмауэра для доступа к базе данных.
- `initialize.yml` — инициализация новой базы данных.
- `configure.yml` — настройка параметров конфигурации PostgreSQL.
- `databases.yml` — создание и управление базами данных.
- `users.yml` — создание и управление пользователями базы данных.
- `backup.yml` — резервное копирование базы данных.
- **templates/** — шаблоны конфигурационных файлов для PostgreSQL:
- `pg_hba.conf.j2` — шаблон файла для управления доступом к базе данных.
- `postgresql.conf.j2` — шаблон основного конфигурационного файла PostgreSQL.
- **vars/** — переменные, используемые в роли PostgreSQL.
## Запуск проекта
### Предварительные требования
- **Jenkins** с установленным Ansible плагином
- Доступ к хостам, указанным в `inventory.yml`
### Пайплайн Jenkins
Файл **Jenkinsfile** определяет этапы пайплайна для автоматизированного развертывания PostgreSQL:
1. **Клонирование репозитория** — загрузка кода проекта.
2. **Расшифровка SSH-ключа** — декодирование зашифрованного ключа с использованием Ansible Vault.
3. **Запуск плейбука PostgreSQL** — выполнение Ansible плейбука для развертывания и настройки PostgreSQL на целевых хостах.
### Параметры запуска
Пайплайн поддерживает следующие параметры:
- **DB_USER** — имя пользователя PostgreSQL.
- **DB_NAME** — название базы данных.
- **BACKUP_DIR** — директория для хранения резервных копий.
- **TASKS** — список задач для выполнения, указанный через запятую (например, `setup,backup`).
### Порядок задач
По умолчанию задачи выполняются в следующем порядке:
1. `setup` — установка необходимых пакетов.
2. `firewall` — настройка брандмауэра.
3. `init` — инициализация базы данных.
4. `configure` — конфигурация базы данных.
5. `database` — создание базы данных.
6. `user` — управление пользователями.
7. `backup` — резервное копирование данных.
При указании параметра `TASKS`, можно выбрать конкретные задачи, и они будут выполнены в этом порядке.

View File

@ -1,3 +0,0 @@
[defaults]
inventory = inventory.yml
roles_path = ./roles

37
backup_postgresql.yml Normal file
View File

@ -0,0 +1,37 @@
---
- name: Backup PostgreSQL and create cron
hosts: postgres_servers
become: true
vars:
backup_dir: "{{ backup_dir }}"
tasks:
- name: Create backup directory
file:
path: "{{ backup_dir }}"
state: directory
owner: postgres
group: postgres
mode: '0755'
- name: PostgreSQL database backup
become_user: postgres
command: >
pg_dump -U {{ postgres_user }}
-F c
-f "{{ backup_dir }}/db_backup_{{ postgres_db }}_{{ ansible_date_time.iso8601 }}.sql"
{{ postgres_db }}
environment:
PGPASSWORD: "{{ postgres_password }}"
- name: Create cron backup script
cron:
name: "PostgreSQL hourly backup"
user: postgres
minute: "0"
hour: "*"
job: 'pg_dump -U {{ postgres_user }} -F c {{ postgres_db }} > {{ backup_dir }}/db_backup_{{ postgres_db }}_$(date +\%F-\%H-\%M).sql'
environment:
PGPASSWORD: "{{ postgres_password }}"

View File

@ -1,26 +0,0 @@
$ANSIBLE_VAULT;1.1;AES256
65316433646437363338333233313530386265396432326633303334363130396438623632373733
6234643334313336376439343564616333366632393666320a623066663130336665663763626337
36353135383933386431643036336561653438356537363262333530663363333138663966336231
3631333939653033370a643061336136313031336163346431393034653237646265653665316466
63333966383038666635636462393361313731666239356139653466663761383531653063343733
64396533303131666139323333653838323961396437326438353733653262393164343263643738
37626464353762656532373739376363363935383065336637333161356331303230356163626533
66363331616263383366303534376235663564313031343031323466333564646233393238336665
62383138623137323761656163336631393861386436626338666662313739353338373563626335
31663831366135396437643562373463613566333433666162313833653230396439353461633437
31663937343437643363323137313331373839313032333830316135303734376264396539396339
37613031376235316439303363326134613136616137623133353738313236383436386631636432
64373861346631386234316234663134316231336666356230373862396237346565393434383039
64323462653532636161333339623138663564396261363832626630393533323139616165363065
66376166306131333531323966633036623762323037616261643930343733383165333939326537
34636534343436313132383532633631363631356563336365393437616337333062323862336164
66656463643761366335663331633733383065316530653935613134653837666332653262326266
39396237616235383163386662363637346633366231373236323734383934383035623739333263
65316364306462376134373165393661316561383837383438306365666437373365366461663439
61336463636462333363313766363465313163373063323864613136303564396137333536373235
33656135393732653230373031613663633866386537643164623138623663626663303331656631
37666562663135643832386335373132643738393233656361663931306563386666613135303033
32663633373439646564663036626561336338313239316634623838633534306530633739363831
39306631356662363430633866653538623837303537343331363066326466646430346638623162
6438

98
install_postgresql.yml Normal file
View File

@ -0,0 +1,98 @@
---
- name: Install PostgreSQL on openSUSE Leap
hosts: postgres_servers
become: yes
vars:
postgres_user: "{{ postgres_user }}"
postgres_password: "{{ postgres_password }}"
postgres_db: "{{ postgres_db }}"
tasks:
- name: Update zypper
command: zypper refresh
register: zypper_refresh
changed_when: "'Refreshing' in zypper_refresh.stdout"
- name: Update System
zypper:
name: '*'
state: latest
when: zypper_refresh.changed
- name: Update PostgreSQL package
zypper:
name:
- postgresql-server
- postgresql-contrib
state: present
- name: PostgreSQL initdb
command: sudo -u postgres initdb -D /var/lib/pgsql/data
args:
creates: /var/lib/pgsql/data/PG_VERSION
- name: Systemctl start and enable PostgreSQL
service:
name: postgresql
state: started
enabled: yes
- name: python3-psycopg2 install
zypper:
name: python3-psycopg2
state: present
- name: Change listen_addresses in postgresql.conf
lineinfile:
path: /var/lib/pgsql/data/postgresql.conf
regexp: '^#?listen_addresses\s*='
line: "listen_addresses = '*'"
notify: Restart PostgreSQL
- name: Change pg_hba.conf
lineinfile:
path: /var/lib/pgsql/data/pg_hba.conf
regexp: '^host\s+all\s+all\s+0\.0\.0\.0/0\s+md5'
line: "host all all 0.0.0.0/0 md5"
notify: Restart PostgreSQL
- name: Create User PostgreSQL
community.postgresql.postgresql_user:
name: "{{ postgres_user }}"
password: "{{ postgres_password }}"
state: present
- name: Create Base PostgreSQL
community.postgresql.postgresql_db:
name: "{{ postgres_db }}"
owner: "{{ postgres_user }}"
encoding: UTF8
state: present
- name: Create a table
community.postgresql.postgresql_query:
db: "{{ postgres_db }}"
query: >
CREATE TABLE IF NOT EXISTS contacts (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
phone_number VARCHAR(15)
);
login_user: "{{ postgres_user }}"
login_password: "{{ postgres_password }}"
- name: open firewall 5432 port
command: firewall-cmd --add-port=5432/tcp --permanent
become: yes
- name: Restart Firewall
command: firewall-cmd --reload
become: yes
handlers:
- name: Restart PostgreSQL
service:
name: postgresql
state: restarted

View File

@ -1,6 +0,0 @@
all:
children:
postgres_servers:
hosts:
192.168.0.71:
ansible_user: ansible

View File

@ -1,4 +0,0 @@
- hosts: all
become: true
roles:
- postgresql

View File

@ -1,4 +0,0 @@
- name: Restart PostgreSQL
service:
name: postgresql
state: restarted

View File

@ -1,41 +0,0 @@
- name: Create backup directory
file:
path: '{{ backup_dir }}'
state: directory
owner: postgres
group: postgres
mode: '0755'
tags:
- backup
- name: Perform database backup
command: >
pg_dump -U {{ postgres_user }} -F c -f "{{ backup_dir }}/db_backup_{{ postgres_db }}_{{ ansible_date_time.iso8601 }}.sql" {{ postgres_db }}
become_user: postgres
environment:
PGPASSWORD: '{{ postgres_password }}'
tags:
- backup
- name: Daily cron full backup
cron:
name: 'PostgreSQL daily full backup'
user: postgres
minute: '0'
hour: '1'
job: "pg_dump -U {{ postgres_user }} -F c {{ postgres_db }} > {{ backup_dir }}/full_db_backup_{{ postgres_db }}_$(date +\\%F-\\%H-%M).sql"
environment:
PGPASSWORD: '{{ postgres_password }}'
tags:
- backup
- name: Hourly cron incremental backup
cron:
name: 'PostgreSQL hourly incremental backup'
user: postgres
minute: '0'
job: "pg_dump -U {{ postgres_user }} -F c --data-only --file=\"{{ backup_dir }}/incremental_db_backup_{{ postgres_db }}_$(date +\\%F-\\%H-%M).sql\" {{ postgres_db }}"
environment:
PGPASSWORD: '{{ postgres_password }}'
tags:
- backup

View File

@ -1,21 +0,0 @@
- name: Configure postgresql.conf with template
template:
src: postgresql.conf.j2
dest: /var/lib/pgsql/data/postgresql.conf
owner: postgres
group: postgres
mode: '0644'
notify: Restart PostgreSQL
tags:
- configure
- name: Configure pg_hba.conf with template
template:
src: pg_hba.conf.j2
dest: /var/lib/pgsql/data/pg_hba.conf
owner: postgres
group: postgres
mode: '0644'
notify: Restart PostgreSQL
tags:
- configure

View File

@ -1,17 +0,0 @@
- name: Create PostgreSQL database
community.postgresql.postgresql_db:
name: '{{ postgres_db }}'
owner: '{{ postgres_user }}'
encoding: UTF8
state: present
tags:
- database
- name: Create contacts table in PostgreSQL
community.postgresql.postgresql_query:
db: '{{ postgres_db }}'
query: 'CREATE TABLE IF NOT EXISTS contacts (id SERIAL PRIMARY KEY, name VARCHAR(100), phone_number VARCHAR(15));'
login_user: '{{ postgres_user }}'
login_password: '{{ postgres_password }}'
tags:
- database

View File

@ -1,14 +0,0 @@
- name: PostgreSQL initdb
command: sudo -u postgres initdb -D /var/lib/pgsql/data
args:
creates: /var/lib/pgsql/data/PG_VERSION
tags:
- init
- name: Systemctl start and enable PostgreSQL
service:
name: postgresql
state: started
enabled: true
tags:
- init

View File

@ -1,7 +0,0 @@
- import_tasks: setup.yml
- import_tasks: initialize.yml
- import_tasks: configure.yml
- import_tasks: users.yml
- import_tasks: databases.yml
- import_tasks: open_firewall.yml
- import_tasks: backup.yml

View File

@ -1,14 +0,0 @@
- name: Open PostgreSQL port in firewall
firewalld:
port: 5432/tcp
permanent: true
state: enabled
become: true
tags:
- firewall
- name: Reload firewall using command
command: firewall-cmd --reload
become: true
tags:
- firewall

View File

@ -1,15 +0,0 @@
- name: Install PostgreSQL packages
zypper:
name:
- postgresql-server
- postgresql-contrib
state: present
tags:
- setup
- name: Install python3-psycopg2
zypper:
name: python3-psycopg2
state: present
tags:
- setup

View File

@ -1,7 +0,0 @@
- name: Create PostgreSQL user
community.postgresql.postgresql_user:
name: '{{ postgres_user }}'
password: '{{ postgres_password }}'
state: present
tags:
- users

View File

@ -1,3 +0,0 @@
{% for entry in postgres_hba_entries %}
{{ entry.type }} {{ entry.database }} {{ entry.user }} {{ entry.address }} {{ entry.method }}
{% endfor %}

View File

@ -1,12 +0,0 @@
listen_addresses = '{{ postgres_listen_addresses | default("*") }}'
port = {{ postgres_port | default(5432) }}
max_connections = {{ postgres_max_connections | default(100) }}
shared_buffers = {{ postgres_shared_buffers | default("128MB") }}
effective_cache_size = {{ postgres_effective_cache_size | default("4GB") }}
maintenance_work_mem = {{ postgres_maintenance_work_mem | default("64MB") }}
checkpoint_completion_target = {{ postgres_checkpoint_completion_target | default(0.7) }}
wal_buffers = {{ postgres_wal_buffers | default("16MB") }}
default_statistics_target = {{ postgres_default_statistics_target | default(100) }}

View File

@ -1,11 +0,0 @@
postgres_listen_addresses: '*'
postgres_port: 5432
postgres_hba_entries:
- { type: 'host', database: 'all', user: 'all', address: '0.0.0.0/0', method: 'md5' }
- { type: 'local', database: 'all', user: 'all', address: '', method: 'trust' }
backup_dir: "/var/lib/pgsql/backups"
postgres_user: "postgres"
postgres_password: "your_password"
postgres_db: "your_database"