Ansible Mariadb w/ Galera support
Adds initial support for Mariadb with Galera replication in Ansible using the CONFIG_EXTERNAL methods. Additionally, this refactors some of the Galera config script to allow for reuse by CONFIG_EXTERNAL. Partially Implements: blueprint ansible-service Change-Id: I566fea0376ecca39fc8a5167f9ff9ff434ea7b7e
This commit is contained in:
parent
90d92347e8
commit
efbfd7912b
@ -14,6 +14,9 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
# TODO(SamYaple): Provide idempotency for module (Note to self: pull logic from
|
||||||
|
# pervious bslurp module in yaodu)
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
---
|
---
|
||||||
module: merge_configs
|
module: merge_configs
|
||||||
|
21
ansible/roles/database/defaults/main.yml
Normal file
21
ansible/roles/database/defaults/main.yml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
project_name: "mariadb"
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Database
|
||||||
|
####################
|
||||||
|
database_cluster_name: "kolla"
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Docker
|
||||||
|
####################
|
||||||
|
docker_database_registry: "{{ docker_registry }}"
|
||||||
|
docker_database_namespace: "{{ docker_namespace }}"
|
||||||
|
kolla_database_base_distro: "{{ kolla_base_distro }}"
|
||||||
|
kolla_database_install_type: "{{ kolla_install_type }}"
|
||||||
|
kolla_database_container_name: "galera"
|
||||||
|
|
||||||
|
docker_database_image: "{{ docker_database_registry }}{{ docker_database_namespace }}/{{ kolla_database_base_distro }}-{{ kolla_database_install_type }}-{{ kolla_database_container_name }}"
|
||||||
|
docker_database_tag: "{{ openstack_release }}"
|
||||||
|
docker_database_image_full: "{{ docker_database_image }}:{{ docker_database_tag }}"
|
61
ansible/roles/database/tasks/bootstrap.yml
Normal file
61
ansible/roles/database/tasks/bootstrap.yml
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
---
|
||||||
|
- name: Creating temp file on localhost
|
||||||
|
local_action: shell echo 'None' > /tmp/kolla_mariadb_cluster
|
||||||
|
register: status
|
||||||
|
changed_when: False
|
||||||
|
failed_when: status.rc != 0
|
||||||
|
always_run: True
|
||||||
|
run_once: True
|
||||||
|
|
||||||
|
# TODO(SamYaple): Improve failed_when check
|
||||||
|
- name: Checking if a previous cluster exists
|
||||||
|
command: docker exec mariadb stat /var/lib/mysql/grastate.dat
|
||||||
|
register: exists
|
||||||
|
changed_when: False
|
||||||
|
failed_when: False
|
||||||
|
always_run: True
|
||||||
|
run_once: True
|
||||||
|
|
||||||
|
- name: Writing hostname of host with existing cluster files to temp file
|
||||||
|
local_action: shell echo "{{ ansible_hostname }}" > /tmp/kolla_mariadb_cluster
|
||||||
|
register: status
|
||||||
|
changed_when: False
|
||||||
|
failed_when: status.rc != 0
|
||||||
|
always_run: True
|
||||||
|
when: exists.rc == 0
|
||||||
|
|
||||||
|
- name: Registering host from temp file
|
||||||
|
set_fact:
|
||||||
|
delegate_host: "{{ lookup('file', '/tmp/kolla_mariadb_cluster') }}"
|
||||||
|
|
||||||
|
- name: Cleaning up temp file on localhost
|
||||||
|
local_action: shell rm /tmp/kolla_mariadb_cluster
|
||||||
|
register: status
|
||||||
|
changed_when: False
|
||||||
|
failed_when: status.rc != 0
|
||||||
|
always_run: True
|
||||||
|
run_once: True
|
||||||
|
|
||||||
|
- include: ../../start.yml
|
||||||
|
vars:
|
||||||
|
container_environment:
|
||||||
|
KOLLA_BOOTSTRAP:
|
||||||
|
container_image: "{{ docker_database_image_full }}"
|
||||||
|
container_name: "mariadb_data"
|
||||||
|
container_volumes:
|
||||||
|
- "/var/lib/mysql/"
|
||||||
|
container_command: "/bin/sleep infinity"
|
||||||
|
|
||||||
|
- include: ../../start.yml
|
||||||
|
vars:
|
||||||
|
container_environment:
|
||||||
|
KOLLA_BOOTSTRAP:
|
||||||
|
KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
|
||||||
|
DB_ROOT_PASSWORD: "{{ database_password }}"
|
||||||
|
container_image: "{{ docker_database_image_full }}"
|
||||||
|
container_name: "mariadb"
|
||||||
|
container_volumes:
|
||||||
|
- "{{ node_config_directory }}/mariadb/:/opt/kolla/mariadb/:ro"
|
||||||
|
container_volumes_from:
|
||||||
|
- "mariadb_data"
|
||||||
|
when: delegate_host == 'None' and inventory_hostname == groups['database'][0]
|
10
ansible/roles/database/tasks/config.yml
Normal file
10
ansible/roles/database/tasks/config.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
- include: ../../config.yml
|
||||||
|
vars:
|
||||||
|
config_source:
|
||||||
|
- "roles/database/templates/galera.cnf.j2"
|
||||||
|
config_template_dest:
|
||||||
|
- "{{ node_templates_directory }}/mariadb/galera.cnf_minimal"
|
||||||
|
config_dest: "{{ node_config_directory }}/mariadb/galera.cnf"
|
@ -1,7 +1,13 @@
|
|||||||
---
|
---
|
||||||
- name: Bringing up mariadb service(s)
|
- include: config.yml
|
||||||
docker_compose:
|
|
||||||
project_name: mariadb
|
- include: bootstrap.yml
|
||||||
compose_file: "{{ koalla_directory }}/compose/mariadb.yml"
|
|
||||||
command: up
|
- include: start.yml
|
||||||
no_recreate: true
|
|
||||||
|
- include: register.yml
|
||||||
|
|
||||||
|
# This will restart the container we initially used to bootstrap the cluster to
|
||||||
|
# make it match the other containers environment-wise. This also prevents a
|
||||||
|
# change from showing up when rerunning the playbooks
|
||||||
|
- include: start.yml
|
||||||
|
18
ansible/roles/database/tasks/register.yml
Normal file
18
ansible/roles/database/tasks/register.yml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
- name: Creating haproxy mysql user
|
||||||
|
mysql_user:
|
||||||
|
login_host: "{{ database_address }}"
|
||||||
|
login_user: "{{ database_user }}"
|
||||||
|
login_password: "{{ database_password }}"
|
||||||
|
name: "haproxy"
|
||||||
|
password: ""
|
||||||
|
host: "%"
|
||||||
|
priv: "*.*:USAGE"
|
||||||
|
register: status
|
||||||
|
until: status|success
|
||||||
|
retries: 10
|
||||||
|
delay: 5
|
||||||
|
|
||||||
|
- name: Cleaning up facts
|
||||||
|
set_fact:
|
||||||
|
delegate_host: "bootstraped"
|
13
ansible/roles/database/tasks/start.yml
Normal file
13
ansible/roles/database/tasks/start.yml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
- include: ../../start.yml
|
||||||
|
vars:
|
||||||
|
container_environment:
|
||||||
|
KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
|
||||||
|
container_image: "{{ docker_database_image_full }}"
|
||||||
|
container_name: "mariadb"
|
||||||
|
container_volumes:
|
||||||
|
- "{{ node_config_directory }}/mariadb/:/opt/kolla/mariadb/:ro"
|
||||||
|
container_volumes_from:
|
||||||
|
- "mariadb_data"
|
||||||
|
when: delegate_host != 'None' or
|
||||||
|
( delegate_host == 'None' and inventory_hostname != groups['database'][0])
|
18
ansible/roles/database/templates/galera.cnf.j2
Normal file
18
ansible/roles/database/templates/galera.cnf.j2
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
[mysqld]
|
||||||
|
bind-address={{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}
|
||||||
|
binlog_format=ROW
|
||||||
|
default-storage-engine=innodb
|
||||||
|
innodb_autoinc_lock_mode=2
|
||||||
|
query_cache_size=0
|
||||||
|
query_cache_type=0
|
||||||
|
innodb_log_file_size=48M
|
||||||
|
|
||||||
|
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
|
||||||
|
wsrep_cluster_address=gcomm://{% for host in groups['database'] %}{{ hostvars[host]['ansible_hostname'] }}{% if not loop.last %},{% endif %}{% endfor %}
|
||||||
|
|
||||||
|
wsrep_cluster_name="{{ database_cluster_name }}"
|
||||||
|
wsrep_node_address={{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}
|
||||||
|
wsrep_node_name={{ ansible_hostname }}
|
||||||
|
wsrep_sst_method=xtrabackup-v2
|
||||||
|
wsrep_sst_auth={{ database_user }}:{{ database_password }}
|
||||||
|
wsrep_slave_threads=4
|
@ -9,22 +9,24 @@
|
|||||||
# docker_api_version from docker-py, so we specify it here. This will be
|
# docker_api_version from docker-py, so we specify it here. This will be
|
||||||
# removed when the bugfix makes it downstream
|
# removed when the bugfix makes it downstream
|
||||||
|
|
||||||
- name: Starting the container
|
- name: Starting container(s)
|
||||||
docker:
|
docker:
|
||||||
|
command: "{{ container_command | default(None) }}"
|
||||||
detach: "{{ container_detach | default('True') }}"
|
detach: "{{ container_detach | default('True') }}"
|
||||||
env: "{{ container_environment }}"
|
env: "{{ container_environment | default(None) }}"
|
||||||
docker_api_version: "{{ docker_api_version }}"
|
docker_api_version: "{{ docker_api_version }}"
|
||||||
image: "{{ container_image }}"
|
image: "{{ container_image }}"
|
||||||
insecure_registry: "{{ docker_insecure_registry }}"
|
insecure_registry: "{{ docker_insecure_registry }}"
|
||||||
name: "{{ container_name }}"
|
name: "{{ container_name }}"
|
||||||
net: host
|
net: "host"
|
||||||
password: "{{ docker_registry_password }}"
|
password: "{{ docker_registry_password }}"
|
||||||
privileged: "{{ container_privileged | default('False') }}"
|
privileged: "{{ container_privileged | default('False') }}"
|
||||||
pull: "{{ docker_pull_policy }}"
|
pull: "{{ docker_pull_policy }}"
|
||||||
registry: "{{ docker_registry }}"
|
registry: "{{ docker_registry }}"
|
||||||
restart_policy: "{{ docker_restart_policy }}"
|
restart_policy: "{{ docker_restart_policy }}"
|
||||||
restart_policy_retry: "{{ docker_restart_policy_retry }}"
|
restart_policy_retry: "{{ docker_restart_policy_retry }}"
|
||||||
state: reloaded
|
state: "reloaded"
|
||||||
username: "{{ docker_registry_username }}"
|
username: "{{ docker_registry_username }}"
|
||||||
volumes: "{{ container_volumes }}"
|
volumes: "{{ container_volumes }}"
|
||||||
|
volumes_from: "{{ container_volumes_from | default([]) }}"
|
||||||
run_once: "{{ run_once | default('False') }}"
|
run_once: "{{ run_once | default('False') }}"
|
||||||
|
@ -21,7 +21,8 @@ RUN echo "[mariadb]" > /etc/yum.repos.d/MariaDB.repo && \
|
|||||||
tar \
|
tar \
|
||||||
expect
|
expect
|
||||||
|
|
||||||
COPY config-galera.sh /opt/kolla/config-galera.sh
|
COPY config-galera.sh /opt/kolla/config/
|
||||||
COPY start.sh /start.sh
|
COPY config-internal.sh config-external.sh /opt/kolla/
|
||||||
|
COPY start.sh /
|
||||||
|
|
||||||
CMD ["/start.sh"]
|
CMD ["/start.sh"]
|
||||||
|
1
docker/centos/binary/galera/config-external.sh
Symbolic link
1
docker/centos/binary/galera/config-external.sh
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../common/galera/config-external.sh
|
1
docker/centos/binary/galera/config-internal.sh
Symbolic link
1
docker/centos/binary/galera/config-internal.sh
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../common/galera/config-internal.sh
|
@ -175,19 +175,19 @@ set_configs() {
|
|||||||
exec /opt/kolla/config-internal.sh
|
exec /opt/kolla/config-internal.sh
|
||||||
;;
|
;;
|
||||||
CONFIG_EXTERNAL_COPY_ALWAYS)
|
CONFIG_EXTERNAL_COPY_ALWAYS)
|
||||||
source /opt/kolla/config-exernal.sh
|
source /opt/kolla/config-external.sh
|
||||||
;;
|
;;
|
||||||
CONFIG_EXTERNAL_COPY_ONCE)
|
CONFIG_EXTERNAL_COPY_ONCE)
|
||||||
if [[ -f /configured ]]; then
|
if [[ -f /configured ]]; then
|
||||||
echo 'INFO - This container has already been configured; Refusing to copy new configs'
|
echo 'INFO - This container has already been configured; Refusing to copy new configs'
|
||||||
return
|
else
|
||||||
|
source /opt/kolla/config-external.sh
|
||||||
|
touch /configured
|
||||||
fi
|
fi
|
||||||
source /opt/kolla/config-exernal.sh
|
|
||||||
touch /configured
|
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
echo '$CONFIG_STRATEGY is not set properly'
|
echo '$KOLLA_CONFIG_STRATEGY is not set properly'
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
8
docker/common/galera/config-external.sh
Normal file
8
docker/common/galera/config-external.sh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Cluster configuration
|
||||||
|
if [[ -f /opt/kolla/mariadb/galera.cnf ]]; then
|
||||||
|
cp /opt/kolla/mariadb/galera.cnf /etc/my.cnf.d/galera.cnf
|
||||||
|
chown mysql: /etc/my.cnf.d/galera.cnf
|
||||||
|
chmod 0600 /etc/my.cnf.d/galera.cnf
|
||||||
|
fi
|
@ -1,13 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
. /opt/kolla/kolla-common.sh
|
|
||||||
|
|
||||||
check_required_vars DB_CLUSTER_BIND_ADDRESS DB_CLUSTER_NAME DB_CLUSTER_NODES \
|
|
||||||
DB_ROOT_PASSWORD DB_CLUSTER_WSREP_METHOD
|
|
||||||
|
|
||||||
CFG=/etc/my.cnf.d/server.cnf
|
|
||||||
DB_CLUSTER_INIT_SQL=/tmp/mysql-first-time.sql
|
|
||||||
|
|
||||||
function configure_files {
|
function configure_files {
|
||||||
crudini --set $CFG mariadb bind-address "${DB_CLUSTER_BIND_ADDRESS}"
|
crudini --set $CFG mariadb bind-address "${DB_CLUSTER_BIND_ADDRESS}"
|
||||||
crudini --set $CFG mariadb binlog_format "ROW"
|
crudini --set $CFG mariadb binlog_format "ROW"
|
||||||
@ -30,8 +22,9 @@ function configure_files {
|
|||||||
crudini --set $CFG mariadb wsrep_sst_method "${DB_CLUSTER_WSREP_METHOD}"
|
crudini --set $CFG mariadb wsrep_sst_method "${DB_CLUSTER_WSREP_METHOD}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function bootstrap_database {
|
function bootstrap_db {
|
||||||
mysqld_safe &
|
mysqld_safe --wsrep-new-cluster &
|
||||||
|
|
||||||
# Waiting for deamon
|
# Waiting for deamon
|
||||||
sleep 10
|
sleep 10
|
||||||
expect -c '
|
expect -c '
|
||||||
@ -54,11 +47,14 @@ function bootstrap_database {
|
|||||||
expect "Reload privilege tables now?"
|
expect "Reload privilege tables now?"
|
||||||
send "y\r"
|
send "y\r"
|
||||||
expect eof'
|
expect eof'
|
||||||
|
|
||||||
|
mysql -u root --password="${DB_ROOT_PASSWORD}" -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY '${DB_ROOT_PASSWORD}' WITH GRANT OPTION;"
|
||||||
|
mysql -u root --password="${DB_ROOT_PASSWORD}" -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '${DB_ROOT_PASSWORD}' WITH GRANT OPTION;"
|
||||||
mysqladmin -p"${DB_ROOT_PASSWORD}" shutdown
|
mysqladmin -p"${DB_ROOT_PASSWORD}" shutdown
|
||||||
}
|
}
|
||||||
|
|
||||||
function configure_db {
|
function configure_db {
|
||||||
bootstrap_database
|
bootstrap_db
|
||||||
|
|
||||||
echo "GRANT ALL ON *.* TO 'root'@'%' IDENTIFIED BY '$DB_ROOT_PASSWORD' ;" > $DB_CLUSTER_INIT_SQL
|
echo "GRANT ALL ON *.* TO 'root'@'%' IDENTIFIED BY '$DB_ROOT_PASSWORD' ;" > $DB_CLUSTER_INIT_SQL
|
||||||
|
|
||||||
@ -81,7 +77,7 @@ function populate_db {
|
|||||||
if [[ $(ls /var/lib/mysql) == "" ]]; then
|
if [[ $(ls /var/lib/mysql) == "" ]]; then
|
||||||
echo "POPULATING NEW DB"
|
echo "POPULATING NEW DB"
|
||||||
mysql_install_db
|
mysql_install_db
|
||||||
chown -R mysql /var/lib/mysql
|
chown -R mysql: /var/lib/mysql
|
||||||
else
|
else
|
||||||
echo "DB ALREADY EXISTS"
|
echo "DB ALREADY EXISTS"
|
||||||
fi
|
fi
|
||||||
|
20
docker/common/galera/config-internal.sh
Executable file
20
docker/common/galera/config-internal.sh
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
. /opt/kolla/kolla-common.sh
|
||||||
|
. /opt/kolla/config-galera.sh
|
||||||
|
|
||||||
|
check_required_vars DB_CLUSTER_BIND_ADDRESS DB_CLUSTER_NAME DB_CLUSTER_NODES \
|
||||||
|
DB_ROOT_PASSWORD DB_CLUSTER_WSREP_METHOD DB_CLUSTER_INIT_DB
|
||||||
|
|
||||||
|
CFG=/etc/my.cnf.d/server.cnf
|
||||||
|
DB_CLUSTER_INIT_SQL=/tmp/mysql-first-time.sql
|
||||||
|
|
||||||
|
prepare_db
|
||||||
|
|
||||||
|
if [[ "${DB_CLUSTER_INIT_DB}" == "true" ]] && ! [[ -a /var/lib/mysql/cluster.exists ]]; then
|
||||||
|
DB_CLUSTER_IS_MASTER_NODE="--wsrep-new-cluster"
|
||||||
|
touch /var/lib/mysql/cluster.exists
|
||||||
|
fi
|
||||||
|
|
||||||
|
mysqld_safe --init-file=$DB_CLUSTER_INIT_SQL $DB_CLUSTER_IS_MASTER_NODE
|
||||||
|
|
@ -1,15 +1,25 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
. /opt/kolla/kolla-common.sh
|
set -o errexit
|
||||||
. /opt/kolla/config-galera.sh
|
|
||||||
|
|
||||||
check_required_vars DB_CLUSTER_INIT_DB
|
CMD="/usr/bin/mysqld_safe"
|
||||||
prepare_db
|
ARGS=""
|
||||||
|
|
||||||
if [[ "${DB_CLUSTER_INIT_DB}" == "true" ]] && ! [[ -a /var/lib/mysql/cluster.exists ]]; then
|
# loading common functions
|
||||||
DB_CLUSTER_IS_MASTER_NODE="--wsrep-new-cluster"
|
source /opt/kolla/kolla-common.sh
|
||||||
|
|
||||||
|
# config-internal script exec out of this function, it does not return here
|
||||||
|
set_configs
|
||||||
|
|
||||||
|
# loading functions
|
||||||
|
source /opt/kolla/config/config-galera.sh
|
||||||
|
|
||||||
|
# This catches all cases of the BOOTSTRAP variable being set, including empty
|
||||||
|
if [[ "${!KOLLA_BOOTSTRAP[@]}" ]] && [[ ! -e /var/lib/mysql/cluster.exists ]]; then
|
||||||
|
ARGS="--wsrep-new-cluster"
|
||||||
touch /var/lib/mysql/cluster.exists
|
touch /var/lib/mysql/cluster.exists
|
||||||
|
populate_db
|
||||||
|
bootstrap_db
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mysqld_safe --init-file=$DB_CLUSTER_INIT_SQL $DB_CLUSTER_IS_MASTER_NODE
|
exec $CMD $ARGS
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user