一、PlayBook介绍
1.什么是playbook
playbook 顾名思义,即剧本,现实生活中演员按照剧本表演,在 ansible 中,由被控计算机表演,进行安装,部署应用,提供对外的服务等,以及组织计算机处理各种各样的事情。
playbook 是 ansible 用于配置,部署,和管理节点的剧本通过 playbook 的详细描述,执行其中的-些列 tasks,可以让远端的主机达到预期的状态。playbook 就像 ansible 控制器给被控节点列出的一系列 to-do-list,而且被控节点必须要完成。
2.Ansible playbook 使用场景
执行一些简单的任务,使用 ad-hoc 命令可以方便的解决问题,但是有时一个设施过于复杂,需要大量的操作的时候,执行的 ad-hoc 命令是不合适的,这时候最好使用 playbook。
就像执行 shell 命令与写 shell脚本一样,也可以理解为批处理任务,不过 playbook 有自己的语法格式使用 playbook 可以方便的重复使用这些代码,可以移植到不同的机器上面,像函数一样,最大化的利用代码。在你使用 Ansible 的过程中,你也会发现,你所处理的大部分操作都是编写 playbook。可以把常见的应用都编写为 playbook,之后管理服务器会变得很简单。
二、Playbook的组成
Playbook 是由一个或多个"play"组成的列表,主要功能在于通过将 task 定义好的角色归并为组进行统一管理,也就是通过 Task 调用 Ansible 的模板将多个"play"组织在一个 Playbook 中运行。
Playbook 本身由以下几部分组成:
- Tasks:任务,即调用模块完成的某操作;
- Variables:变量;
- Templates:模板;
- Handlers:处理器,某条件满足时,触发执行的操作; ['hendla(r)]
- Roles:角色。
下面是一个Playbook的简单实例:
[root@ansible-node1 ~]# vim a.yaml
---
- hosts: web
remote_user: root
tasks:
- name: create user
user:
name: zhangsan
password: "{{ 'aptech' | password_hash('sha512') }}"
state: present
tags:
- ccc
...
(1)执行playbook,进行语法检查
[root@ansible-node1 ~]# ansible-playbook --syntax-check a.yaml
playbook: a.yaml
(2)预测试
[root@ansible-node1 ~]# ansible-playbook -C a.yaml
PLAY [web] *************************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.10.102]
TASK [create user] *****************************************************************
changed: [192.168.10.102]
PLAY RECAP *************************************************************************
192.168.10.102 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
(3)列出主机
[root@ansible-node1 ~]# ansible-playbook --list-hosts a.yaml
playbook: a.yaml
play #1 (web): web TAGS: []
pattern: [u'web']
hosts (1):
192.168.10.102
(4)列出任务
[root@ansible-node1 ~]# ansible-playbook --list-tasks a.yaml
playbook: a.yaml
play #1 (web): web TAGS: []
tasks:
create user TAGS: [ccc]
(5)列出标签
[root@ansible-node1 ~]# ansible-playbook --list-tags a.yaml
playbook: a.yaml
play #1 (web): web TAGS: []
TASK TAGS: [ccc]
(6)执行任务
[root@ansible-node1 ~]# ansible-playbook a.yaml
PLAY [web] *************************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.10.102]
TASK [create user] *****************************************************************
changed: [192.168.10.102]
PLAY RECAP *************************************************************************
192.168.10.102 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
1.Hosts 和Users 介绍
Playbook 的设计目的是为了让某个或某些主机以某个用户身份去执行完成相应的任务。其中用于指定要执行指定任务的主机用 hosts 定义,可以是一个也可以是由冒号分隔的多个主机组;用于指定被管理主机上执行任务的用户用 remote user 来定义,如下面示例中所示。
- hosts: web
remote_user: zhangsan
remote user 也可定义指定用户通过 sudo 的方法在被管理主机上运行指令,甚至可以在使用sudo 时用 sudo user 指定 sudo 切换的用户。
[root@ansible-node1 ~]# vim b.yaml
---
- hosts: web
remote_user: zhangsan
tasks:
- name: test connection
ping:
...
[root@ansible-node1 ~]# ansible-playbook -C b.yaml
PLAY [web] *************************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.10.102]
TASK [create user] *****************************************************************
changed: [192.168.10.102]
PLAY RECAP *************************************************************************
192.168.10.102 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@ansible-node1 ~]# ssh-copy-id zhangsan@192.168.10.102
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
zhangsan@192.168.10.102's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'zhangsan@192.168.10.102'"
and check to make sure that only the key(s) you wanted were added.
[root@ansible-node1 ~]# ansible-playbook b.yaml
PLAY [web] *************************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.10.102]
TASK [test connection] *************************************************************
ok: [192.168.10.102]
PLAY RECAP *************************************************************************
192.168.10.102 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2.任务列表和 action 介绍
"Play"的主体是任务列表(Tasks list)。任务列表中的任务按照次序逐个在 hosts 中指定的所有主机上执行,在顺序执行这些任务时,如果发生错误会将所有已执行任务回滚。因此,需要在更正Playbook 中的错误后重新执行这些任务。
Task 的任务是按照指定的参数去执行模块。每个 task 使用 name 输出 Playbook 的运行结果,一般输出内容为描述该任务执行的步骤。如果没有提供将输出 action 的运行结果。
定义 task 的格式可以用"action:module options"或"module:options"都可,其中后者可以实现向后兼容。如果 action 的内容过多,可在行首使用空白字符进行换行。
[root@ansible-node1 ~]# vim a.yaml
---
- hosts: web
remote_user: root
tasks:
- name: create user
user:
name: zhangsan
password: "{{ 'aptech' | password_hash('sha512') }}"
state: present
tags:
- ccc
- hosts: db
remote_user: root
tasks:
- name: copy file to web
copy: src=/etc/passwd dest=/opt
tags:
- ddd
...
[root@ansible-node1 ~]# ansible-playbook -C a.yaml
PLAY [web] *************************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.10.102]
TASK [create user] *****************************************************************
changed: [192.168.10.102]
PLAY [db] **************************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.10.103]
TASK [copy file to web] ************************************************************
changed: [192.168.10.103]
PLAY RECAP *************************************************************************
192.168.10.102 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.10.103 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@ansible-node1 ~]# ansible-playbook a.yaml
PLAY [web] *************************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.10.102]
TASK [create user] *****************************************************************
changed: [192.168.10.102]
PLAY [db] **************************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.10.103]
TASK [copy file to web] ************************************************************
changed: [192.168.10.103]
PLAY RECAP *************************************************************************
192.168.10.102 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.10.103 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
如果多次去执行修改的 Playbook 时,涉及到一些没有变化的代码,可以使用 tages 让用户选择跳过没有变化代码,只运行 Playbook中发生变化的部分代码。可以在Playbook中为某个或某些任务定义"标签",在执行此Playbook 时通过ansible-playbook 命令的--tags 选项能实现仅运行指定的 tasks 而非所有的 tasks。
3.Handlers 介绍
Handlers 用于当关注的资源发生变化时所采取的操作。在 notify 中列出的操作便称为 handler,也就是 notify 中需要调用 handler 中定义的操作。 而 notify 这个动作用于在每个"play"的最后被触发,仅在所有的变化发生完成后一次性地执行指定操作。
示例:当拷贝模板文件为/etc/foo.conf 文件时,重新启动 memcached 和 apache 服务,如下所示。
简单示例如下所示。
(1)安装apache
[root@ansible-node1 ~]# mkdir conf
[root@ansible-node1 ~]# yum -y install httpd
[root@ansible-node1 ~]# cp /etc/httpd/conf/httpd.conf conf
[root@ansible-node1 ~]# vim conf/httpd.conf
Listen 8080//修改端口号
[root@ansible-node1 ~]# vim a.yaml
- hosts: web
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install configuration file or httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: start httpd service
service: enabled=true name=httpd state=started
[root@ansible-node1 ~]# ansible-playbook a.yaml
PLAY [web] *************************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.10.102]
TASK [install httpd package] *******************************************************
changed: [192.168.10.102]
TASK [install configuration file or httpd] *****************************************
changed: [192.168.10.102]
TASK [start httpd service] *********************************************************
changed: [192.168.10.102]
PLAY RECAP *************************************************************************
192.168.10.102 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
(2)登录被管理主机 ansible-node2 进行查看执行结果。
[root@ansible-node2 ~]# rpm -qa httpd
httpd-2.4.6-99.el7.centos.1.x86_64
[root@ansible-node2 ~]# grep "Listen" /etc/httpd/conf/httpd.conf | grep -v "#"
Listen 8080
[root@ansible-node2 ~]# systemctl status httpd
(3)设置handlers
如果配置文件有改动,如:Apache 端口号改变,则需要定义 notify 和 handlers,关执行操作。
[root@ansible-node1 ~]# vim conf/httpd.conf
Listen 808
[root@ansible-node1 ~]# vim b.yaml
---
- hosts: web
remote_user: root
tasks:
- name: change port
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
handlers:
- name: restart httpd
service: name=httpd state=restarted
...
[root@ansible-node1 ~]# ansible-playbook b.yaml
PLAY [web] *************************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.10.102]
TASK [change port] *****************************************************************
ok: [192.168.10.102]
PLAY RECAP *************************************************************************
192.168.10.102 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
注意:
node2 上要关闭 selinux,否则,同步配置会出错,
(4)登录被管理主机 ansible-node2 进行查看。
[root@ansible-node2 ~]# netstat -anpt | grep httpd
4.Templates 介绍
Jinia 是基于 Pvthon 的模板引擎。Template 类似 Jinia 的另一个重要组件,可以看作是一个编译过的模板文件。用来产生目标文本,传递 Python 的变量给模板去替换模板中的标记。
(1)创建模板文件
[root@ansible-node1 ~]# mkdir templates
[root@ansible-node1 ~]# cp conf/httpd.conf templates/httpd.conf.j2
[root@ansible-node1 ~]# vim templates/httpd.conf.j2
Listen {{ http_port }}
ServerName {{ ansible_fqdn }}
(2)为远程主机添加变量
[root@ansible-node1 ~]# vim /etc/ansible/hosts
[web]
192.168.10.102 http_port=8888
[db]
192.168.10.103
(3)编写playbook文件
[root@ansible-node1 ~]# vim apache.yaml
- hosts: web
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd
yum: name={{ package }} state=latest
- name: install configuration file for httpd
template: src=/root/templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: start httpd service
service: enabled=true name={{ service }} state=started
handlers:
- name: restart httpd
service: name={{ service }} state=restarted
[root@ansible-node1 ~]# ansible-playbook apache.yaml
PLAY [web] *************************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.10.102]
TASK [install httpd] ***************************************************************
ok: [192.168.10.102]
TASK [install configuration file for httpd] ****************************************
changed: [192.168.10.102]
TASK [start httpd service] *********************************************************
changed: [192.168.10.102]
RUNNING HANDLER [restart httpd] ****************************************************
changed: [192.168.10.102]
PLAY RECAP *************************************************************************
192.168.10.102 : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
(4)登录被管理主机 ansible-node2,执行查看命令
[root@ansible-node2 ~]# grep -i listen /etc/httpd/conf/httpd.conf | grep -v "#"
Listen 8888
[root@ansible-node2 ~]# grep -i servername /etc/httpd/conf/httpd.conf | grep -v "#"
ServerName ansible-node2
三、Roles 介绍
1.什么是 Roles
Ansible 为了层次化、结构化地组织 Playbook,使用了角色(roles),可以根据层次结构自动装载变量文件、tasks 以及 handlers 等。只需要在 Playbook 中使用 include 指令便可使用 roles。简单来讲, roles 就是分别将变量、文件、任务、模块及处理器设置于单独的目录中,便捷地使用它们。
2.案例--利用 Roles 部署 mariadb
(1)被管理主机配置 yum 源
(2)配置数据库角色
[root@ansible-node1 ~]# cd /etc/ansible/
[root@ansible-node1 ansible]# ls
ansible.cfg hosts roles
[root@ansible-node1 ansible]# cd roles/
[root@ansible-node1 roles]# ls
[root@ansible-node1 roles]# mkdir mariadb
[root@ansible-node1 roles]# ls
mariadb
[root@ansible-node1 roles]# cd mariadb/
[root@ansible-node1 mariadb]# mkdir files
[root@ansible-node1 mariadb]# mkdir tasks
[root@ansible-node1 mariadb]# mkdir handlers
(3)编写主文件
[root@ansible-node1 tasks]# vim main.yaml
---
- name: install mariadb
yum: name=mariadb-server state=present
- name:install MySQL-python
yum: name=MySQL-python state=present
- name: bak config file
shell: "[ -e /etc/my.cnf ] && mv /etc/my.cnf /etc/my.cnf.bak"
- name: copy new config file
copy: src=my.cnf dest=/etc/my.cnf
- name: restart mariadb
shell: systemctl restart mariadb
- name: init mysql
shell: mysql -u root -e "create database testdb;grant all on testdb.* to test@'%' identified by 'pwd123';flush privileges;"
notify:
- restart mariadb
...
(4)编写触发器文件
[root@ansible-node1 mariadb]# cd handlers/
[root@ansible-node1 handlers]# vim main.yaml
---
- name: restart mariadb
service: name=mariadb state=restarted
...
(5)编写角色文件
[root@nodel tasks]# cd /etc/ansible/roles/mariadb/files
[root@node1 files]# ls
my.cnf ##将编辑好的 my.cnf 文件拷贝在此处
[root@ansible-node1 ansible]# vim mariadb.yaml
---
- hosts: db
remote_user: root
roles:
- mariadb
...
(6)测试角色文件
[root@ansible-node1 ansible]# ansible-playbook --syntax-check mariadb.yaml
playbook: mariadb.yaml
(7)执行yml文件
[root@ansible-node1 ansible]# ansible-playbook mariadb.yaml
PLAY [db] **************************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.10.103]
TASK [install mariadb] *************************************************************
changed: [192.168.10.103]
TASK [mariadb : install MySQL-python] **********************************************
changed: [192.168.10.103]
TASK [mariadb : bak config file] ***************************************************
changed: [192.168.10.103]
TASK [mariadb : copy new config file] **********************************************
changed: [192.168.10.103]
TASK [restart mariadb] *************************************************************
changed: [192.168.10.103]
TASK [mariadb : init mysql] ********************************************************
changed: [192.168.10.103]
RUNNING HANDLER [restart mariadb] **************************************************
changed: [192.168.10.103]
PLAY RECAP *************************************************************************
192.168.10.103 : ok=8 changed=7 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
(8)检查远程服务器上数据库
查看数据库信息,看看有没有创建制定的数据库
四、利用 Ansible 管理数据库
1.用 ansible 查看数据库
[root@ansible-node1 ansible]# ansible db -m shell -a 'mysql -u root -e "show databases;"'
192.168.10.103 | CHANGED | rc=0 >>
Database
information_schema
mysql
performance_schema
test
testdb
2.创建账户并授权
[root@ansible-node1 ansible]# ansible db -m yum -a "name=MySQL-python state=present"
192.168.10.103 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"msg": "",
"rc": 0,
"results": [
"MySQL-python-1.2.5-1.el7.x86_64 providing MySQL-python is already installed"
]
}
[root@ansible-node1 ansible]# ansible db -m mysql_user -a "name==zhangsan password=pwd123 host=192.168.10.% priv=*.*:ALL"
[WARNING]: Module did not set no_log for update_password
192.168.10.103 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"msg": "User added",
"user": "=zhangsan"
}
[root@ansible-node1 ansible]# ansible db -m mysql_user -a "name=lisi password=pwd123 priv=*.*:ALL"
[WARNING]: Module did not set no_log for update_password
192.168.10.103 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"msg": "User added",
"user": "lisi"
}
注意:
张三能够远程登录,但李四不能
要想使用 mysql user 模块,需要在客户端安装MySQL-python,安装时注意大小写
3.为老用户授权(语法和创建用户并授权的语法是相同的)
[root@ansible-node1 ansible]# ansible db -m mysql_user -a "name=root password=pwd123 host=192.168.10.% priv=*.*:ALL"
[WARNING]: Module did not set no_log for update_password
192.168.10.103 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"msg": "User added",
"user": "root"
}