Ansibleを構成管理に使用して、AWSにMySQLサーバーをセットアップしたい。 AmazonのデフォルトAMI(AMI-3275ee5b)を使用しています。これは、パッケージ管理にyum
を使用します。
以下のプレイブックを実行すると、すべてうまくいきます。しかし、2回目に実行すると、タスクConfigure the root credentials
は失敗します。これは、このPlaybookを前回実行したときに更新されていたため、MySQLの古いパスワードが一致しなくなったためです。
これにより、Playbookはide等ではなくなりますが、これは好ましくありません。プレイブックを何度でも実行できるようにしたい。
- 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
これを解決する最良の方法は何ですか?つまり、Playbookをi等にすることです?前もって感謝します!
- 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
[client]
user=root
password={{ mysql_root_password }}
これについて coderwall に投稿しましたが、元の投稿のコメントでdennisjacの改善を再現します。
それをdem等に行う秘trickは、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 Neneの推奨するコメントに特権を追加し、変数補間を変更してドル記号の代わりに中括弧を使用しました。
これは、@ LorinHochSteinが提案するソリューションの代替ソリューションです
私の制約の1つは、パスワードがサーバー上のどこにでもプレーンテキストファイルに保存されないようにすることでした。したがって、.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
そして、varsファイルで
current_password: foobar
new_password: "{{ current_password }}"
Mysqlのパスワードを変更しない場合は、通常どおりコマンドラインでansible Playbookを実行します。
Mysqlのパスワードを変更する場合、コマンドラインに次を追加します。コマンドラインで指定すると、コマンドラインで設定されたパラメーターが、varsファイルでデフォルト設定されているパラメーターよりも優先されます。
$ ansible-playbook ........ --extra-vars "new_password=buzzz"
コマンドを実行した後、次のようにvarsファイルを変更します
current_password=buzzz
new_password={{ current_password }}
前の回答に加えて、コマンドを実行する前に手動の手順が必要ではありませんでした。つまり、新しいサーバーを起動し、最初にルートパスワードを手動で変更せずにプレイブックを実行するだけです。ルートパスワードがnullの場合、{{mysql_password}}が最初に機能するとは思われません。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
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
まあ、これは少し複雑になりました。私はこれに丸一日を費やし、以下にリストされたソリューションを思いつきました。重要な点は、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 }}
以下が機能します(2つのmysql_user呼び出しの間に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"
ルートパスワードを設定する前に、mysqlサーバーを起動/再起動することが重要です。また、この投稿[日付]までに投稿されたすべてを試してみましたが、login_password
とlogin_user
を渡すことが不可欠であることがわかりました。
(つまり)mysql_user
user:root
およびpassword= {{ SOMEPASSWORD }}
を設定した後のすべての再生、その後の再生にはlogin_password
およびlogin_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'
私たちはこの問題に多くの時間を費やしました。 MySQL 5.7以降では、ルートアカウントを単純に無視し、通常のMySQLユーザーにアクセス許可を設定する方が簡単だと結論付けました。
unix_socket
認証プラグインが標準認証プラグインと競合していますunix_socket
プラグインを無効にした後にルートパスワードを確実に変更することはほとんど不可能ですべき等性を放棄すると、正常に機能するようになります。しかし、無理のない価値提案はi等性が可能であるということなので、開発者は間違った仮定で時間を浪費することがわかります。
check_implicit_admin
のようなハックオプションが存在するだけで、決定論的なMySQLセットアップはそれほど簡単ではないことが示唆され始めます。それが実際に決定論的である場合、「チェック」はなく、「実行」のみが行われるべきです。
私はこれが古い質問であることを知っていますが、それを探している人たちのために私の作業プレイブックを共有しています:
---
- 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
---
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
[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/
[client]
user=root
password={{ mysql_root_pass }}
さまざまなアプローチについて独自の見解を追加しています(centos 7)。
変数mysql_root_passwordは、ansible-vaultに保存する(より良い)か、コマンドラインで渡す(より悪い)必要があります
- 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 }}