## playbook

### 1、playbook概述

Ansible Playbooks 提供了一个可重复、可重用、简单的配置管理和多机部署系统，非常适合部署复杂的应用程序。如果您需要多次使用 Ansible 执行任务，请编写剧本并将其置于源代码控制之下。然后您可以使用 playbook 推送新配置或确认远程系统的配置。

### 2、Ansible playbook.与AD-Hoc的关系

1) playbook是AD-Hoc的一种编排方式。

2) playbook可以持久运行（重复），而Ad-Hoc只能临时运行。

3) playbook适合复杂的任务，而Ad-Hoc适合做快速简单的任务。

4) playbook能控制任务执行的先后顺序。

### 3、Ansible Playbook书写格式

playbook是由yaml语法书写，结构清晰，可读性强，所以心须掌握yml基础语法

| 语法   | 描述                                                         |
| ------ | ------------------------------------------------------------ |
| 缩进   | YAML使用固定的缩进风格表示层级结构，每个缩进由两个空格组成，不能使用tab |
| 冒号   | 以冒号结尾的除外，其他所有冒号后面所有必须有空格             |
| 短横线 | 表示列表项，使用一个短横杠加一个空格。多个项使用同样的缩进级别作为同一列表。 |



### 1. 安装Apache

```shell
[root@ansible1 opt]# mkdir /opt/playbook   # 建议playbook都放在一个目录里面，工程化
[root@ansible1 opt]# cd /opt/playbook/
[root@ansible1 playbook]# cat /opt/playbook/first.yml   # 严格要求格式，缩进(两个空格)
---
- hosts: all
  tasks:
    - name: install http
      yum: 
        name: httpd
        state: present
    - name: start server
      systemd: 
        name: httpd
        state: started
[root@ansible1 playbook]# ansible-playbook --syntax-check first.yml   # 语法检测

playbook: first.yml

# 可以使用网站检测工具检查语法是否错误
# https://www.bejson.com/validators/yaml_editor/
```

```shell
playbook执行语法：
ansible-playbook  -i 主机清单  playbook文件  -C 测试
[root@ansible1 playbook]# ansible-playbook -C /opt/playbook/first.yml   # 模拟执行
```

```shell
[root@ansible1 playbook]# ansible-playbook /opt/playbook/first.yml   # 正式执行
# 验证，浏览器输入远程主机的ip，成功如下图
```

![](https://note-1308251438.cos.ap-guangzhou.myqcloud.com/typora/202206071037631.png)

### 2. 不同web页面

#### **修改不同机子的html页面**

```shell
请补充操作
        
# 语法检测        
[root@ansible1 playbook]# ansible-playbook --syntax-check first.yml 

playbook: first.yml

# 开始执行
[root@ansible1 playbook]# ansible-playbook /opt/playbook/first.yml
```

![](https://note-1308251438.cos.ap-guangzhou.myqcloud.com/typora/202206071037442.png)

### 3.paly多语法示例

```shell
请补充操作
```

### 4. 编写一个ansible搭建lamp和nfs

#### 3.1 lamp

```shell
请补充操作
需要使用notify和handlers
```

```php
[root@ansible1 playbook]# cat index.php
<?php
phpinfo();
?>
    
# 浏览器打开输入ip/index.php，如下图
```

![](https://note-1308251438.cos.ap-guangzhou.myqcloud.com/typora/202206071644881.png)

#### 3.2 nfs

```shell
# 流程
# 1.安装
# 2.配置
#    组  nfsg
#    用户  nfs
#    共享文件夹 
# 3.启动

# web1组的机子做挂载源，挂去web2组的机子

请补充操作



[root@ansible1 playbook]# ansible-playbook --syntax-check /opt/playbook/nfs.yml   # 语法检测

playbook: /opt/playbook/nfs.yml

[root@ansible1 playbook]# ansible-playbook -C /opt/playbook/nfs.yml   # 模拟执行
[root@ansible1 playbook]# ansible-playbook /opt/playbook/nfs.yml   # 正式执行
```

```shell
# 验证
[root@ansible3 ~]# df -h
文件系统                     容量  已用  可用 已用% 挂载点
/dev/sda3                     17G  2.3G   15G   14% /
devtmpfs                     903M     0  903M    0% /dev
tmpfs                        912M     0  912M    0% /dev/shm
tmpfs                        912M  8.7M  903M    1% /run
tmpfs                        912M     0  912M    0% /sys/fs/cgroup
/dev/sr0                     4.3G  4.3G     0  100% /mnt
/dev/sda1                   1014M  135M  880M   14% /boot
tmpfs                        183M     0  183M    0% /run/user/0
192.168.188.31:/opt/nfstest   17G  2.3G   15G   14% /opt
```

#### 3.3 一键部署discuz论坛

```shell
请补充操作
```

作业：请用playbook编写lnmp和lnmT，nginx需要yum与编译安装  mysql需要yum与二进制安装



### 变量

[官方文档变量](https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html)



#### 1.变量概述

变量提供了便捷的方式来管理ansible项目中的动态值 

在ansible中，定义变量分为如下三种方式：

1.通过**命令行**进行变量定义

2.在**playbook文件**中进行定义变量

3.通过主机清单在主机组或单个主机中设置变量



 如果定义的变量出现重复，且造成冲突，优先级如下：

命令行定义的变量 >> playbook文件定义的变量 >> 主机清单定义的变量

#### 2.变量定义

##### 1.playbook的开头hosts下面通过vars进行定义

```shell
# 安装两个软件包使用变量方式
请补充操作过程与验证 

```

##### 2.playbook中使用vars_files指定文件作为变量文件

**<font color='red'>这种方法的好处就是其他的playbook也可以调</font>**

```shell
#一定要是yml结尾的
请补充操作过程与验证 
```

##### 3.在主机清单中定义变量

**主机变量优先级高于主机组变量(但是容易将环境弄的特别乱)**

```shell
请补充操作过程与验证 

#local3只能是web2群组的变量，其它群组不能使用



#playbook调用变量需要主机清单定义，否则报错

     				#路径调用变量的示例
          
      
```

##### 4.host_vars和group_vars

**更好的方式是在ansible的项目目录中创建额外的两个变量目录，分别是host_vars和group_vars(一定名字是这两个不能改)**

**4.1、group_vars**

```shell
[root@ansible1 playbook]# grep -Ev "#|^$"  /etc/ansible/hosts
[web1]
web01 ansible_ssh_host=192.168.188.31
[web2]
web02 ansible_ssh_host=192.168.188.32
[server:children]
web1
web2
[root@ansible1 playbook]# mkdir /opt/playbook/host_vars
[root@ansible1 playbook]# mkdir /opt/playbook/group_vars

# group_vars目录下必须存放和主机清单文件中定义的组名一致，如下
[root@ansible1 playbook]# cat /opt/playbook/group_vars/server # 指定组来执行，在group_vars目录里创建对应的组名一致的文件，再编写内容，如果不符合，则报错
web_package: httpd
ftp_package: vsftpd
[root@ansible1 playbook]# cat /opt/playbook/p4.yml 
---
- hosts: server
  tasks:
    - name: Installed Packages
      yum: 
        name: 
          - "{{ web_package }}"
          - "{{ ftp_package }}"
        state: present 
[root@ansible1 playbook]# ansible-playbook --syntax-check /opt/playbook/p4.yml 

playbook: /opt/playbook/p4.yml
[root@ansible1 playbook]# ansible-playbook /opt/playbook/p4.yml


# 注意：系统提供了特殊的组，all，也就说在group_vars目录下创建一个all文件，定义变量对所有的主机都生效
```

4.2、**host_vars**

```shell
[root@ansible1 playbook]# grep -Ev "#|^$"  /etc/ansible/hosts
[web1]
web01 ansible_ssh_host=192.168.188.31
[web2]
web02 ansible_ssh_host=192.168.188.32
[server:children]
web1
web2
[root@ansible1 playbook]# cat /opt/playbook/host_vars/web01   # 指定机子别名来执行，在host_vars写对应的机名再写内容
web_package: zlib-static
ftp_package: zmap
[root@ansible1 playbook]# cat /opt/playbook/p5.yml 
---
- hosts: all
  tasks:
    - name: Installed Packages
      yum: 
        name: 
          - "{{ web_package }}"
          - "{{ ftp_package }}"
        state: present
[root@ansible1 playbook]# ansible-playbook --syntax-check /opt/playbook/p5.yml 

playbook: /opt/playbook/p5.yml
[root@ansible1 playbook]# ansible-playbook /opt/playbook/p5.yml
```

```shell
[root@ansible1 playbook]# grep -Ev "#|^$" /etc/ansible/hosts
[webservers]
web01 ansible_ssh_host=192.168.188.31 ansible_ssh_port=22
web02 ansible_ssh_host=192.168.188.32
[root@ansible1 playbook]# cat /opt/playbook/p6.yml   # 主机清单里面的也是变量
---
- hosts: all
  tasks:
    - name: touch file
      file: 
        path: /tmp/{{ ansible_ssh_port }}.txt
        state: touch
```

```shell
# 将原有Playbook中的变量覆盖掉，使其自行使用新的变量
[root@ansible1 playbook]# cat /opt/playbook/p2.yml 
---
- hosts: web2
  vars:
    - web_package: httpd
    - ftp_package: vsftpd
  tasks:
    - name:
      yum:
        name:
          - "{{ web_package }}"
          - "{{ ftp_package }}"
        state: present
[root@ansible1 playbook]# ansible-playbook /opt/playbook/p2.yml -e 'web_package=nginx'
```

```shell
# 变量优先级测试
#命令行变量--->play中的vars_files--->play中的vars变量-->host_vars中定义的变量--->group_vars/组--->group_vars/all
[root@m01 project1]# cat p5.yml 
---
- hosts: webservers
#  vars:
#    filename: play_vars
#  vars_files:
#    - ./vars.yml
  tasks:

    - name: Create 
      shell: mkdir -pv /tmp/{{ filename }}
      register: mk_test

    - name: debug
      debug: msg={{ mk_test }}
```

##### 5.**变量注册register**

```
register关键字可以将某个task任务结果存储至变量中，最后使用debug输出变量内容，可以用于后续排障

类似于命令行的$? 
```

**当我们需要判断对执行了某个操作或者某个命令后，如何做相应的响应处理，也就是说在ansible的playbook中task之间的相互传递变量**

```shell
[root@ansible1 playbook]# grep -Ev "#|^$"  /etc/ansible/hosts
[web1]
web01 ansible_ssh_host=192.168.188.31
[web2]
web02 ansible_ssh_host=192.168.188.32
[server:children]
web1
web2
[root@ansible1 playbook]# grep -Ev "#|^$" /opt/playbook/p7.yml 
---
- hosts: web1
  tasks:
    - name: Get Network Port Status
      shell: netstat -lntp
      register: net_port
    - name: OutPut Network Port Status
      debug:
        msg: "{{ net_port.stdout_lines }}"
        
# 第一个任务就是用shell模块，执行netstat
# 通过shell模块执行netstat，把这个执行结果传递给register
# 第三个任务，将第二个任务捕获到的结果，赋值给变量通过变量net_port调用register结果中stdout_lines

register应用场景小结
	用于调试配合bebug模块msg输出
	用于与when一起使用实现判断功能
```

```shell
# 变量也支持层级定义，使用"."可能会有问题，建议使用"[]"代替。
[root@m01 project1]# cat vars1.yml 
rainbow:
  web:
    web_package: httpd
    db_package: mariadb
    

code:
  web:
    filename: code_web_filename

	
[root@m01 project1]# cat p8.yml 
---
- hosts: webservers
  vars_files: ./vars1.yml
  tasks:
    - name: Install Package
      yum: name= "{{ rainbow['web']['web_package'] }}"

    - name: create filename
      file: 
        path: /tmp/{{ code.web.filename }}
        state: touch
```

##### 6. Facts 变量

`Ansible facts` 用来自动采集，”被控端主机“ 自身的状态信息。

比如: 主机名、IP地址、系统版本、CPU数量、内存状态、磁盘状态等等。

facts使用场景

1.通过facts检查cpu，来生成对应的nginx配置文件

2.通过facts检杳内存的情况，来设置tomcat的配置文件

3.通过facts检杳内存的情况来自定义mysql的配置文件





###### 1.1 facts的获取方法

被控节点的`facts`信息需要使用`ansible`的`setup`模块进行获取，使用`filter`参数可以过滤特定的`Facts`变量：

`facts`中的变量可以直接引用，无需获取。

通过系统采集获取变量。facts (setup模块)

```shell
# 获取被控主机的信息
请补充操作过程与验证 

# 模糊匹配，获取主机名
请补充操作过程与验证 

# 查看系统版本信息
请补充操作过程与验证 
```

```shell
# 通过fact变量获取主机地址
请补充两种写法


```

几个常用的facts

```
ansible_default_ipv4.adress		#默认的网卡IP
ansible_distribution			#系统发行版本名字	
ansible_memtotal_mb				#内存大小
ansible_processor_vcpus			#cpu个数
ansible_processor_cores			#cpu核心数
ansilbe_date_time.date			#时间
```

facts开启后会影响ansible主机的性能，如果没有采集被控端主机需求可选择关闭

```
#关闭信息采集,但模块不能使用facts采集的变量
请补充操作过程与验证 
        
```



**playbook安装一个memcached**

```shell
# template:模块可以将带有参数的配置文件传递到目标地址
请补充操作过程与验证 
```

​     

