Skip to content

Commit

Permalink
feat: create playbook to install mysql8.4 (#33)
Browse files Browse the repository at this point in the history
* feat: create playbook to install mysql8.4

* docs: update mysql version comment

* fix: create users manually

* fix: include create user if exists and remove drop users task

* docs: add comments for mysql_native_password and cashing_sha2_password reference

* fix: change with_items iterator to loop

* fix: default all privileges
  • Loading branch information
marbonilla authored Jul 2, 2024
1 parent 3cfa344 commit bd3bcdb
Show file tree
Hide file tree
Showing 11 changed files with 385 additions and 0 deletions.
9 changes: 9 additions & 0 deletions mysql_8_4.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
# Playbook to provision MySQL

- name: Configure db MySQL instances
hosts: mysql_servers
become: True
gather_facts: True
roles:
- role: mysql_8_4
84 changes: 84 additions & 0 deletions roles/mysql_8_4/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
mysql_8_4_debian_pkgs:
- python3-mysqldb
- gpg

mysql_server_8_4_pkg: "mysql-server=8.4.*"
mysql_client_8_4_pkg: "mysql-client=8.4.*"
mysql_community_server_8_4_pkg: "mysql-server=8.4.*"

mysql_8_4_socket: /var/run/mysqld/mysqld.sock

MYSQL_8_4_APT_KEYSERVER: "keyserver.ubuntu.com"
MYSQL_8_4_APT_KEY: "A8D3785C"
MYSQL_8_4_REPO: "deb http://repo.mysql.com/apt//ubuntu/ {{ ansible_distribution_release }} mysql-8.4-lts"

MYSQL_8_4_SUPPORTED_DISTRIBUTIONS:
- "jammy"

# List of dictionaries as described in the mount_ebs role's default
# for the volumes.
# Useful if you want to store your MySQL data on separate
# disks from the root volume.
MYSQL_VOLUMES: []

# Mysql DB's in the form:
# MYSQL_CONFIG_DATABASES:
# - name: mydb
# collation: utf8_general_ci
# encoding: utf8
# state: present
MYSQL_CONFIG_DATABASES: []
# MYSQL_CONFIG_USERS:
# - name: myuser
# host: '%'
# password: 'strong_pass'
# priv: 'mydb.*:ALL'
# state: present
# append_privs: no
MYSQL_CONFIG_USERS: []

MYSQL_CONFIG_DEFAULT_ALLOWED_HOSTS: "%"

MYSQL_CONFIG_BIND_ADDRESS: "0.0.0.0"
MYSQL_CONFIG_PORT: 3306

MYSQL_CONFIG_SERVER_ID: 1

# In this path we store the MySQL configuration we create via templates
MYSQL_CONFIG_EXTRA_CONFIG_PATH: "/etc/mysql/mysql.conf.d"

# Using default MySQL 8.4 settings
# For more information check the links below:
# 8.4
# - https://dev.mysql.com/doc/refman/8.4/en/server-system-variables.html
# - https://dev.mysql.com/doc/refman/8.4/en/innodb-parameters.html

# Config for MySQL 8.4
# This variables are only compatible with MySQL 8.4
# More info: https://dev.mysql.com/doc/refman/8.4/en/added-deprecated-removed.html
MYSQL_CONFIG_EXPIRE_LOGS_SECONDS: 432000 # 5 days
MYSQL_CONFIG_INNODB_LOG_CAPACITY: 48M

MYSQL_CONFIG_CHARACTER_SET_SERVER: "utf8mb4"
MYSQL_CONFIG_COLLATION_SERVER: "utf8mb4_unicode_ci"
MYSQL_CONFIG_KEY_BUFFER_SIZE: 8M
MYSQL_CONFIG_MAX_CONNECTIONS: 1200
MYSQL_CONFIG_OPEN_FILES_LIMIT: 5000
MYSQL_CONFIG_TABLE_OPEN_CACHE: 2000
MYSQL_CONFIG_MAX_ALLOWED_PACKET: 16M
MYSQL_CONFIG_INNODB_BUFFER_POOL_SIZE: 128M
MYSQL_CONFIG_INNODB_IO_CAPACITY: 200
MYSQL_CONFIG_INNODB_IO_CAPACITY_MAX: 1000
MYSQL_CONFIG_INNODB_LOG_FILE_SIZE: 48M
MYSQL_CONFIG_INNODB_LOG_BUFFER_SIZE: 16M
MYSQL_CONFIG_INNODB_READ_IO_THREADS: 4
MYSQL_CONFIG_INNODB_WRITE_IO_THREADS: 4
MYSQL_CONFIG_INNODB_FLUSH_LOG_AT_TRX_COMMIT: 1

MYSQL_CONFIG_ENABLE_SLOW_QUERY_LOGS: false
MYSQL_CONFIG_READ_ONLY: false

# Replication
MYSQL_CONFIG_REPL_ENABLE_GTID_MODE: false
MYSQL_CONFIG_REPL_DISABLE_MYISAM: false
3 changes: 3 additions & 0 deletions roles/mysql_8_4/handlers/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
- name: restart mysql
service: name=mysql state=restarted
5 changes: 5 additions & 0 deletions roles/mysql_8_4/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
dependencies:
- common
- role: mount_ebs
volumes: "{{ MYSQL_VOLUMES }}"
26 changes: 26 additions & 0 deletions roles/mysql_8_4/tasks/configure.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
- name: Update mysql configuration
template:
src: mysqld.cnf.j2
dest: "{{ MYSQL_CONFIG_EXTRA_CONFIG_PATH }}/mysqld.cnf"
notify:
- restart mysql

- name: Put replication configuration file
template:
src: replication.cnf.j2
dest: "{{ MYSQL_CONFIG_EXTRA_CONFIG_PATH }}/replication.cnf"
notify:
- restart mysql

- name: Creating MySQL systemd custom dir
file:
path: /etc/systemd/system/mysql.service.d
state: directory

- name: Update mysql systemd configuration
template:
src: override.conf.j2
dest: /etc/systemd/system/mysql.service.d/override.conf
notify:
- restart mysql
10 changes: 10 additions & 0 deletions roles/mysql_8_4/tasks/databases.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
- name: Ensure MySQL databases are present.
mysql_db:
name: "{{ item.name }}"
collation: "{{ item.collation | default('') }}"
encoding: "{{ item.encoding | default('') }}"
state: "{{ item.state | default('present') }}"
target: "{{ item.target | default(omit) }}"
when: item.name != None and item.name != ''
with_items: "{{ MYSQL_CONFIG_DATABASES }}"
70 changes: 70 additions & 0 deletions roles/mysql_8_4/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
- name: Fail if trying to install on an unsupported distribution
fail:
msg: MySQL must be installed in a supported distribution
when: ansible_distribution_release not in MYSQL_8_4_SUPPORTED_DISTRIBUTIONS

- name: Install mysql dependencies
apt:
name: "{{ mysql_8_4_debian_pkgs }}"
install_recommends: yes
update_cache: yes
state: present

- name: Add MySQL repository key
apt_key:
keyserver: "{{ MYSQL_8_4_APT_KEYSERVER }}"
id: "{{ MYSQL_8_4_APT_KEY }}"
state: present

- name: Update APT cache
apt:
update_cache: yes

- name: Add MySQL repository to sources list
apt_repository:
repo: "{{ MYSQL_8_4_REPO }}"
state: present

# Installing mysql-8.4-client, mysql-8.4-community-server
# and mysql-8.4-server in separate tasks to resolve dependencies
- name: install mysql-8.4-client
apt:
name: "{{ mysql_client_8_4_pkg }}"
state: present
update_cache: yes

- name: install mysql-8.4-community-server
apt:
name: "{{ mysql_community_server_8_4_pkg }}"
state: present
update_cache: yes

- name: install mysql-8.4-server
apt:
name: "{{ mysql_server_8_4_pkg }}"
state: present
update_cache: yes

- name: restart mysql
command: service mysql restart

- name: Ensure Anonymous user(s) does not exist
mysql_user:
name: ''
host: "{{ item }}"
state: absent
login_unix_socket: "{{ mysql_8_4_socket }}"
with_items:
- localhost
- "{{ ansible_hostname }}"

- name: Alter user root to use caching_sha2_password
shell:
mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password; SET PASSWORD='';"
become: true

- name: Post MySQL installation configuration
include_tasks: configure.yml
- include_tasks: databases.yml
- include_tasks: users.yml
23 changes: 23 additions & 0 deletions roles/mysql_8_4/tasks/users.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
# Users are created manually because the mysql-users module in Ansible is still unable to
# create users correctly using the caching_sha2_password authentication plugin.
# As of now (20/06/2024), there is no release with the module fix.
# References
# https://github.com/ansible-collections/community.mysql/issues/621
# https://github.com/ansible-collections/community.mysql/pull/631
- name: Create or update extra users
shell: |
mysql -e "CREATE USER IF NOT EXISTS '{{ item.name }}'@'{{ item.host }}' IDENTIFIED BY '{{ item.password }}';"
when: item.name != None and item.name != ''
loop: "{{ MYSQL_CONFIG_USERS }}"

- name: Adding users extra config
mysql_user:
name: "{{ item.name }}"
host: "{{ item.host | default(MYSQL_CONFIG_DEFAULT_ALLOWED_HOSTS) }}"
priv: "{{ item.priv if item.priv is defined else (item.db + '.*:ALL' if item.db is defined else '*.*:ALL') }}"
state: "{{ item.state | default('present') }}"
append_privs: "{{ item.append_privs | default('no') }}"
encrypted: "{{ item.encrypted | default('no') }}"
when: item.name != None and item.name != ''
loop: "{{ MYSQL_CONFIG_USERS }}"
117 changes: 117 additions & 0 deletions roles/mysql_8_4/templates/mysqld.cnf.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#
# The MySQL database server configuration file.
#
# You can copy this to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
# https://dev.mysql.com/doc/refman/8.4/en/server-system-variables.html

# This will be passed to all mysql clients
# It has been reported that passwords should be enclosed with ticks/quotes
# escpecially if they contain "#" chars...
# Remember to edit /etc/mysql/debian.cnf when changing the socket location.

# Here is entries for some specific programs
# The following values assume you have at least 32M ram

[mysqld_safe]
socket = /var/run/mysqld/mysqld.sock
nice = 0

[mysqld]
#
# * Basic Settings
#
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = {{ MYSQL_CONFIG_PORT }}
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = {{ MYSQL_CONFIG_BIND_ADDRESS }}
#
# * Fine Tuning
#
key_buffer_size = {{ MYSQL_CONFIG_KEY_BUFFER_SIZE }}
max_allowed_packet = {{ MYSQL_CONFIG_MAX_ALLOWED_PACKET }}
thread_stack = 192K
thread_cache_size = 8
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched
myisam-recover-options = BACKUP
max_connections = {{ MYSQL_CONFIG_MAX_CONNECTIONS }}
table_open_cache = {{ MYSQL_CONFIG_TABLE_OPEN_CACHE }}
open_files_limit = {{ MYSQL_CONFIG_OPEN_FILES_LIMIT }}
#table_cache = 64
#thread_concurrency = 10
#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.
# As of 5.1 you can enable the log at runtime!
#general_log_file = /var/log/mysql/mysql.log
#general_log = 1
#
# Error log - should be very few entries.
#
log_error = /var/log/mysql/error.log
#
{% if MYSQL_CONFIG_ENABLE_SLOW_QUERY_LOGS %}
# Here you can see queries with especially long duration
slow_query_log = 1
slow_query_log_file = /var/lib/mysql/slow-queries.log
long_query_time = 2
{% endif %}
#log-queries-not-using-indexes
#
# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
# other settings you may need to change.
binlog_expire_logs_seconds = {{ MYSQL_CONFIG_EXPIRE_LOGS_SECONDS }}
read_only = {{ MYSQL_CONFIG_READ_ONLY }}
#binlog_do_db = include_database_name
#binlog_ignore_db = include_database_name
#
# * Character set and collation configuration
#
character-set-server = {{ MYSQL_CONFIG_CHARACTER_SET_SERVER }}
collation-server = {{ MYSQL_CONFIG_COLLATION_SERVER }}
#
# * InnoDB
#
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
# Read the manual for more InnoDB related options. There are many!
#
# * Security Features
#
# Read the manual, too, if you want chroot!
# chroot = /var/lib/mysql/
#
# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
#
# ssl-ca=/etc/mysql/cacert.pem
# ssl-cert=/etc/mysql/server-cert.pem
# ssl-key=/etc/mysql/server-key.pem

innodb_buffer_pool_size = {{ MYSQL_CONFIG_INNODB_BUFFER_POOL_SIZE }}
innodb_io_capacity = {{ MYSQL_CONFIG_INNODB_IO_CAPACITY }}
innodb_io_capacity_max = {{ MYSQL_CONFIG_INNODB_IO_CAPACITY_MAX }}
innodb_redo_log_capacity = {{ MYSQL_CONFIG_INNODB_LOG_CAPACITY }}
innodb_log_buffer_size = {{ MYSQL_CONFIG_INNODB_LOG_BUFFER_SIZE }}
innodb_read_io_threads = {{ MYSQL_CONFIG_INNODB_READ_IO_THREADS }}
innodb_write_io_threads = {{ MYSQL_CONFIG_INNODB_WRITE_IO_THREADS }}
innodb_flush_log_at_trx_commit = {{ MYSQL_CONFIG_INNODB_FLUSH_LOG_AT_TRX_COMMIT }}
2 changes: 2 additions & 0 deletions roles/mysql_8_4/templates/override.conf.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Service]
LimitNOFILE={{ MYSQL_CONFIG_OPEN_FILES_LIMIT }}
36 changes: 36 additions & 0 deletions roles/mysql_8_4/templates/replication.cnf.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[mysqld]
server-id = {{ MYSQL_CONFIG_SERVER_ID }}

# Replication and binlog related options
# See: https://mysqlhighavailability.com/mysql-group-replication-a-quick-start-guide/
binlog-row-image = MINIMAL
binlog-rows-query-log-events = ON
log-bin-trust-function-creators = TRUE
max-binlog-size = 1G
relay-log-recovery = ON
slave-parallel-type = LOGICAL_CLOCK
slave-preserve-commit-order = ON
slave-parallel-workers = 8
slave-type-conversions = ALL_NON_LOSSY
sync-master-info = 1000
sync-relay-log = 1000


# Group replication pre-requisites & recommendations.
# See: https://mysqlhighavailability.com/mysql-group-replication-a-quick-start-guide/
log-bin
binlog-format = ROW
{% if MYSQL_CONFIG_REPL_ENABLE_GTID_MODE %}
gtid-mode = ON
{% endif %}
enforce-gtid-consistency = ON
log_slave_updates = ON
binlog-checksum = NONE
# prevent use of non-transactional storage engines
{% if MYSQL_CONFIG_REPL_DISABLE_MYISAM %}
disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE"
{% endif %}
# InnoDB gap locks are problematic for multi-primary conflict detection; none are used with READ-COMMITTED
# So if you don't rely on REPEATABLE-READ semantics and/or wish to use multi-primary mode then this
# isolation level is recommended
transaction-isolation = 'READ-COMMITTED'

0 comments on commit bd3bcdb

Please sign in to comment.