책임감 있는 MySQL 설치 플레이북
구성 관리를 위해 Ansible을 사용하여 AWS에 MySQL 서버를 설정하고 싶습니다.나는 아마존의 기본 AMI(ami-3275ee5b)를 사용하고 있으며, 이는yum
패키지 관리를 위해.
아래 Playbook을 실행하면 모든 것이 잘 진행됩니다.하지만 두 번째로 실행하면 작업을 수행합니다.Configure the root credentials
MySQL의 이전 암호가 마지막으로 이 Playbook을 실행했을 때 업데이트되었기 때문에 더 이상 일치하지 않습니다.
이것은 플레이북을 동일시하지 않게 만들고, 저는 그것을 좋아하지 않습니다.Playbook을 원하는 횟수만큼 실행할 수 있기를 원합니다.
- 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을 동일하게 만드는 것입니다.잘 부탁드립니다!
나는 이것에 대해 코더월에 게시했지만, 나는 원래 게시물의 댓글에서 데니스잭의 개선점을 재현할 것입니다.
mysql_user 모듈이 파일을 찾으면 ~/.my.cnf 파일을 로드한다는 것을 아는 것이 이를 잠재적으로 수행하는 비결입니다.
먼저 암호를 변경한 다음 암호 자격 증명이 있는 .my.cnf 파일을 복사합니다.두 번째 실행을 시도하면 myqsl_user answible 모듈이 .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 }}
Edit : 댓글에 Dhanjay Nene님의 추천으로 권한을 추가하였으며, 변수 보간법을 달러 기호 대신 중괄호를 사용하도록 변경하였습니다.
안전한 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 }}
레퍼런스
이것은 @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
그리고 vars 파일에서.
current_password: foobar
new_password: "{{ current_password }}"
mysql 암호를 변경하지 않으면 평소와 같이 명령줄에서 건전한 플레이북을 실행합니다.
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
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.
빈 암호 또는 null 암호에 대한 문제는 큰 놀라움이었습니다.
역할:
---
- 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 설치에 사용해 보십시오.
호스트: slave.server.com 가 됨: 예
작업:
이름: "Repo 설치 중" 셸: sudo rpm -Uvh http://dev.mysql.com/get/mysql57-community-release-el6-7.noarch.rpm ignore_filename: 예
이름: "MySQL 5.7 설치" 패키지: name=syslog-community-server state=present
name: MySQL 서비스 시작: name: mysqld state: started enabled: yes
shell: "": "MySQL": "echo"
grep 'temporary.*root@localhost' /var/log/mysqld.log | sed 's/.*root@localhost: //'
파일: mysql_root_pass
이것이 오래된 질문이라는 것을 알지만, 저는 그것을 찾고 있는 사람들을 위해 제 작업 전략을 공유합니다.
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 }}
루트 암호를 설정하기 전에 mysql 서버를 시작/재시작하는 것이 중요합니다.또한, 저는 이 게시물[날짜]까지 게시된 모든 것을 시도했고 합격하는 것이 필수적이라는 것을 알게 되었습니다.login_password
그리고.login_user
.
(예:) 의 모든 Playsmysql_user
user:root
그리고.password= {{ SOMEPASSWORD }}
다음을 사용하여 연결해야 합니다.login_password
그리고.login_user
다음 플레이를 위해.
참고: 아래는 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'
저는 다양한 접근법(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 }}
우리는 이 문제에 많은 시간을 보냈습니다.MySQL 5.7 이상의 경우 단순히 루트 계정을 무시하고 일반 MySQL 사용자에게 권한을 설정하는 것이 더 쉽다는 결론을 내렸습니다.
이유들
- 루트 암호 설정이 어렵습니다.
unix_socket
auth 플러그인이 표준 auth 플러그인과 충돌합니다.- 사용하지 않도록 설정한 후 루트 암호를 안정적으로 변경
unix_socket
플러그인이 거의 불가능합니다. - Ansible은 루트 암호를 한 번에 원자적으로 변경하는 데 적합하지 않습니다.
- 일반 계정을 광범위하게 사용하는 것이 효과적입니다.
만약 당신이 동일한 능력을 포기한다면, 당신은 그것을 잘 작동시킬 수 있습니다.그러나 타당한 가치 제안은 동일성이 가능하다는 것이기 때문에, 우리는 개발자들이 잘못된 가정으로 시간을 낭비한다는 것을 발견했습니다.
해킹 옵션이 존재하는 것만으로도check_implicit_admin
결정론적인 MySQL 설정이 그렇게 쉽지 않다는 것을 암시하기 시작합니다.만약 그것이 실제로 결정론적이라면, "체크"는 없어야 하고, "실행"만 있어야 합니다.
저는 Ansible 2.9.20을 사용하고 있으며 버전 8.0.26의 mysql 설치를 위한 플레이북을 만들었습니다.이 mysql 버전 설치에 대한 몇 가지 변경 사항이 있으므로, 여기에 저에게 효과적인 솔루션을 추가하십시오.
MySQL.yml
---
# tasks file for mysql_setup
- name: Upgrade all packages
yum:
name: "*"
state: latest
- name: Install MySQL repository
yum:
name: "https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm"
state: present
- name: Install MySQL
yum:
name: ['mysql-community-devel*', 'mysql-community-server*', 'MySQL-python']
state: present
- name: copy my.cnf
copy:
src: ../files/etc/my.cnf
dest: /etc/my.cnf
mode: 0644
- name: Enable the MySQL service
service:
name: mysqld
state: restarted
enabled: true
- name: Read secret file
include_vars: "defaults/secret.yml"
- name: get root password
shell: "grep 'A temporary password is generated for root@localhost' /var/log/mysqld.log | awk -F ' ' '{print $(NF)}'"
register: root_password
- name: Ensure root can login into MySQL localhost using temporary password
shell: "mysql -uroot -p'{{ root_password.stdout }}' --connect-expired-password"
with_items:
- 127.0.0.1
- ::1
- localhost
register: root_login_tmp_pass
ignore_errors: yes
- name: update expired root user password
command: mysql --user root --password={{ root_password.stdout }} --connect-expired-password --execute="ALTER USER 'root'@'localhost' IDENTIFIED BY '{{ secret.passwd_mysql_root }}';"
when: root_login_tmp_pass is succeeded
- name: update root user password
command: mysql --user root --password={{ secret.current_passwd_mysql_root }} --execute="ALTER USER 'root'@'localhost' IDENTIFIED BY '{{ secret.passwd_mysql_root }}';"
when: root_login_tmp_pass is failed
- name: Copy root .my.cnf file
template:
src: ../templates/root-my.cnf.j2
dest: /root/.my.cnf
owner: root
group: root
mode: 0600
- name: Create a database
mysql_db: name={{ db_name }}
collation=utf8_general_ci
encoding=utf8
state=present
- name: Create a database user
mysql_user: name={{ db_user }}
password={{ secret.db_user_password }}
priv="{{ db_name }}.*:ALL"
host=localhost
state=present
템플릿/root-my.cnf.j2
[client]
user=root
password={{ secret.passwd_mysql_root }}
파일/etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
default-authentication-plugin=mysql_native_password
defaults/main.yml
---
# defaults file for mysql_setup
db_name: mydb
db_user: iamuser
defaults/secret.yml
secret:
passwd_mysql_root: RootPassword2!3
db_user_password: iamdbpassword
current_passwd_mysql_root: currRootPass2!3
이 플레이북을 두 번 실행한 후에는 현재 암호(current_passwd_mysql_root)와 설정할 루트 암호(passwd_mysql_root)로 이 secret.yml 파일을 업데이트해야 합니다.
언급URL : https://stackoverflow.com/questions/16444306/ansible-idempotent-mysql-installation-playbook
'programing' 카테고리의 다른 글
Maria에서 고유한 값을 가진 쿼리를 제한하려면 어떻게 합니까?DB (0) | 2023.08.23 |
---|---|
Nodejs 이벤트 루프 (0) | 2023.08.23 |
응용 프로그램의 설정 번들에 응용 프로그램 버전 버전을 표시하려면 어떻게 해야 합니까? (0) | 2023.08.23 |
drop_certificates가 판다에서 작동하지 않습니까? (0) | 2023.08.18 |
Yarn의 로컬 경로로 패키지를 설치하는 방법은 무엇입니까?패키지를 찾을 수 없습니다. (0) | 2023.08.18 |