实战案例: 利用ansible 的 playbook 批量部署MySQL5.7 或8.0
案例1: 利用register 注册变量批量部署MySQL5.7 或8.0
[root@centos8 ~]#mkdir -p /data/ansible/files
[root@centos8 ~]#cd /data/ansible
[root@centos8 ansible]#tree
.
├── files
│ ├── my.cnf
│ ├── mysql-5.7.33-linux-glibc2.12-x86_64.tar.gz
│ └── mysql-8.0.23-linux-glibc2.12-x86_64.tar.xz
└── install_mysql5.7or8.0.yml
1 directory, 4 files
[root@centos8 ansible]#cat files/my.cnf
[mysqld]
server-id=1
log-bin
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
[client]
socket=/data/mysql/mysql.sock
[root@centos8 ansible]#cat install_mysql5.7or8.0.yml
---
# install mysql-5.7.33-linux-glibc2.12-x86_64.tar.gz
# install mysql-8.0.23-linux-glibc2.12-x86_64.tar.xz
- hosts: dbsrvs
remote_user: root
gather_facts: no
vars:
mysql_version: 5.7.33
mysql_file: mysql-{{mysql_version}}-linux-glibc2.12-x86_64.tar.gz
mysql_root_password: test@123
tasks:
- name: install packages
yum:
name:
- libaio
- numactl-libs
- MySQL-python
state: latest
- name: create mysql group
group: name=mysql gid=306
- name: create mysql user
user: name=mysql uid=306 group=mysql shell=/sbin/nologin system=yes
create_home=no home=/data/mysql
- name: copy tar to remote host and file mode
unarchive: src=/data/ansible/files/{{mysql_file}} dest=/usr/local/
owner=root group=root
- name: create linkfile /usr/local/mysql
file: src=/usr/local/mysql-{{ mysql_version }}-linux-glibc2.12-x86_64
dest=/usr/local/mysql state=link
- name: data dir
shell: /usr/local/mysql/bin/mysqld --initialize --user=mysql --
datadir=/data/mysql
tags: data
- name: config my.cnf
copy: src=/data/ansible/files/my.cnf dest=/etc/my.cnf
- name: service script
shell: /bin/cp /usr/local/mysql/support-files/mysql.server
/etc/init.d/mysqld
- name: PATH variable
copy: content='PATH=/usr/local/mysql/bin:$PATH'
dest=/etc/profile.d/mysql.sh
- name: enable service
shell: chkconfig --add mysqld;/etc/init.d/mysqld start
tags: service
- name: get password
shell: awk '/A temporary password/{print $NF}' /data/mysql/mysql.log
register: password
- name: change password
#debug:
# msg: "{{ password.stdout }}"
shell: /usr/local/mysql/bin/mysqladmin -uroot -p'{{password.stdout}}'
password {{mysql_root_password}}
[root@centos8 ansible]#ansible-playbook install_mysql5.7or8.0.yml
#注意:第一次执行无法修改密码,需要在目标主机上执行下面操作后再一次playbook
[root@centos8 ansible]#ansible dbsrvs -m shell -a "service mysqld stop ;rm -rf
/data/mysql/*"
#再次执行成功
[root@centos8 ansible]#ansible-playbook install_mysql5.7or8.0.yml
template模板
模板是一个文本文件,可以做为生成文件的模版,并且模板文件中还可嵌套jinja2语法
template功能:可以根据和参考模块文件,动态生成相类似的配置文件
template文件必须存放于templates目录下,且命名为 .j2 结尾
yaml/yml 文件需和templates目录平级,目录结构如下示例:
./
├── temnginx.yml
└── templates
└── nginx.conf.j2
#准备templates/nginx.conf.j2文件
[root@ansible ~]#vim temnginx.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
[root@ansible ~]#ansible-playbook temnginx.yml
template变更替换
#修改文件nginx.conf.j2
[root@ansible ~]#mkdir templates
[root@ansible ~]#vim templates/nginx.conf.j2
......
worker_processes {{ ansible_processor_vcpus }};
......
[root@ansible ~]#vim temnginx2.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: install nginx
yum: name=nginx
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: start service
service: name=nginx state=started enabled=yes
[root@ansible ~]#ansible-playbook temnginx2.yml
template算术运算
vim nginx.conf.j2
worker_processes {{ ansible_processor_vcpus**2 }};
worker_processes {{ ansible_processor_vcpus+2 }};
[root@ansible ansible]#vim templates/nginx.conf.j2
worker_processes {{ ansible_processor_vcpus**3 }};
[root@ansible ansible]#cat templnginx.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: install nginx
yum: name=nginx
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart nginx
- name: start service
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx
service: name=nginx state=restarted
[root@ansible ~]#-playbook templnginx.yml --limit 10.0.0.8
template
中使用流程控制
for
和
if
示例:
{% for i in range(1,10) %}
server_name web{{i}};
{% endfor %}
{% for i in range(1,10) %}
server_name web{{i}};
{% endfor %}
#nginx.conf5.j2
upstream webservers {
{% for in range(1,11) %}
server 10.0.0.{{i}}:{{http_port}}
{% endfor %}
server {
listen {{http_port}};
server_name {{server_name}};
location / {
proxy_pass http://webservers;
}
}
#templnginx5.yml
- hosts: websrvs
vars:
http_port: 80
server_name: test
tasks:
- name:install nginx
yum: name=nginx
- name: config file
template: src=nginx.conf5.j2 dest=/etc/nginx/conf.d/web_proxy.conf
- name: start nginx
service: name=nginx state=started
迭代嵌套子变量
[root@ansible ~]#cat with_item2.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: add some groups
group: name={{ item }} state=present
with_items:
- g1
- g2
- g3
- name: add some users
user: name={{ item.name }} group={{ item.group }} home={{ item.home }}
create_home=yes state=present
with_items:
- { name: 'user1', group: 'g1', home: '/data/user1' }
- { name: 'user2', group: 'g2', home: '/data/user2' }
- { name: 'user3', group: 'g3', home: '/data/user3' }
playbook使用 when
---
- hosts: websrvs
tasks :
- name: Check nginx Service #检查nginx服务是否是活动的
command: systemctl is-active nginx
ignore_ errors: yes
register: check_nginx
- name: Httpd Restart #如果check nginx执行命令结果成功,即check_nginx.rc等于0,则执
行重启nginx,否则跳过
service: name=nginx state=restarted
when: check_nginx.rc == 0
---
- hosts: websrvs
remote_user: root
tasks:
- name: "shutdown RedHat flavored systems"
command: /sbin/shutdown -h now
when: ansible_os_family == "RedHat"
---
- hosts: websrvs
remote_user: root
tasks:
- name: "shutdown RedHat flavored systems"
command: /sbin/shutdown -h now
when: ansible_os_family == "RedHat"
changed_when 检查task返回结果,决定是否继续向下执行
[root@ansible ansible]#cat test_changed_when.yml
---
- hosts: websrvs
tasks:
- name: install nginx
yum: name=nginx
- name: config file
template: src="nginx.conf.j2" dest="/etc/nginx/nginx.conf"
notify: restart nginx
- name: check config
shell: /usr/sbin/nginx -t
register: check_nginx_config
changed_when:
- (check_nginx_config.stdout.find('successful')) #如果执行结果中有
successful字符串,则继续执行,如果没有则停止向下执行
- false #nginx -t 每次成功执行是
changed状态,关闭此changed状态
- name: start service
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx
service: name=nginx state=restarted
创建 role
roles/project/ :项目名称,有以下子目录
files/ :存放由copy或script模块等调用的文件
templates/:template模块查找所需要模板文件的目录
tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其它的文件需要在此
文件中通过include进行包含
handlers/:至少应该包含一个名为main.yml的文件;此目录下的其它的文件需要在此文件中通过
include进行包含
vars/:定义变量,至少应该包含一个名为main.yml的文件;此目录下的其它的变量文件需要在此
文件中通过include进行包含
meta/:定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件,其它文
件需在此文件中通过include进行包含
default/:设定默认变量时使用此目录中的main.yml文件,比vars的优先级低
1 创建role的目录结构.在以roles命名的目录下分别创建以各角色名称命名的目录,如mysql等,在每个角
色命名的目录中分别创建相关的目录和文件,比如tasks、files、handlers、templates和vars等目录;
用不到的目录可以创建为空目录,也可以不创建
2 编写和准备role的功能文件
3 编写playbook文件调用需要的角色应用于指定的主机
[root@ansible ansible]#ansible-galaxy init test_role
- Role test_role was created successfully
[root@ansible ansible]#tree test_role/
test_role/
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
nginx-role目录结构
nginx-role.yml
roles/
└── nginx
├── files
│ └── nginx.conf
├── tasks
│ ├── groupadd.yml
│ ├── install.yml
│ ├── main.yml
│ ├── restart.yml
│ └── useradd.yml
└── vars
└── main.yml
Nginx role编排
[root@ansible ~]#mkdir -pv
/data/ansible/roles/nginx/{tasks,handlers,templates,vars}
#创建task文件
[root@ansible ~]#cd /data/ansible/roles/nginx/
[root@ansible nginx]#vim tasks/main.yml
- include: install.yml
- include: config.yml
- include: index.yml
- include: service.yml
[root@ansible nginx]#vim tasks/install.yml
- name: install
yum: name=nginx
[root@ansible nginx]#vim tasks/config.yml
- name: config file for centos7
template: src=nginx7.conf.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version=="7"
notify: restart
- name: config file for centos8
template: src=nginx8.conf.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version=="8"
notify: restart
#跨角色调用文件
[root@ansible nginx]#vim tasks/index.yml
- name: index.html
copy: src=roles/httpd/files/index.html dest=/usr/share/nginx/html/
[root@ansible nginx]#vim tasks/service.yml
- name: start service
service: name=nginx state=started enabled=yes
#创建handler文件
[root@ansible nginx]#cat handlers/main.yml
- name: restart
service: name=nginx state=restarted
#创建两个template文件
[root@ansible nginx]#cat templates/nginx7.conf.j2
...省略...
user {{user}};
worker_processes {{ansible_processor_vcpus+3}}; #修改此行
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
...省略...
[root@ansible nginx]#cat templates/nginx8.conf.j2
...省略...
user {{user}};
worker_processes {{ansible_processor_vcpus**3}}; #修改此行
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
...省略...
#创建变量文件
[root@ansible nginx]#vim vars/main.yml
user: daemon
#目录结构如下
[root@ansible ~]#tree /data/ansible/roles/nginx/
/data/ansible/roles/nginx/
├── handlers
│ └── main.yml
├── tasks
│ ├── config.yml
│ ├── file.yml
│ ├── install.yml
│ ├── main.yml
│ └── service.yml
├── templates
│ ├── nginx7.conf.j2
│ └── nginx8.conf.j2
└── vars
└── main.yml
4 directories, 9 files
#在playbook中调用角色
[root@ansible ~]#vim /data/ansible/role_nginx.yml
---
#nginx role
- hosts: websrvs
roles:
- role: nginx
#运行playbook
[root@ansible ~]#ansible-playbook /data/ansible/role_nginx.yml