Ansible幂等MySQL安装剧本(Ansible idempotent MySQL instal

2019-09-02 06:19发布

我想设置在AWS上一个MySQL服务器,使用Ansible的配置管理。 我使用亚马逊(AMI-3275ee5b),它使用默认的AMI yum管理软件包。

当执行下面的剧本,一切顺利。 但是,当我运行它第二次,任务Configure the root credentials失败,因为MySQL的旧密码不匹配了,因为它已被更新的最后一次,我跑了这个剧本。

这使得剧本非幂等的,我不喜欢。 我希望能够运行剧本多次,我想。

- hosts: staging_mysql
  user: ec2-user
  sudo: yes

  tasks:
    - name: Install MySQL
      action: yum name=$item
      with_items:
        - MySQL-python
        - mysql
        - mysql-server

    - name: Start the MySQL service
      action: service name=mysqld state=started

    - name: Configure the root credentials
      action: command mysqladmin -u root -p $mysql_root_password

什么是解决这个的最佳方式,这意味着使剧本幂? 提前致谢!

Answer 1:

我贴这个的coderwall ,但我会重现dennisjac的改善,我原来的职位的意见。

诀窍idempotently做,就知道,如果它发现一个mysql_user模块加载〜/ .my.cnf文件。

我先更改密码,然后.my.cnf文件复制与密码凭据。 当您尝试运行它第二次,myqsl_user ansible模块会发现.my.cnf并使用新密码。

- hosts: staging_mysql
  user: ec2-user
  sudo: yes

  tasks:
    - name: Install MySQL
      action: yum name={{ item }}
      with_items:
        - MySQL-python
        - mysql
        - mysql-server

    - name: Start the MySQL service
      action: service name=mysqld state=started

    # 'localhost' needs to be the last item for idempotency, see
    # http://ansible.cc/docs/modules.html#mysql-user
    - name: update mysql root password for all root accounts
      mysql_user: name=root host={{ item }} password={{ mysql_root_password }} priv=*.*:ALL,GRANT
      with_items:
        - "{{ ansible_hostname }}"
        - 127.0.0.1
        - ::1
        - localhost

    - name: copy .my.cnf file with root password credentials
      template: src=templates/root/.my.cnf dest=/root/.my.cnf owner=root mode=0600

该.my.cnf模板看起来是这样的:

[client]
user=root
password={{ mysql_root_password }}

编辑:作为意见建议Dhananjay内内,并改变变量代换使用括号,而不是美元符号添加权限



Answer 2:

Ansible版本安全​​MySQL安装。

mysql_secure_installation.yml

- hosts: staging_mysql
  user: ec2-user
  sudo: yes

  tasks:
    - name: Install MySQL
      action: yum name={{ item }}
      with_items:
        - MySQL-python
        - mysql
        - mysql-server

    - name: Start the MySQL service
      action: service name=mysqld state=started

    # 'localhost' needs to be the last item for idempotency, see
    # http://ansible.cc/docs/modules.html#mysql-user
    - name: update mysql root password for all root accounts
      mysql_user: name=root host={{ item }} password={{ mysql_root_password }}
      with_items:
        - "{{ ansible_hostname }}"
        - 127.0.0.1
        - ::1
        - localhost

    - name: copy .my.cnf file with root password credentials
      template: src=templates/root/my.cnf.j2 dest=/root/.my.cnf owner=root mode=0600

    - name: delete anonymous MySQL server user for $server_hostname
      action: mysql_user user="" host="{{ server_hostname }}" state="absent"

    - name: delete anonymous MySQL server user for localhost
      action: mysql_user user="" state="absent"

    - name: remove the MySQL test database
      action: mysql_db db=test state=absent

模板/根/ my.cnf.j2

[client]
user=root
password={{ mysql_root_password }}

参考

  • 原来答案由洛林·霍克斯坦
  • https://github.com/gaspaio/ansible-devbox/blob/master/roles/mysql/tasks/server.yml


Answer 3:

这是一种替代解决方案由@LorinHochStein提出的一个

我的一个制约因素是,以确保没有密码采用明文存储的任何地方服务器上的文件。 因此.my.cnf不是一个切合实际的建议

解决方案:

- name: update mysql root password for all root accounts from local servers
  mysql_user: login_user=root 
              login_password={{ current_password }} 
              name=root 
              host=$item 
              password={{ new_password }} 
              priv=*.*:ALL,GRANT
  with_items:
      - $ansible_hostname
      - 127.0.0.1
      - ::1
      - localhost

而在瓦尔文件

current_password: foobar
new_password: "{{ current_password }}"

如果不改变mysql的密码运行命令行照常ansible剧本。

当改变mysql的密码,添加以下命令行。 指定它的命令行允许参数在命令行设置为优先于一个默认为在瓦尔文件。

$ ansible-playbook ........ --extra-vars "new_password=buzzz"

运行该命令后更改瓦尔文件,如下所示

current_password=buzzz
new_password={{ current_password }}


Answer 4:

添加到以前的答案,我不想在运行命令之前手动工序,即我想旋转了一个新的服务器,只是运行的剧本,而不必手动修改root密码第一次。 我不相信{{mysql_password}}将努力在第一时间,当root密码为空,因为mysql_password仍然在某处被定义(除非你想用-e来覆盖它)。

所以我加了一个规则来做到这一点,如果失败,它会被忽略。 这是除,并出现之前,这里的任何其他命令。

- name: Change root user password on first run
  mysql_user: login_user=root
              login_password=''
              name=root
              password={{ mysql_root_password }}
              priv=*.*:ALL,GRANT
              host={{ item }}
      with_items:
        - $ansible_hostname
        - 127.0.0.1
        - ::1
        - localhost
      ignore_errors: true


Answer 5:

对于ansible 1.3+:

- name: ensure mysql local root password is zwx123
  mysql_user: check_implicit_admin=True login_user=root login_password="zwx123" name=root password="zwx123" state=present


Answer 6:

好了,这次来到有点复杂。 我花在这个一整天,并与下面列出的解决方案上来。 关键的一点是如何Ansible安装MySQL服务器。 从该文档mysql_user模块(在页面上最后一个音符):

MySQL server installs with default login_user of ‘root’ and no password. To secure this user as part of an idempotent playbook, you must create at least two tasks: the first must change the root user’s password, without providing any login_user/login_password details. The second must drop a ~/.my.cnf file containing the new root credentials. Subsequent runs of the playbook will then succeed by reading the new credentials from the file.

与空白或空口令问题是一个很大的惊喜。

作用

---

- name: Install MySQL packages
  sudo: yes
  yum: name={{ item }} state=present
  with_items:
    - mysql
    - mysql-server
    - MySQL-python


- name: Start MySQL service
  sudo: yes
  service: name=mysqld state=started enabled=true


- name: Update MySQL root password for root account
  sudo: yes
  mysql_user: name=root password={{ db_root_password }} priv=*.*:ALL,GRANT


- name: Create .my.cnf file with root password credentials
  sudo: yes
  template: src=.my.cnf.j2 dest=/root/.my.cnf owner=root group=root mode=0600
  notify:
  - restart mysql


- name: Create a database
  sudo: yes
  mysql_db: name={{ db_name }}
            collation=utf8_general_ci
            encoding=utf8
            state=present


- name: Create a database user
  sudo: yes
  mysql_user: name={{ db_user }}
              password={{ db_user_password }}
              priv="{{ db_name }}.*:ALL"
              host=localhost
              state=present

处理器

---

- name: restart mysql
  service: name=mysqld state=restarted

.my.cnf.j2:

[client]
user=root
password={{ db_root_password }}


Answer 7:

下面的工作(在mysql_user电话2之间插入的my.cnf)


- name: 'Install MySQL'
    yum: name={{ item }} state=present
    with_items:
    - MySQL-python
    - mysql
    - mysql-server
    notify:
     - restart-mysql
- name: 'Start Mysql Service'
  action: service name=mysqld state=started enabled=yes
- name: 'Update Mysql Root Password'
  mysql_user: name=root host=localhost password={{ mysql_root_password }} state=present
- name: 'Copy Conf file with root password credentials'
  template: src=../templates/my.cnf.j2 dest=/root/.my.cnf owner=root mode=0600
- name: 'Update Rest-Mysql Root Password'
  mysql_user: name=root host={{ item }} password={{ mysql_root_password }} state=present
    with_items:
    - "{{ ansible_hostname }}"
    - "{{ ansible_eth0.ipv4.address }}"
    - 127.0.0.1
    - ::1
- name: 'Delete anonymous MySQL server user from server'
  mysql_user: name="" host={{ ansible_hostname }} state="absent"


Answer 8:

我知道这是一个老问题,但我分享的那些,谁是寻找它我的工作剧本:

mysql.yml

---
 - name: Install the MySQL packages
   apt: name={{ item }} state=installed update_cache=yes
   with_items:
     - mysql-server-5.6
     - mysql-client-5.6
     - python-mysqldb
     - libmysqlclient-dev

 - name: Copy the configuration file (my.cnf)
   template: src=my.cnf.j2 dest=/etc/mysql/my.cnf
   notify:
     - Restart MySQL

 - name: Update MySQL root password for all root accounts
   mysql_user: name=root host={{ item }} password={{ mysql_root_pass }} state=present
   with_items:
     - "{{ ansible_hostname }}"
     - 127.0.0.1
     - ::1
     - localhost

 - name: Copy the root credentials as .my.cnf file
   template: src=root.cnf.j2 dest=~/.my.cnf mode=0600

 - name: Ensure Anonymous user(s) are not in the database
   mysql_user: name='' host={{ item }} state=absent
   with_items:
     - localhost
     - "{{ ansible_hostname }}"

 - name: Remove the test database
   mysql_db: name=test state=absent
   notify:
     - Restart MySQL

vars.yml

---
 mysql_port: 3306 #Default is 3306, please change it if you are using non-standard
 mysql_bind_address: "127.0.0.1" #Change it to "0.0.0.0",if you want to listen everywhere
 mysql_root_pass: mypassword #MySQL Root Password

my.cnf.j2

[client]
port            = 3306
socket          = /var/run/mysqld/mysqld.sock

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

[mysqld]
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = {{ mysql_port }}
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
bind-address            = {{ mysql_bind_address }}
key_buffer              = 16M
max_allowed_packet      = 64M
thread_stack            = 192K
thread_cache_size       = 8
myisam-recover         = BACKUP
query_cache_limit       = 1M
query_cache_size        = 16M
log_error = /var/log/mysql/error.log
expire_logs_days        = 10
max_binlog_size         = 100M

[mysqldump]
quick
quote-names
max_allowed_packet      = 64M

[mysql]

[isamchk]
key_buffer              = 16M

!includedir /etc/mysql/conf.d/

root.cnf.j2

[client]
user=root
password={{ mysql_root_pass }}


Answer 9:

它启动/重新启动之前,设置root密码的MySQL服务器是很重要的。 另外,我已经想尽一切贴上去的这个帖子[日期],发现当务之急是要通过login_passwordlogin_user

(即)设置之后的任何播放mysql_user user:rootpassword= {{ SOMEPASSWORD }}必须连接使用login_passwordlogin_user对于任何后续的播放。

注: with_items下面是基于Ansible及/ MariaDB的默认主机上创建的

例如用于确保MariaDB的服务器:

---
# 'secure_mariadb.yml'

- name: 'Ensure MariaDB server is started and enabled on boot'
  service: name={{ mariadb_service_name }} state=started enabled=yes

# localhost needs to be the last item for idempotency, see
# http://ansible.cc/docs/modules.html#mysql-user
- name: 'Update Mysql Root Password'
  mysql_user: name=root
              host={{ item }}
              password={{ root_db_password }}
              priv=*.*:ALL,GRANT
              state=present
  with_items:
    - 127.0.0.1
    - ::1
    - instance-1 # Created by MariaDB to prevent conflicts between port and sockets if multi-instances running on the same computer.
    - localhost

- name: 'Create MariaDB main configuration file'
  template: >
    src=my.cnf.j2
    dest=/etc/mysql/my.cnf
    owner=root
    group=root
    mode=0600

- name: 'Ensure anonymous users are not in the database'
  mysql_user: login_user=root 
              login_password={{ root_db_password }}
              name=''
              host={{ item }}
              state=absent
  with_items:
    - 127.0.0.1
    - localhost

- name: 'Remove the test database'
  mysql_db: login_user=root 
            login_password={{ root_db_password }}
            name=test
            state=absent

- name: 'Reload privilege tables'
  command: 'mysql -ne "{{ item }}"'
  with_items:
    - FLUSH PRIVILEGES
  changed_when: False

- name: 'Ensure MariaDB server is started and enabled on boot'
  service: name={{ mariadb_service_name }} state=started enabled=yes


# 'End Of File'


Answer 10:

我将我自己取的各种方法(CentOS的7)。

可变mysql_root_password应被存储在ansible-保管库(更好)或命令行传递(差)

- name: "Ensure mariadb packages are installed"
  yum: name={{ item }} state="present"
  with_items:
    - mariadb
    - mariadb-server

- name: "Ensure mariadb is running and configured to start at boot"
  service: name=mariadb state=started enabled=yes

# idempotently ensure secure mariadb installation --
# - attempts to connect as root user with no password and then set the root@ mysql password for each mysql root user mode.
# - ignore_errors is true because this task will always fail on subsequent runs (as the root user password has been changed from "")
- name: Change root user password on first run, this will only succeed (and only needs to succeed) on first playbook run
  mysql_user: login_user=root
              login_password=''
              name=root
              password={{ mysql_root_password }}
              priv=*.*:ALL,GRANT
              host={{ item }}
  with_items:
    - "{{ ansible_hostname }}"
    - 127.0.0.1
    - ::1
    - localhost
  ignore_errors: true

- name: Ensure the anonymous mysql user ""@{{ansible_hostname}} is deleted
  action: mysql_user user="" host="{{ ansible_hostname }}" state="absent" login_user=root login_password={{ mysql_root_password }}

- name: Ensure the anonymous mysql user ""@localhost is deleted
  action: mysql_user user="" state="absent" login_user=root login_password={{ sts_ad_password }}

- name: Ensure the mysql test database is deleted
  action: mysql_db db=test state=absent login_user=root login_password={{ mysql_root_password }}


Answer 11:

我们花了很多时间在这个问题上。 对于MySQL 5.7和上面我们得出的结论很容易简单地忽略root帐户,并定期MySQL用户设置权限。

原因

  1. 设置root密码难
  2. unix_socket身份验证与标准的身份验证插件的插件冲突
  3. 停用后,确实改变了root密码unix_socket插件几乎是不可能的
  4. Ansible不能很好地适合于在一个步骤中以原子方式改变根密码
  5. 使用普通帐户广泛的工作良好

如果你放弃幂等,那么你就可以得到它的工作的罚款。 然而,由于ansible价值主张是幂等是可能的,我们发现开发人员浪费时间与错误的假设。

就像一个黑客选项仅仅存在check_implicit_admin开始提示我们,确定MySQL的设置并不那么容易。 如果它实际上是确定性的,不应该有“检查”,应该只有“做”。



文章来源: Ansible idempotent MySQL installation Playbook