maxscale: refs #8822 - refactor some minnor things #86

Open
xavi wants to merge 9 commits from 8822_MaxScale_final_migrate into main
7 changed files with 249 additions and 60 deletions

164
roles/maxscale/README.md Normal file
View File

@ -0,0 +1,164 @@
# MaxScale Ansible Role
This role installs and configures MariaDB MaxScale on Debian-based systems.
It supports both production and testing environments through the use of the variable `db.maxscale_is_test`.
The role is fully agnostic and depends on the `company` variable to dynamically build file paths, certificate names, and configuration details. All secrets are expected to be provided via inventory variables and/or `lookup()` calls.
---
## 🔧 Required Variables (Defined in Inventory)
### `company`
Defines the company/client identifier, used to build certificate filenames, paths, and other values.
**Must be defined in** `group_vars/all.yml`.
```yaml
company: verdnatura
```
---
### `db`
Defines MaxScale version and environment type (prod or test).
```yaml
db:
maxscale: "23.08.5"
maxscale_is_test: true # or false
```
---
### `maxscale_config`
Contains backend server definitions and active servers for services.
```yaml
maxscale_config:
db_servers:
- { name: db1, address: db1.example.com }
- { name: db2, address: db2.example.com }
db_servers_active:
- { name: db1, address: db1.example.com }
```
---
### `maxscale_config_certs`
Contains private key for MaxScale TLS listener (e.g. db.company.es.key).
```yaml
maxscale_config_certs:
db_verdnatura_es_key: "{{ lookup('passbolt', 'db_verdnatura_es_key', folder_parent_id=passbolt_folder).description }}"
```
---
### `cert_files_local`
Contains local certificate (e.g. db.company.es.pem).
```yaml
cert_files_local:
db_verdnatura_es_pem: "{{ lookup('file', inventory_dir + '/certs/db.verdnatura.es.pem') }}"
```
---
### `cert_files_all`
Global certificates shared between environments.
```yaml
cert_files_all:
wildcard_servers_dc_verdnatura_es_pem: "{{ lookup('file', inventory_dir + '/certs/wildcard.servers.dc.verdnatura.es.pem') }}"
verdnatura_ca_2042_pem: "{{ lookup('file', inventory_dir + '/certs/Verdnatura-ca_2042.pem') }}"
```
---
### `cert_files_all_key`
Private key for wildcard certificate.
```yaml
cert_files_all_key:
wildcard_servers_dc_verdnatura_es_key: "{{ lookup('passbolt', 'servers_wildcard_cert.key', folder_parent_id=passbolt_folder).description }}"
```
---
### `keepalive`
Required for high-availability setups (used by keepalived).
```yaml
keepalive:
interface: enp0s8
peers:
- host: db-proxy1
ip: 10.0.2.101
- host: db-proxy2
ip: 10.0.2.102
vips:
- name: vip1
host: db-proxy1
vrid: 11
vip: 10.0.1.101
- name: vip2
host: db-proxy2
vrid: 12
vip: 10.0.1.102
priorities:
master: 101
backup: 100
```
---
## 🧱 Template Behavior
- Uses `company` to generate certificate paths dynamically.
- Uses `db.maxscale_is_test` to choose ports and specific settings.
- All templates support dynamic inventory input.
---
## 📎 Included Templates
- `bothmaxscale.cnf.j2` → MaxScale config (production/test unified).
- `keepalived.conf.j2` → VIP and HA setup.
- `override.conf.j2` → Systemd override for `setcap`.
---
## 💡 Notes
- All secrets are retrieved via `lookup('passbolt', ...)` or `lookup('file', ...)`.
- The role fails if required variables are missing (by design).
- The role does not hardcode any company-specific data — everything comes from inventory.
---
## 🚀 Example Inventory Structure
```
inventory/
├── group_vars/
│ ├── all.yml
│ ├── dbproxy.yml
│ └── test_dbproxy.yml
└── certs/
├── db.verdnatura.es.pem
├── wildcard.servers.dc.verdnatura.es.pem
└── Verdnatura-ca_2042.pem
```
---
## 🧪 Run Example
```bash
ansible-playbook site.yml -l db-proxy1
```
---
Made with love and idempotence. 💚

View File

@ -1,15 +0,0 @@
downloads:
- url: https://r.mariadb.com/downloads/mariadb_repo_setup
dest: /tmp/mariadb_repo_setup
mode: u=rwx,g=rx,o=rx
certificates:
- { content: '{{ maxscale_config.admin_cert }}', dest: '/etc/ssl/private/cert.pem', owner: 'root', group: 'maxscale', mode: 'u=rw,g=r,o=r' }
- { content: '{{ maxscale_config.admin_key }}', dest: '/etc/ssl/private/key.pem', owner: 'root', group: 'maxscale', mode: 'u=rw,g=r,o=' }
- { content: '{{ maxscale_config.db_cert_pem }}', dest: '/etc/ssl/private/db-cert.pem', owner: 'root', group: 'maxscale', mode: 'u=rw,g=r,o=' }
- { content: '{{ maxscale_config.db_ca_pem }}', dest: '/etc/ssl/private/db-ca.pem', owner: 'root', group: 'maxscale', mode: 'u=rw,g=r,o=' }
- { content: '{{ maxscale_config.db_key }}', dest: '/etc/ssl/private/db-key.pem', owner: 'root', group: 'maxscale', mode: 'u=rw,g=r,o=' }
maxscale_templates:
- { src: 'maxscale.cnf.j2', dest: '/etc/maxscale.cnf' }
- { src: 'keepalived.conf.j2', dest: '/etc/keepalived/keepalived.conf' }
- { src: 'override.conf.j2', dest: '/etc/systemd/system/maxscale.service.d/override.conf' }
- { src: '.secrets', dest: '/var/lib/maxscale/.secrets', owner: 'maxscale', group: 'maxscale', mode: 'u=r,g=,o=' }

View File

@ -0,0 +1,17 @@
downloads:
- url: https://r.mariadb.com/downloads/mariadb_repo_setup
dest: /tmp/mariadb_repo_setup
mode: u=rwx,g=rx,o=rx
certificates_private_keys:
#- { content: "{{ maxscale_config_certs['db_' ~ company ~ '_es_key'] }}", dest: "/etc/ssl/private/db.{{ company }}.es.key", owner: "maxscale", group: "maxscale", mode: "u=rw,go=" }
- { content: "{{ maxscale_config_certs['db_' ~ company ~ '_es_key'] }}", dest: "/etc/ssl/private/{{ db.maxscale_is_test | ternary('test-', '') }}db.{{ company }}.es.key", owner: "maxscale", group: "maxscale", mode: "u=rw,go=" }
- { content: "{{ cert_files_all_key['wildcard_servers_dc_' ~ company ~ '_es_key'] }}", dest: "/etc/ssl/private/wildcard.servers.dc.{{ company }}.es.key", owner: "maxscale", group: "maxscale", mode: "u=rw,go=" }
cert_files:
- { content: "{{ cert_files_all['wildcard_servers_dc_' ~ company ~ '_es_pem'] }}", dest: "/etc/ssl/private/wildcard.servers.dc.{{ company }}.es.pem", owner: "root", group: "maxscale", mode: "u=rw,g=r,o=r" }
- { content: "{{ cert_files_all[company ~ '_ca_2042_pem'] }}", dest: "/etc/ssl/private/{{ company | capitalize }}-ca_2042.pem", owner: "root", group: "maxscale", mode: "u=rw,g=r,o=r" }
#- { content: "{{ cert_files_local['db_' ~ company ~ '_es_pem'] }}", dest: "/etc/ssl/private/db.{{ company }}.es.pem", owner: "root", group: "maxscale", mode: "u=rw,g=r,o=r" }
- { content: "{{ cert_files_local['db_' ~ company ~ '_es_pem'] }}", dest: "/etc/ssl/private/{{ db.maxscale_is_test | ternary('test-', '') }}db.{{ company }}.es.pem", owner: "root", group: "maxscale", mode: "u=rw,g=r,o=r" }
maxscale_templates:
- { src: 'keepalived.conf.j2', dest: '/etc/keepalived/keepalived.conf' }
- { src: 'override.conf.j2', dest: '/etc/systemd/system/maxscale.service.d/override.conf' }
- { src: '.secrets', dest: '/var/lib/maxscale/.secrets', owner: 'maxscale', group: 'maxscale', mode: 'u=r,g=,o=' }

View File

@ -11,6 +11,3 @@
name: keepalived
state: restarted
enabled: yes
- name: reload-systemd
command:
cmd: systemctl daemon-reload

View File

@ -1,3 +1,7 @@
- name: Set installation method for MaxScale
set_fact:
maxscale_use_deb: "{{ db.maxscale == '23.08.5' }}"
maxscale_use_repo: "{{ db.maxscale != '23.08.5' }}"
- name: Ensure required packages for MaxScale are installed
apt:
name: keepalived
@ -13,9 +17,27 @@
loop: "{{ downloads }}"
- name: Run MariaDB repository setup script
command:
cmd: "/bin/bash /tmp/mariadb_repo_setup --mariadb-server-version={{ db.version | default('10.11.10') }} --mariadb-maxscale-version={{ db.maxscale | default('23.08.9') }}"
cmd: "/bin/bash /tmp/mariadb_repo_setup --mariadb-maxscale-version={{ db.maxscale | default('23.08.9') }}"
creates: "/etc/apt/sources.list.d/mariadb.list"
when: mariadb_repo_script.changed
- name: Install maxscale via apt
apt:
name: maxscale
state: present
install_recommends: no
update_cache: true
when: maxscale_use_repo
- name: Download MaxScale 23.08.5 .deb package
get_url:
url: "https://dlm.mariadb.com/3773315/MaxScale/23.08.5/packages/debian/bookworm/x86_64/maxscale-23.08.5-1.debian.bookworm.x86_64.deb"
dest: "/tmp/maxscale-23.08.5.deb"
mode: '0644'
when: maxscale_use_deb
register: maxscale_manual_deb_tmp
- name: Install MaxScale .deb packages manually
apt:
deb: "/tmp/maxscale-23.08.5.deb"
when: maxscale_manual_deb_tmp.changed
- name: Ensure systemd override directory exists
file:
path: /etc/systemd/system/maxscale.service.d
@ -23,12 +45,6 @@
owner: root
group: root
mode: 'u=rwx,g=rx,o=rx'
- name: Install maxscale
apt:
name: maxscale
state: present
install_recommends: no
update_cache: true
- name: Ensure /etc/ssl/private has correct permissions and ownership
file:
path: /etc/ssl/private
@ -36,8 +52,15 @@
owner: root
group: maxscale
mode: "u=rwx,g=rx,o="
- name: Copy standard MaxScale template
template:
src: bothmaxscale.cnf.j2
dest: /etc/maxscale.cnf
owner: root
group: root
mode: "u=rw,g=r,o=r"
- name: Deploy templated configuration files
ansible.builtin.template:
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: "{{ item.owner | default('root') }}"
@ -48,7 +71,7 @@
- restart-keepalived
- restart-maxscale
- reload-systemd
- name: Insert certificates
- name: Insert private certificates
no_log: true
copy:
content: "{{ item.content }}"
@ -56,12 +79,16 @@
owner: "{{ item.owner }}"
group: "{{ item.group }}"
mode: "{{ item.mode }}"
loop: "{{ certificates }}"
loop: "{{ certificates_private_keys }}"
notify:
- restart-maxscale
- name: Insert certificates files
copy:
content: "{{item.content }}"
dest: "{{ item.dest }}"
owner: "{{ item.owner }}"
group: "{{ item.group }}"
mode: "{{ item.mode }}"
loop: "{{ cert_files }}"
notify:
- restart-maxscale

View File

@ -6,21 +6,21 @@
threads=auto
admin_host=0.0.0.0
admin_port=443
admin_ssl_cert={{ maxscale_config.admin_cert_path }}
admin_ssl_key={{ maxscale_config.admin_key_path }}
admin_ssl_cert=/etc/ssl/private/wildcard.servers.dc.{{ company }}.es.pem
admin_ssl_key=/etc/ssl/private/wildcard.servers.dc.{{ company }}.es.key
syslog=false
log_warning=false
logdir=/var/log/maxscale/
query_classifier_cache_size=250M
config_sync_cluster={{ maxscale_config.config_sync_cluster }}
config_sync_user={{ maxscale_config.config_sync_user }}
config_sync_cluster=MariaDB-Monitor
config_sync_user=maxscale-config
config_sync_password={{ lookup(passbolt, 'maxscale_config.config_sync_password', folder_parent_id=passbolt_folder).password }}
{% for server in maxscale_config.db_servers %}
[{{ server.name }}]
type=server
address={{ server.address }}
port=3306
port={{ db.maxscale_is_test | ternary('3307', '3306') }}
protocol=MariaDBBackend
{% endfor %}
@ -28,10 +28,10 @@ protocol=MariaDBBackend
type=monitor
module=mariadbmon
servers={{ maxscale_config.db_servers | map(attribute='name') | join(',') }}
user={{ maxscale_config.monitor_user }}
user=maxscale-mon
password={{ lookup(passbolt, 'maxscale_config.monitor_password', folder_parent_id=passbolt_folder).password }}
monitor_interval=2s
replication_user={{ maxscale_config.repl_user }}
replication_user=replication
replication_password={{ lookup(passbolt, 'maxscale_config.repl_password', folder_parent_id=passbolt_folder).password }}
switchover_timeout=1m
cooperative_monitoring_locks=majority_of_running
@ -39,8 +39,8 @@ cooperative_monitoring_locks=majority_of_running
[Read-Write-Service]
type=service
router=readwritesplit
servers=db1,db2
user={{ maxscale_config.rw_user }}
servers={{ maxscale_config.db_servers_active | map(attribute='name') | join(',') }}
user=maxscale-write
password={{ lookup(passbolt, 'maxscale_config.rw_password', folder_parent_id=passbolt_folder).password }}
master_accept_reads=true
strict_multi_stmt=true
@ -52,8 +52,8 @@ use_sql_variables_in=master
[Read-Only-Service]
type=service
router=readconnroute
servers=db1,db2
user={{ maxscale_config.ro_user }}
servers={{ maxscale_config.db_servers_active | map(attribute='name') | join(',') }}
user=maxscale-read
password={{ lookup(passbolt, 'maxscale_config.ro_password', folder_parent_id=passbolt_folder).password }}
router_options=slave
@ -63,25 +63,25 @@ service=Read-Write-Service
protocol=MariaDBClient
port=3306
ssl=true
ssl_cert={{ maxscale_config.db_cert_path }}
ssl_key={{ maxscale_config.db_key_path }}
ssl_ca_cert={{ maxscale_config.db_ca_path }}
ssl_cert=/etc/ssl/private/{{ db.maxscale_is_test | ternary('test-', '') }}db.{{ company }}.es.pem
ssl_key=/etc/ssl/private/{{ db.maxscale_is_test | ternary('test-', '') }}db.{{ company }}.es.key
ssl_ca_cert=/etc/ssl/private/{{ company | capitalize }}-ca_2042.pem
[Read-Only-Listener-SSL]
type=listener
service=Read-Only-Service
protocol=MariaDBClient
port=3307
port={{ db.maxscale_is_test | ternary('3308', '3307') }}
ssl=true
ssl_cert={{ maxscale_config.db_cert_path }}
ssl_key={{ maxscale_config.db_key_path }}
ssl_ca_cert={{ maxscale_config.db_ca_path }}
ssl_cert=/etc/ssl/private/{{ db.maxscale_is_test | ternary('test-', '') }}db.{{ company }}.es.pem
ssl_key=/etc/ssl/private/{{ db.maxscale_is_test | ternary('test-', '') }}db.{{ company }}.es.key
ssl_ca_cert=/etc/ssl/private/{{ company | capitalize }}-ca_2042.pem
[Read-Write-Listener]
type=listener
service=Read-Write-Service
protocol=MariaDBClient
port=3308
port={{ db.maxscale_is_test | ternary('3307', '3308') }}
[Read-Only-Listener]
type=listener

View File

@ -16,23 +16,22 @@ vrrp_script check_maxscale {
vrrp_instance {{ vip.name }} {
interface {{ k.interface }}
state BACKUP
priority {{ k.priorities.master if vip.host == inventory_hostname_short else k.priorities.backup }}
priority {{ k.priorities.master if vip.host == inventory_hostname else k.priorities.backup }}
virtual_router_id {{ vip.vrid }}
advert_int 1
accept
unicast_src_ip {{ ansible_host }}
unicast_src_ip {{ ansible_default_ipv4.address }}
unicast_peer {
{% for peer in k.peers if peer.host != inventory_hostname %}
{% for peer in k.peers %}
{% if peer.host != inventory_hostname %}
{{ peer.ip }}
{% endif %}
{% endfor %}
}
virtual_ipaddress {
{{ vip.vip }}
}
track_script {
check_maxscale
}