1. 引言
MySQL 是一个广泛使用的开源关系型数据库管理系统,通过使用 Ansible,您可以实现自动化部署和配置 MySQL,简化数据库管理和提高系统可靠性。
2. MySQL 的使用场景
MySQL 在以下场景中特别有用:
2.1 Web 应用程序
MySQL 是 Web 应用程序常用的数据库选择之一。它可以存储和管理应用程序的数据,提供高性能和可靠的数据存储服务。MySQL 支持广泛的编程语言和框架,并提供了强大的查询和数据操作功能。
2.2 大规模应用程序
MySQL 具有良好的可伸缩性和高可用性特性,适用于大规模应用程序。通过使用主从复制、分片和集群等技术,可以构建高性能、可扩展和高可用的 MySQL 架构,满足大型应用程序的需求。
3. 部署 MySQL 8.0
下面是使用 Ansible 部署 MySQL 的最佳实践步骤:
3.1 配置 Host
创建一个名为 deploy-mysql-host.ini 的 Ansible Inventory 文件
[deploy]
aliyun_ecs ansible_ssh_host=47.98.49.189 ansible_ssh_port=22 ansible_user=ecs-user ansible_ssh_pass=Ecs-user123 ansible_sudo_pass=Ecs-user123
3.2 MySQL 配置文件
创建一个名为 my.cnf.j2 的 Ansible Template 文件
[mysqld]
user = ecs-user
basedir = /home/ecs-user/{{ mysql_home_name }}
datadir = /home/ecs-user/datas/mysql
port = 3306
socket = /tmp/mysqlx.sock
pid-file = /home/ecs-user/datas/mysql/mysql.pid
log-error = /home/ecs-user/datas/mysql/mysql-err.log
# sql_mode = "STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER"
max_connections = 2000
character-set-server = utf8mb4
default-storage-engine = INNODB
default-time-zone = '+8:00'
[mysql]
# 客户端默认字符集
default-character-set = utf8mb4
[client]
port = 3306
socket = /tmp/mysqlx.sock
3.3 MySQL 开机启动服务
创建一个名为 mysql-supervisord.j2 的 Ansible Template 文件
[program:MySQL]
directory=/home/ecs-user/{{ mysql_home_name }} ;
command=/home/ecs-user/{{ mysql_home_name }}/bin/mysqld --defaults-file=/home/ecs-user/{{ mysql_home_name }}/etc/my.cnf ;
stopsignal=KILL ;
stderr_logfile=/home/ecs-user/logs/supervisor/supervisor-mysql.err ;
stdout_logfile=/home/ecs-user/logs/supervisor/supervisor-mysql.out ;
stdout_logfile_maxbytes=10MB ;
stdout_logfile_backups=10 ;
user=ecs-user ;
umask=022 ;
autostart=true ;
autorestart=true ;
startsecs=10 ;
startretries=3 ;
stopasgroup=true ;
killasgroup=true ;
redirect_stderr=false ;
3.4 创建 Playbook
创建一个名为 deploy-mysql.yml 的 Ansible Playbook 文件,并使用文本编辑器打开。在 Playbook 中,定义以下任务:
---
- name: 安装 MySQL
hosts: deploy
become: true
vars:
mysql_version: 8.0.34
mysql_home_name: "mysql-8.0.34-linux-glibc2.12-x86_64"
mysql_tar_name: "{{ mysql_home_name }}.tar.xz"
mysql_root_password: MySQL#123456
tasks:
- name: 下载 Linux 通用包
ansible.builtin.get_url:
url: "http://i-ansible.oss-cn-hangzhou-internal.aliyuncs.com/{{ mysql_tar_name }}"
validate_certs: false
dest: "/tmp/{{ mysql_tar_name }}"
mode: "0755"
force: true
owner: ecs-user
group: ecs-user
- name: 解压 Linux 通用包
ansible.builtin.unarchive:
src: /tmp/{{ mysql_tar_name }}
dest: /home/ecs-user
remote_src: true
owner: ecs-user
group: ecs-user
- name: 安装 MySQL 依赖包
ansible.builtin.apt:
name: "{{ item }}"
state: present
with_items:
- libaio
when: ansible_os_family == 'Debian'
- name: 安装 MySQL 依赖包
ansible.builtin.yum:
name: "{{ item }}"
state: present
with_items:
- libaio
when: ansible_os_family == 'RedHat'
- name: RM DATA
ansible.builtin.command:
cmd: rm -rf "/home/ecs-user/datas/mysql"
changed_when: false
- name: 创建 MySQL DATA & LOG
ansible.builtin.file:
name: "{{ item }}"
state: directory
mode: "0755"
owner: ecs-user
group: ecs-user
with_items:
- "/home/ecs-user/logs/mysql"
- "/home/ecs-user/logs/supervisor"
- "/home/ecs-user/datas/mysql"
- "/home/ecs-user/{{ mysql_home_name }}/etc"
- name: 之前遗留的创建配置目录
ansible.builtin.file:
name: "{{ item }}"
state: directory
mode: "0755"
owner: root
group: root
with_items:
- "/etc/supervisord.d/conf.d"
- name: 复制启动文件
ansible.builtin.template:
src: "{{ item }}.j2"
dest: "/etc/supervisord.d/conf.d/{{ item }}"
mode: "0755"
owner: root
group: root
with_items:
- mysql-supervisord.ini
- name: 复制MySQL配置文件
ansible.builtin.template:
src: "{{ item }}.j2"
dest: "/home/ecs-user/{{ mysql_home_name }}/etc/{{ item }}"
mode: "0755"
owner: ecs-user
group: ecs-user
with_items:
- my.cnf
- name: 数据库初始化 8.0.33
ansible.builtin.command:
chdir: "/home/ecs-user/{{ mysql_home_name }}/bin"
cmd: "./mysqld --initialize --console --user=ecs-user --basedir=/home/ecs-user/{{ mysql_home_name }} --datadir=/home/ecs-user/datas/mysql"
register: mysql_initialize_output
changed_when: false
- name: Extract the temporary password
ansible.builtin.set_fact:
temp_password: "{{ mysql_initialize_output.stderr_lines[-1] | regex_search('temporary password(.*): \\s*(.*)', '\\2') }}"
- name: Print the password
ansible.builtin.debug:
var: temp_password
- name: 更新启动文件
ansible.builtin.command:
chdir: /tmp
cmd: /usr/bin/supervisorctl -c /etc/supervisord.d/supervisor.conf update
changed_when: false
- name: 重启
ansible.builtin.command:
chdir: /tmp
cmd: "/usr/bin/supervisorctl -u admin -p 123456 restart MySQL"
changed_when: false
- name: 检查端口是否运行
ansible.builtin.wait_for:
port: 3306
state: started
delay: 1
timeout: 30
- name: 重置密码
ansible.builtin.command:
chdir: "/home/ecs-user/{{ mysql_home_name }}"
cmd: ./bin/mysql -uroot -S /tmp/mysqlx.sock -p'{{ temp_password[0] }}' -e "{{ item }}" --connect-expired-password
with_items:
- ALTER USER 'root'@'localhost' IDENTIFIED BY '{{ mysql_root_password }}';
changed_when: false
become_user: ecs-user
- name: 设置root访问权限
ansible.builtin.command:
chdir: "/home/ecs-user/{{ mysql_home_name }}"
cmd: ./bin/mysql -uroot -S /tmp/mysqlx.sock -p'{{ mysql_root_password }}' -e "{{ item }}"
with_items:
- CREATE USER 'root'@'%' IDENTIFIED BY '{{ mysql_root_password }}';
- GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
- FLUSH PRIVILEGES;
no_log: true
changed_when: false
- name: 测试mysql服务
ansible.builtin.command:
chdir: "/home/ecs-user/{{ mysql_home_name }}"
cmd: ./bin/mysql -uroot -S /tmp/mysqlx.sock -p'{{ mysql_root_password }}' -e "select version();"
register: mysql_info
changed_when: false
- name: 打印mysql版本
ansible.builtin.debug:
var: mysql_info.stdout_lines
changed_when: false
上述 Playbook 定义了以下任务:
- 安装 MySQL 依赖包,根据操作系统类型使用对应的包管理器。
- 启动并设置 MySQL 服务。
3.5 执行 Ansible Playbook
在终端中,导航到包含 Playbook 的目录,并运行以下命令来执行 Ansible Playbook:
$ ansible-playbook deploy-mysql-8.yml -i deploy-mysql-host.ini
PLAY [安装 MySQL] ******************************************************************************
TASK [Gathering Facts] *************************************************************************
ok: [aliyun_ecs]
TASK [下载 Linux 通用包] ***********************************************************************
changed: [aliyun_ecs]
TASK [解压 Linux 通用包] ***********************************************************************
changed: [aliyun_ecs]
TASK [安装 MySQL 依赖包] ***********************************************************************
skipping: [aliyun_ecs] => (item=libaio)
skipping: [aliyun_ecs]
TASK [安装 MySQL 依赖包] ***********************************************************************
ok: [aliyun_ecs] => (item=libaio)
TASK [RM DATA] *********************************************************************************
ok: [aliyun_ecs]
TASK [创建 MySQL DATA & LOG] *******************************************************************
ok: [aliyun_ecs] => (item=/home/ecs-user/logs/mysql)
ok: [aliyun_ecs] => (item=/home/ecs-user/logs/supervisor)
changed: [aliyun_ecs] => (item=/home/ecs-user/datas/mysql)
changed: [aliyun_ecs] => (item=/home/ecs-user/mysql-8.0.34-linux-glibc2.12-x86_64/etc)
TASK [之前遗留的创建配置目录] ******************************************************************
ok: [aliyun_ecs] => (item=/etc/supervisord.d/conf.d)
TASK [复制启动文件] ****************************************************************************
ok: [aliyun_ecs] => (item=mysql-supervisord.ini)
TASK [复制MySQL配置文件] ***********************************************************************
changed: [aliyun_ecs] => (item=my.cnf)
TASK [数据库初始化 8.0.33] *********************************************************************
ok: [aliyun_ecs]
TASK [Extract the temporary password] **********************************************************
ok: [aliyun_ecs]
TASK [Print the password] **********************************************************************
ok: [aliyun_ecs] => {
"temp_password": [
"1p53He&&r_1m"
]
}
TASK [更新启动文件] ****************************************************************************
ok: [aliyun_ecs]
TASK [重启] ************************************************************************************
ok: [aliyun_ecs]
TASK [检查端口是否运行] ************************************************************************
ok: [aliyun_ecs]
TASK [重置密码] ********************************************************************************
ok: [aliyun_ecs] => (item=ALTER USER 'root'@'localhost' IDENTIFIED BY 'MySQL#123456';)
TASK [设置root访问权限] ************************************************************************
ok: [aliyun_ecs] => (item=None)
ok: [aliyun_ecs] => (item=None)
ok: [aliyun_ecs] => (item=None)
ok: [aliyun_ecs]
TASK [测试mysql服务] ***************************************************************************
ok: [aliyun_ecs]
TASK [打印mysql版本] ***************************************************************************
ok: [aliyun_ecs] => {
"mysql_info.stdout_lines": [
"version()",
"8.0.34"
]
}
PLAY RECAP *************************************************************************************
aliyun_ecs : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Ansible 将在目标主机上安装 MySQL 并启动服务。您可以检查目标主机上的 MySQL 进程和服务状态,确保一切正常。
3.6 客户端工具测试
4. 结论
本文介绍了使用 Ansible 部署 MySQL 的最佳实践。通过自动化配置和部署 MySQL,您可以简化数据库管理过程,提高系统的可靠性和稳定性。使用 Ansible Playbook,您可以定义安装和配置任务,并在目标主机上执行。这种自动化方式能够节省时间和减少手动操作的出错风险。希望这篇文章对您有所帮助!如果您有任何其他问题,请随时提问。