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 客户端工具测试

ansible部署redis 端口写法_ansible

ansible部署redis 端口写法_ansible_02

4. 结论

本文介绍了使用 Ansible 部署 MySQL 的最佳实践。通过自动化配置和部署 MySQL,您可以简化数据库管理过程,提高系统的可靠性和稳定性。使用 Ansible Playbook,您可以定义安装和配置任务,并在目标主机上执行。这种自动化方式能够节省时间和减少手动操作的出错风险。希望这篇文章对您有所帮助!如果您有任何其他问题,请随时提问。