作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
- 一.主机清单管理
- 1.安装ansible
- 2.直接指定主机
- 3.基于别名管理
- 3.基于多个分组
- 4.通过域名解析
- 5.序列定义方式
- 6.支持子组
- 7.为组设置变量
- 8.通过免密钥的方式配置Inventory
- 二.ansible的模块
- 三.Playbook实战之vars变量管理
- 1.playbook概述
- 1.1 Playbook的核心元素
- 1.2 ansible运行结果颜色说明
- 2.定义变量
- 2.1 直接在play定义变量
- 2.2 在文件中定义变量
- 2.3 在主机清单中定义变量
- 2.4 官方推荐的定义变量方式
- 3.变量注册
- 4.层级定义变量
- 4.1 使用点号'.'区分层级变量
- 4.2 使用方括号'[]'区分层级变量 (官方推荐写法)
- 4.3 语法风格对比
- 5.Facts缓存
- 5.1 facts概述
- 5.2 facts内置变量
- 5.2.1 系统发行版 & 内核架构
- 5.2.2 CPU 硬件信息
- 5.2.3 内存与 Swap
- 5.2.4 磁盘与挂载设备
- 5.2.5 网络相关(高频)
- 5.2.6 虚拟化 / 云主机标识
- 5.2.7 用户、环境、时间
- 5.2.8 Windows 系统专属 Facts
- 5.2.9 playbook 全局内置变量(非 setup 采集 facts,配套使用)
- 5.3 测试案例
- 6.template使用变量
- 四.Playbook实战之流程控制
- 1.playbook条件语句概述
- 2.when判断实战
- 2.1 when条件表达式
- 2.2 when案例
- 2.3 部署nginx服务案例
- 3.Handlers实战
- 4.循环语句
- 5.任务标签
- 6.文件复用-task拆解
- 7.抑制changed
- 五.jinja2模板及Role角色
- 1.jinja2模板
- 1.1 什么是jinja2模板
- 1.2 实战案例-for循环和if语句
- 2.Roles角色
- 2.1 什么是Roles
- 2.2 实战案例-部署rsync服务
- 2.3 实战案例-部署nfs服务
一.主机清单管理
1.安装ansible
1.安装ansible
[root@ansible99 ~]# apt -y install ansible sshpass2.关闭主机密钥检查
[root@ansible99 ~]# cat > /etc/ansible/ansible.cfg <<EOF
[defaults]
host_key_checking = False
deprecation_warnings=False
inventory = /etc/ansible/hosts
EOF
2.直接指定主机
1.定义主机列表
[root@ansible99 ~]# mkdir etcansible
[root@ansible99 ~]#
[root@ansible99 ~]# vim /etc/ansible/hosts
[root@ansible99 ~]#
[root@ansible99 ~]# cat /etc/ansible/hosts
10.0.0.231 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
10.0.0.232 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
10.0.0.233 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
[root@ansible99 ~]# 2.链接指定的主机进行检测
[root@ansible99 ~]# ansible 10.0.0.231 -m ping
10.0.0.231 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
[root@ansible99 ~]# ansible 10.0.0.232 -m ping
10.0.0.232 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
[root@ansible99 ~]# ansible 10.0.0.66 -m ping # 如果没有定义主机,则无法使用
[WARNING]: Could not match supplied host pattern, ignoring: 10.0.0.66
[WARNING]: No hosts matched, nothing to do
[root@ansible99 ~]#
3.基于别名管理
1.定义主机列表
[root@ansible99 ~]# cat /etc/ansible/hosts
10.0.0.231 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
master232 ansible_ssh_host=10.0.0.232 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
master233 ansible_ssh_host=10.0.0.233 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
[root@ansible99 ~]#
[root@ansible99 ~]# 2.基于别名管理
[root@ansible99 ~]# ansible 10.0.0.231 -m ping
10.0.0.231 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
[root@ansible99 ~]# ansible master232 -m ping
master232 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
[root@ansible99 ~]# ansible master233 -m ping
master233 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
[root@ansible99 ~]# ansible 10.0.0.233 -m ping # 基于别名就不能直接写主机IP了,如果非要用,也可以
[WARNING]: Could not match supplied host pattern, ignoring: 10.0.0.233
[WARNING]: No hosts matched, nothing to do
[root@ansible99 ~]#
3.基于多个分组
1.修改主机清单
[root@ansible99 ~]# cat /etc/ansible/hosts
[k8s_master]
master231 ansible_ssh_host=10.0.0.231 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
master232 ansible_ssh_host=10.0.0.232 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
master233 ansible_ssh_host=10.0.0.233 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'[k8s_worker]
worker66 ansible_ssh_host=10.0.0.66 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
worker77 ansible_ssh_host=10.0.0.77 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
[root@ansible99 ~]#
[root@ansible99 ~]# 2.测试验证
[root@ansible99 ~]# ansible k8s_master -m ping
master231 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
master233 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
master232 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
[root@ansible99 ~]#
[root@ansible99 ~]# ansible k8s_worker -m ping
worker77 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
worker66 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
[root@ansible99 ~]# ansible all -m ping # all代表所有的分组。
worker77 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
master233 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
worker66 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
master232 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
master231 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
4.通过域名解析
1.添加域名配置
[root@ansible99 ~]# cat /etc/ansible/hosts
www.yinzhengjie.com ansible_ssh_host=10.0.0.231 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'[k8s_master]
master231 ansible_ssh_host=10.0.0.231 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
master232 ansible_ssh_host=10.0.0.232 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
master233 ansible_ssh_host=10.0.0.233 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'[k8s_worker]
worker66 ansible_ssh_host=10.0.0.66 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
worker77 ansible_ssh_host=10.0.0.77 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
[root@ansible99 ~]# 2.由于我没有域名指向的服务器,因此在本地host做域名劫持
[root@ansible99 ~]# echo 10.0.0.231 www.yinzhengjie.com >> /etc/hosts
[root@ansible99 ~]#
[root@ansible99 ~]# tail -1 /etc/hosts
10.0.0.231 www.yinzhengjie.com
[root@ansible99 ~]#
[root@ansible99 ~]# ansible www.yinzhengjie.com -m ping
www.yinzhengjie.com | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
5.序列定义方式
1.添加主机解析
[root@ansible99 ~]# cat >> /etc/hosts <<EOF
10.0.0.231 master231
10.0.0.232 master232
10.0.0.233 master233
EOF2.定义主机列表
[root@ansible99 ~]# cat /etc/ansible/hosts
[k8s_master]
master23[1:3] ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'[k8s_worker]
worker66 ansible_ssh_host=10.0.0.66 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
worker77 ansible_ssh_host=10.0.0.77 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'[root@ansible99 ~]# 2.测试验证
[root@ansible99 ~]# ansible k8s_master -m ping
master231 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
master233 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
master232 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
6.支持子组
1.定义主机
[root@ansible99 ~]# cat /etc/ansible/hosts
[k8s01]
master231 ansible_ssh_host=10.0.0.231 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'[k8s02]
master232 ansible_ssh_host=10.0.0.232 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'[k8s03]
master233 ansible_ssh_host=10.0.0.233 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'[master:children]
k8s01
k8s03
[root@ansible99 ~]# 2.调用子组master
[root@ansible99 ~]# ansible master -m ping
master231 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
master233 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
7.为组设置变量
1.定义主机清单
[root@ansible99 ~]# cat /etc/ansible/hosts
[k8s01]
master231 ansible_ssh_host=10.0.0.231[k8s02]
master232 ansible_ssh_host=10.0.0.232[k8s03]
master233 ansible_ssh_host=10.0.0.233 [master:children]
k8s01
k8s03[all:vars] # 此处的all表示所有主机,这里的vars表示设置变量。
ansible_ssh_user=root
ansible_ssh_port=22
ansible_ssh_pass='1'
[root@ansible99 ~]# 2.测试验证
[root@ansible99 ~]# ansible master -m ping
master231 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
master233 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
[root@ansible99 ~]#
[root@ansible99 ~]# ansible k8s02 -m ping
master232 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
8.通过免密钥的方式配置Inventory
1.生成密钥
[root@ansible99 ~]# ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' -q2.配置免密链接
[root@ansible99 ~]# ssh-copy-id 10.0.0.231
[root@ansible99 ~]# ssh-copy-id 10.0.0.232
[root@ansible99 ~]# ssh-copy-id 10.0.0.233
[root@ansible99 ~]# ssh-copy-id 10.0.0.66
[root@ansible99 ~]# ssh-copy-id 10.0.0.773.修改主机清单
[root@ansible99 ~]# cat /etc/ansible/hosts
[master]
10.0.0.231
10.0.0.232
10.0.0.233[worker]
10.0.0.66
10.0.0.77
[root@ansible99 ~]# 4.测试验证
[root@ansible99 ~]# ansible master -m ping
10.0.0.233 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
10.0.0.232 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
10.0.0.231 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
[root@ansible99 ~]#
[root@ansible99 ~]# ansible worker -m ping
10.0.0.66 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
10.0.0.77 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
[root@ansible99 ~]# ansible all -m ping
10.0.0.77 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
10.0.0.66 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
10.0.0.233 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
10.0.0.232 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
10.0.0.231 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"
}
[root@ansible99 ~]#
二.ansible的模块
1.查看模块文档
[root@ansible99 ~]# ansible-doc ping
> ANSIBLE.BUILTIN.PING (/usr/lib/python3/dist-packages/ansible/modules/ping.py)A trivial test module, this module always returns `pong' on successful contact. Itdoes not make sense in playbooks, but it is useful from `/usr/bin/ansible' to verifythe ability to login and that a usable Python is configured. This is NOT ICMP ping,this is just a trivial test module that requires Python on the remote-node. ForWindows targets, use the [ansible.windows.win_ping] module instead. For Networktargets, use the [ansible.netcommon.net_ping] module instead.ADDED IN: historicalOPTIONS (= is mandatory):- dataData to return for the `ping' return value.If this parameter is set to `crash', the module will cause an exception.default: pongtype: strATTRIBUTES:check_mode:description: Can run in check_mode and return changed status prediction withoutmodifying targetsupport: fulldiff_mode:description: Will return details on what has changed (or possibly needs changingin check_mode), when in diff modesupport: noneplatform:
[root@ansible99 ~]#
2.参考资料
推荐阅读:https://www.cnblogs.com/yinzhengjie/p/10447587.html
三.Playbook实战之vars变量管理
1.playbook概述
1.1 Playbook的核心元素
Hosts:定义可以操作的主机,Tasks:定义我们需要执行的任务列表。Variable: 支持变量,流程控制语句,如循环语句等等。(YAML支持编程语言的基本语法,如条件表达式,循环语句,流程控制等等,这也是为什么ansible选择它的一个原因吧!)Templates:包含了模板语法的文本文件。Handlers:处理器是由特定条件触发的任务。Roles:定义角色,其实我们可以理解角色是将服务器主机进行分组,然后基于组的方式进行批量管理。这个角色和MySQL8.0之后版本的角色功能很相似!
1.2 ansible运行结果颜色说明
| 颜色 |
含义 |
描述 |
| 绿色 |
执行成功且未发生状态改变 |
任务成功完成,但目标系统没有发生变化(幂等性体现)。 |
| 黄色 |
成功执行且发生了状态改变 |
任务成功完成,并且目标系统的状态发生了改变(如文件创建,服务启动)。 |
| 红色 |
执行失败 |
执行过程中出现错误,需要排查原因。 |
| 紫色 |
告警信息 |
提示可能存在的问题或建议,但任务可能继续执行。 |
ansible输出的颜色,表示不同的涵义。
2.定义变量
2.1 直接在play定义变量
1.查看主机清单
[root@ansible99 playbook]# cat /etc/ansible/hosts
[master]
10.0.0.231
10.0.0.232
10.0.0.233[worker]
10.0.0.66
10.0.0.77
[root@ansible99 playbook]# 2.编写剧本
[root@ansible99 playbook]# cat 01-play.yaml
- hosts: mastervars:- file01: /tmp/xixi.txt- file02: haha.txttasks:- name: create {{ file01 }} filefile:path: "{{ file01 }}"owner: rootgroup: rootmode: 0644state: touch- name: create {{ file02 }} filefile:path: /tmp/{{ file02 }}state: touch
[root@ansible99 playbook]# 3.测试验证
[root@ansible99 playbook]# ansible-playbook 01-play.yaml PLAY [master] ********************************************************************************************************TASK [Gathering Facts] ***********************************************************************************************
ok: [10.0.0.231]
ok: [10.0.0.233]
ok: [10.0.0.232]TASK [create /tmp/xixi.txt file] *************************************************************************************
changed: [10.0.0.231]
changed: [10.0.0.233]
changed: [10.0.0.232]TASK [create haha.txt file] ******************************************************************************************
changed: [10.0.0.231]
changed: [10.0.0.233]
changed: [10.0.0.232]PLAY RECAP ***********************************************************************************************************
10.0.0.231 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.232 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.233 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@ansible99 playbook]#
2.2 在文件中定义变量
1.编写剧本
[root@ansible99 playbook]# cat pkg.yml
pkg01: wget
pkg02: tree
[root@ansible99 playbook]#
[root@ansible99 playbook]# cat 02-files.yaml
- hosts: mastervars_files:- pkg.ymltasks:- name: Install packageapt:name:- "{{ pkg01 }}"- "{{ pkg02 }}"state: present # 卸载的话可以改成absent
[root@ansible99 playbook]# 2.测试验证
[root@ansible99 playbook]# ansible-playbook 02-files.yaml PLAY [master] ********************************************************************************************************TASK [Gathering Facts] ***********************************************************************************************
ok: [10.0.0.231]
ok: [10.0.0.233]
ok: [10.0.0.232]TASK [Install package] ***********************************************************************************************
changed: [10.0.0.231]
changed: [10.0.0.232]
changed: [10.0.0.233]PLAY RECAP ***********************************************************************************************************
10.0.0.231 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.232 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.233 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@ansible99 playbook]#
2.3 在主机清单中定义变量
1.在主机清单中定义变量
[root@ansible99 playbook]# cat /etc/ansible/hosts
[master]
10.0.0.231
10.0.0.232
10.0.0.233[worker]
10.0.0.66
10.0.0.77[master:vars]
pkg01=wget
pkg02=tree
pkg03=lrzsz
[root@ansible99 playbook]# 2.编写playbook
[root@ansible99 playbook]# cat 03-hosts.yaml
- hosts: mastertasks:- name: Install packageapt:name:- "{{ pkg01 }}"- "{{ pkg02 }}"- "{{ pkg03 }}"state: present
[root@ansible99 playbook]# 3.测试验证
[root@ansible99 playbook]# ansible-playbook 03-hosts.yaml PLAY [master] **********************************************************************TASK [Gathering Facts] *************************************************************
ok: [10.0.0.233]
ok: [10.0.0.232]
ok: [10.0.0.231]TASK [Install package] *************************************************************
changed: [10.0.0.231]
changed: [10.0.0.233]
changed: [10.0.0.232]PLAY RECAP *************************************************************************
10.0.0.231 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.232 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.233 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@ansible99 playbook]#
2.4 官方推荐的定义变量方式
1.在运行playbook的目录下创建两个目录
[root@ansible99 playbook]# mkdir group_vars hosts_vars
[root@ansible99 playbook]# 目录作用说明:group_vars:在目录下面以"组名称"命名的文件,然后在文件中直接定义变量。hosts_vars:在目录下面以"主机"命名的文件,然后在文件中直接定义变量。2.编辑主机清单
[root@ansible99 playbook]# cat /etc/ansible/hosts
[master]
10.0.0.231
10.0.0.232
10.0.0.233[worker]
10.0.0.66
10.0.0.77
[root@ansible99 playbook]# 3.在group_vars或者hosts_vars目录下定义变量
[root@ansible99 playbook]# cat group_vars/all
pkg01: wget
pkg02: tree
pkg03: lrzsz[root@ansible99 playbook]#
[root@ansible99 playbook]# cat group_vars/master
pkg01: curl
pkg02: tree
[root@ansible99 playbook]#
[root@ansible99 playbook]# cat hosts_vars/10.0.0.66
pkg01: nginx
pkg02: curl
[root@ansible99 playbook]# 4.编写playbook
[root@ansible99 playbook]# cat 04-group-vars.yaml
- hosts: mastertasks:- name: Install packageapt:name:- "{{ pkg01 }}"- "{{ pkg02 }}"state: absent
[root@ansible99 playbook]# 5.测试验证
[root@ansible99 playbook]# ansible-playbook 04-group-vars.yaml PLAY [master] **********************************************************************TASK [Gathering Facts] *************************************************************
ok: [10.0.0.233]
ok: [10.0.0.232]
ok: [10.0.0.231]TASK [Install package] *************************************************************
changed: [10.0.0.231]
changed: [10.0.0.233]
changed: [10.0.0.232]PLAY RECAP *************************************************************************
10.0.0.231 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.232 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.233 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@ansible99 playbook]#
3.变量注册
3.1 什么是变量注册
当ansible的模块在运行之后,其实都会返回一些result结果,就像是执行脚本,我们有的时候需要脚本给我们一些return返回值,我们才知道,上一步是否只想成功。默认情况下,ansible的result并不会显示出来,所以,我们可以把这些返回值'存储'到变量中,这样我们就能通过'调用'对应的变量名,从而获取到这些result,这种将模块的返回值,写入变量中的方法我们称之为变量注册。
3.2 变量注册案例
1.编写剧本
[root@ansible99 playbook]# cat 05-register.yaml
- hosts: 10.0.0.232tasks:- name: Install nginxapt:name:- nginxstate: present- name: nginx check syntaxcommand: 'nginx -t'# 注册变量register: nginx_result- name: print nginx_result variablesdebug:# 一般我们不需要查看所有的输出,看指定字段的数据,可以使用"."来取数据即可。# msg: "{{ nginx_result }}"msg: "{{ nginx_result.stderr_lines }}"- name: list nginx conf dircommand: 'ls -lh /etc/nginx/'register: list_result- name: print list_result variablesdebug:msg: "{{ list_result.stdout_lines }}"[root@ansible99 playbook]# 2.测试验证
[root@ansible99 playbook]# ansible-playbook 05-register.yaml PLAY [10.0.0.232] ******************************************************************TASK [Gathering Facts] *************************************************************
ok: [10.0.0.232]TASK [Install nginx] ***************************************************************
ok: [10.0.0.232]TASK [nginx check syntax] **********************************************************
changed: [10.0.0.232]TASK [print nginx_result variables] ************************************************
ok: [10.0.0.232] => {"msg": ["nginx: the configuration file /etc/nginx/nginx.conf syntax is ok","nginx: configuration file /etc/nginx/nginx.conf test is successful"]
}TASK [list nginx conf dir] *********************************************************
changed: [10.0.0.232]TASK [print list_result variables] *************************************************
ok: [10.0.0.232] => {"msg": ["total 68K","drwxr-xr-x 2 root root 4.0K Jun 9 11:45 conf.d","-rw-r--r-- 1 root root 1.1K Nov 30 2023 fastcgi.conf","-rw-r--r-- 1 root root 1.1K Nov 30 2023 fastcgi_params","-rw-r--r-- 1 root root 2.8K Nov 30 2023 koi-utf","-rw-r--r-- 1 root root 2.2K Nov 30 2023 koi-win","-rw-r--r-- 1 root root 5.4K Nov 30 2023 mime.types","drwxr-xr-x 2 root root 4.0K Jun 9 11:45 modules-available","drwxr-xr-x 2 root root 4.0K Jun 9 11:45 modules-enabled","-rw-r--r-- 1 root root 1.5K Nov 30 2023 nginx.conf","-rw-r--r-- 1 root root 180 Nov 30 2023 proxy_params","-rw-r--r-- 1 root root 636 Nov 30 2023 scgi_params","drwxr-xr-x 2 root root 4.0K Jun 10 08:46 sites-available","drwxr-xr-x 2 root root 4.0K Jun 10 08:46 sites-enabled","drwxr-xr-x 2 root root 4.0K Jun 10 08:46 snippets","-rw-r--r-- 1 root root 664 Nov 30 2023 uwsgi_params","-rw-r--r-- 1 root root 3.0K Nov 30 2023 win-utf"]
}PLAY RECAP *************************************************************************
10.0.0.232 : ok=6 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@ansible99 playbook]#
4.层级定义变量
4.1 使用点号'.'区分层级变量
1.定义层级变量
[root@ansible99 playbook]# cat pkg2.yml
lnmp:tools:pkg: wget
[root@ansible99 playbook]# 2.编写playbook局部
[root@ansible99 playbook]# cat 06-layer-var.yaml
- hosts: mastervars_files:- pkg2.ymltasks:- name: remove "{{ lnmp.tools.pkg }}" packageapt:name:- "{{ lnmp.tools.pkg }}"state: absent
[root@ansible99 playbook]#3.测试验证
[root@ansible99 playbook]# ansible-playbook 06-layer-var.yaml PLAY [master] **********************************************************************TASK [Gathering Facts] *************************************************************
ok: [10.0.0.233]
ok: [10.0.0.231]
ok: [10.0.0.232]TASK [remove "wget" package] *******************************************************
changed: [10.0.0.231]
changed: [10.0.0.233]
changed: [10.0.0.232]PLAY RECAP *************************************************************************
10.0.0.231 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.232 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.233 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@ansible99 playbook]#
4.2 使用方括号'[]'区分层级变量 (官方推荐写法)
1.定义层级变量
[root@ansible99 playbook]# cat pkg2.yml
lnmp:tools:pkg: wget
[root@ansible99 playbook]# 2.编写playbook局部
[root@ansible99 playbook]# cat 07-layer2-var.yaml
- hosts: mastervars_files:- pkg2.ymltasks:- name: install "{{ lnmp['tools']['pkg'] }}" packageapt:name:- "{{ lnmp['tools']['pkg'] }}"state: present
[root@ansible99 playbook]# 3.测试验证
[root@ansible99 playbook]# ansible-playbook 07-layer2-var.yaml PLAY [master] **********************************************************************TASK [Gathering Facts] *************************************************************
ok: [10.0.0.233]
ok: [10.0.0.232]
ok: [10.0.0.231]TASK [install "wget" package] ******************************************************
ok: [10.0.0.233]
ok: [10.0.0.231]
ok: [10.0.0.232]PLAY RECAP *************************************************************************
10.0.0.231 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.232 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.233 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@ansible99 playbook]# 温馨提示:语法风格差异:
4.3 语法风格对比
| 类型 |
描述 |
风格 |
| 点号(".") |
键名必须是有效的标识符,不能包含特殊字符,空格,连字符等。 |
类似于python的对象属性访问。 |
| 方括号("[]") |
可以处理任何字符串键名 |
类似于python字典键值对访问。 |
如上所示,官方两种风格都支持,但对于特殊的键名称推荐使用方括号来引用。举个例子:包含特殊字符的键名:lnmp['web-server']['php-version']以数字开头的键名:lnmp['2nd-level']['key']包含空格的键名:lnmp['my key']['sub key']
5.Facts缓存
5.1 facts概述
ansible facts是被管理主机上通过ansible自动采集发现的变量,facts包含每台特定的主机信息。facts包含被控制端的主机名,IP地址,系统版本,CPU数量,内存状态,磁盘状态等等。
5.2 facts内置变量
5.2.1 系统发行版 & 内核架构
| 变量名 |
用途说明 |
| ansible_distribution |
系统发行版名称(CentOS/Ubuntu/Rocky/Windows) |
| ansible_distribution_version |
系统完整版本号 |
| ansible_distribution_major_version |
系统主版本号 |
| ansible_os_family |
系统家族(RedHat/Debian/Suse/Windows) |
| ansible_system |
内核标识(Linux/Windows/Darwin) |
| ansible_kernel |
内核版本号 |
| ansible_architecture |
CPU 架构(x86_64/aarch64/armv7l) |
| ansible_pkg_mgr |
系统包管理器(yum/dnf/apt/chocolatey) |
| ansible_timezone |
系统时区 |
| ansible_selinux |
SELinux 完整状态字典 |
| ansible_selinux_mode |
SELinux 运行模式 |
5.2.2 CPU 硬件信息
| 变量名 |
用途说明 |
| ansible_processor |
CPU 型号列表 |
| ansible_processor_count |
物理 CPU 颗数 |
| ansible_processor_cores |
单 CPU 物理核心数 |
| ansible_processor_vcpus |
逻辑 CPU 总数量(含超线程) |
| ansible_threads_per_core |
每核心线程数 |
| ansible_cpu_min_freq_hz |
CPU 最小运行频率 |
| ansible_cpu_max_freq_hz |
CPU 最大运行频率 |
5.2.3 内存与 Swap
| 变量名 |
用途说明 |
| ansible_memtotal_mb |
物理总内存 (MB) |
| ansible_memfree_mb |
空闲物理内存 (MB) |
| ansible_swaptotal_mb |
Swap 分区总大小 (MB) |
| ansible_swapfree_mb |
空闲 Swap 大小 (MB) |
| ansible_memory_mb |
内存复合字典(real/swap 分组存储 total/free/cached) |
5.2.4 磁盘与挂载设备
| 变量名 |
用途说明 |
| ansible_mounts |
所有挂载点数组,包含路径、设备、容量、文件系统 |
| ansible_devices |
磁盘设备字典(sda/vda 等),包含分区信息 |
5.2.5 网络相关(高频)
| 变量名 |
用途说明 |
| ansible_hostname |
主机短名 |
| ansible_fqdn |
完整主机域名 |
| ansible_nodename |
uname -n 获取的主机名 |
| ansible_default_ipv4 |
默认出口 IPv4 完整字典(地址 / 网关 / 网卡 / 掩码) |
| ansible_default_ipv6 |
默认出口 IPv6 完整字典 |
| ansible_interfaces |
全部网卡名称数组 |
| ansible_网卡名 (ansible_eth0/ens33) |
单网卡详情(IP、MAC、MTU) |
5.2.6 虚拟化 / 云主机标识
| 变量名 |
用途说明 |
| ansible_virtualization_type |
虚拟化类型(kvm/qemu/vmware/docker/physical) |
| ansible_virtualization_role |
guest 虚拟机 /host 宿主机 |
| ansible_container |
是否为容器(true/false) |
| ansible_container_type |
容器类型(docker/podman/lxc) |
| ansible_ec2_* |
AWS EC2 云主机信息 |
| ansible_azure_* |
Azure 云主机信息 |
| ansible_gce_* |
GCP 谷歌云主机信息 |
| ansible_system_vendor |
服务器硬件厂商(Dell/VMware/QEMU) |
5.2.7 用户、环境、时间
| 变量名 |
用途说明 |
| ansible_user_id |
当前执行 ansible 用户 UID |
| ansible_group_id |
当前执行 ansible 用户 GID |
| ansible_user_dir |
当前用户家目录 |
| ansible_env |
系统环境变量全量字典 |
| ansible_date_time |
时间复合字典 |
| ansible_date_time.iso8601 |
ISO 标准格式时间 |
| ansible_date_time.epoch |
时间戳 |
5.2.8 Windows 系统专属 Facts
| 变量名 |
用途说明 |
| ansible_os_version |
Windows 系统版本 |
| ansible_windows_domain |
Windows 域信息 |
| ansible_windows_systemroot |
Windows 系统目录 |
| ansible_total_physical_memory_mb |
Windows 总物理内存 |
5.2.9 playbook 全局内置变量(非 setup 采集 facts,配套使用)
| 变量名 |
用途说明 |
| inventory_hostname |
Inventory 清单内定义的主机名 |
| inventory_hostname_short |
Inventory 主机短名 |
| groups |
全部分组主机字典 |
| group_names |
当前主机所属分组列表 |
| play_hosts |
当前 play 执行的主机列表 |
| ansible_version |
Ansible 工具版本信息字典 |
5.3 测试案例
1.查看资源清单
(venv) [root@ansible99 playbook]# cat /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini
[all]
master231 ansible_host=10.0.0.231 ip=10.0.0.231
master232 ansible_host=10.0.0.232 ip=10.0.0.232
master233 ansible_host=10.0.0.233 ip=10.0.0.233
worker66 ansible_host=10.0.0.66 ip=10.0.0.66
worker77 ansible_host=10.0.0.77 ip=10.0.0.77[kube_control_plane]
master231
master232
master233[etcd]
master231
master232
master233[kube_node]
worker66
worker77(venv) [root@ansible99 playbook]# 2.编写playbook
(venv) [root@ansible99 playbook]# cat 08-facts.yaml
- hosts: kube_control_plane# 获取客户端信息tasks:- name: print server infodebug:msg: '"{{ ansible_hostname }}" --- "{{ ansible_default_ipv4.address }}" --- {{ ansible_virtualization_type }}'- name: mkdir dirfile:path: /tmp/{{ ansible_hostname }}-{{ ansible_default_ipv4.address }}state: directory
(venv) [root@ansible99 playbook]# 3.测试验证
(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 08-facts.yaml PLAY [kube_control_plane] **************************************************************************************************************************************************************************************TASK [Gathering Facts] *****************************************************************************************************************************************************************************************
ok: [master232]
ok: [master233]
ok: [master231]TASK [print server info] ***************************************************************************************************************************************************************************************
ok: [master231] => {"msg": "\"master231\" --- \"10.0.0.231\" --- VMware"
}
ok: [master232] => {"msg": "\"master232\" --- \"10.0.0.232\" --- VMware"
}
ok: [master233] => {"msg": "\"master233\" --- \"10.0.0.233\" --- VMware"
}TASK [mkdir dir] ***********************************************************************************************************************************************************************************************
ok: [master231]
ok: [master232]
ok: [master233]PLAY RECAP *****************************************************************************************************************************************************************************************************
master231 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
master232 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
master233 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 (venv) [root@ansible99 playbook]#
(venv) [root@ansible99 playbook]#
6.template使用变量
6.1 template的作用
如果使用file拷贝一个文件到目的主机,正常情况下就会直接将文件拷贝到目标主机。但是,如果要拷贝的文件中用到了变量,则用file拷贝并不会引用变量,而是直接拷贝文件内容,使用template拷贝则拷贝的文件有变量引用的话,拷贝过去时也会引用相应的变量。
6.2 测试验证
1.准备模板文件
(venv) [root@ansible99 playbook]# cat server.info
------------------------------------------------------------------------------------------------------
- 服务器名称: - {{ ansible_hostname }}
- 服务器IP地址: - {{ ansible_default_ipv4.address }}
- 服务器内存: - {{ ansible_memtotal_mb }}
- 虚拟化类型 - {{ ansible_virtualization_type }} / {{ ansible_virtualization_role }}
- CPU数量: - {{ ansible_processor_count }}
- 逻辑 CPU 总数量 - {{ ansible_processor_vcpus }}
- CPU型号 - {{ ansible_processor }}
-----------------------------------------------------------------------------------------------------
(venv) [root@ansible99 playbook]# 2.编写playbook
(venv) [root@ansible99 playbook]# cat 09-template.yaml
- hosts: kube_control_planetasks:- name: copy server.infotemplate:src: server.infodest: /root/server.txt
(venv) [root@ansible99 playbook]#
(venv) [root@ansible99 playbook]# 3.执行playbook
(venv) [root@ansible99 playbook]# cat /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini
[all]
master231 ansible_host=10.0.0.231 ip=10.0.0.231
master232 ansible_host=10.0.0.232 ip=10.0.0.232
master233 ansible_host=10.0.0.233 ip=10.0.0.233
worker66 ansible_host=10.0.0.66 ip=10.0.0.66
worker77 ansible_host=10.0.0.77 ip=10.0.0.77[kube_control_plane]
master231
master232
master233(venv) [root@ansible99 playbook]#
(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 09-template.yamlPLAY [kube_control_plane] **************************************************************************************************************************************************************************************TASK [Gathering Facts] *****************************************************************************************************************************************************************************************
ok: [master231]
ok: [master233]
ok: [master232]TASK [copy server.info] ****************************************************************************************************************************************************************************************
changed: [master231]
changed: [master233]
changed: [master232]PLAY RECAP *****************************************************************************************************************************************************************************************************
master231 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
master232 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
master233 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 (venv) [root@ansible99 playbook]# 4.查看目标主机信息
[root@master231 ~]# cat server.txt
------------------------------------------------------------------------------------------------------
- 服务器名称: - master231
- 服务器IP地址: - 10.0.0.231
- 服务器内存: - 3868
- 虚拟化类型 - VMware / guest
- CPU数量: - 2
- 逻辑 CPU 总数量 - 2
- CPU型号 - ['0', 'GenuineIntel', 'Intel(R) Core(TM) Ultra 7 356H', '1', 'GenuineIntel', 'Intel(R) Core(TM) Ultra 7 356H']
-----------------------------------------------------------------------------------------------------
[root@master231 ~]# [root@master232 ~]# cat server.txt
------------------------------------------------------------------------------------------------------
- 服务器名称: - master232
- 服务器IP地址: - 10.0.0.232
- 服务器内存: - 3868
- 虚拟化类型 - VMware / guest
- CPU数量: - 2
- 逻辑 CPU 总数量 - 2
- CPU型号 - ['0', 'GenuineIntel', 'Intel(R) Core(TM) Ultra 7 356H', '1', 'GenuineIntel', 'Intel(R) Core(TM) Ultra 7 356H']
-----------------------------------------------------------------------------------------------------
[root@master232 ~]# [root@master233 ~]# cat server.txt
------------------------------------------------------------------------------------------------------
- 服务器名称: - master233
- 服务器IP地址: - 10.0.0.233
- 服务器内存: - 3867
- 虚拟化类型 - VMware / guest
- CPU数量: - 2
- 逻辑 CPU 总数量 - 2
- CPU型号 - ['0', 'GenuineIntel', 'Intel(R) Core(TM) Ultra 7 356H', '1', 'GenuineIntel', 'Intel(R) Core(TM) Ultra 7 356H']
-----------------------------------------------------------------------------------------------------
[root@master233 ~]#
四.Playbook实战之流程控制
1.playbook条件语句概述
任何编程语言几乎都支持流程控制,条件判断,在我们使用ansible的过程中,条件判断也是经常会被使用的。举个例子:- 1.安装同一种软件在不同系统上其软件包名称可能不一致(比如nfs服务),可以通过判断系统来对软件包名称进行修改;- 2.在部署K8S集群之前,我们可以判断现有的环境,是否需要做Linux基础优化(比如禁用swap,修改内核参数,开启本地DNS缓存等);
2.when判断实战
2.1 when条件表达式
精确匹配:when: ansible_hostname == "master231"模糊匹配:when: ansible_hostname is match "master232"when: ansible_hostname is search "master233"
2.2 when案例
1.编写playbook
(venv) [root@ansible99 playbook]# cat 10-when.yaml
- hosts: kube_control_planetasks:- name: remove wgetapt:name: wgetstate: absentwhen: ansible_hostname is match "master"- name: install treeapt:name: treestate: presentwhen: ansible_hostname == "master232"- name: remove curlapt:name: curlstate: absentwhen: - ansible_hostname is match "master" - ansible_default_ipv4.address == "10.0.0.233"# 上面3行,我们可以简写为下面的一行代码# when: (ansible_hostname is match "master") and (ansible_default_ipv4.address == "10.0.0.233")- name: install lrzszapt:name: lrzszstate: presentwhen: (ansible_hostname is match "master233") or (ansible_default_ipv4.address == "10.0.0.231")(venv) [root@ansible99 playbook]# 2.测试验证
(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 10-when.yaml
2.3 部署nginx服务案例
1.准备nginx的配置文件
[root@ansible99 playbook]# cat nginx.conf
error_log stderr notice;worker_processes 2;
worker_rlimit_nofile 130048;
worker_shutdown_timeout 10s;events {multi_accept on;use epoll;worker_connections 16384;
}stream {upstream kube_apiserver {least_conn;server 10.0.0.231:6443;server 10.0.0.232:6443;server 10.0.0.233:6443;}server {listen 127.0.0.1:6443;proxy_pass kube_apiserver;proxy_timeout 10m;proxy_connect_timeout 1s;}
}http {aio threads;aio_write on;tcp_nopush on;tcp_nodelay on;keepalive_timeout 5m;keepalive_requests 100;reset_timedout_connection on;server_tokens off;autoindex off;server {listen 8081;location /healthz {access_log off;return 200;}location /stub_status {stub_status on;access_log off;}}
}
[root@ansible99 playbook]# 2.编写playbook剧本
(venv) [root@ansible99 playbook]# cat 11-nginx-when.yaml
- hosts: kube_control_planetasks:- name: install nginx serviceapt:name: nginxstate: present- name: configure nginx copy:src: nginx.confdest: /root/nginx.conf- name: nginx -tcommand: nginx -tregister: nginx_result# ansible遇到错误就会退出剧本往下执行,如果有错误我们护理后,才能继续往下执行哟。ignore_errors: yes- name: print nginx_resultdebug:msg: "{{ nginx_result }}" - name: start nginx servicesystemd:name: nginxstate: restartedenabled: yes# 如果'nginx_result.rc'的结果为0,表示没有错误,于是就可以重启nginx服务。when: nginx_result.rc is match "0"# 也可以使用'search'进行搜索。# when: nginx_result.rc is search "0"(venv) [root@ansible99 playbook]# 2.执行剧本
(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 11-nginx-when.yaml
3.Handlers实战
3.1 handlers概述
handler用来执行某些条件下的任务,比如当配置发生变化的时候,通过notify出发handler去重启服务。
3.2 实战案例
1.编写playbook
(venv) [root@ansible99 playbook]# cat 12-nginx-notify.yaml
- hosts: kube_control_planetasks:- name: install nginx serviceapt:name: nginxstate: present- name: configure nginx copy:src: nginx.confdest: /root/nginx.conf# 监控配置文件是否发生变化,如果有发生变化则触发同名称的handlers重启服务。notify: Restart Nginx- name: nginx -tcommand: nginx -tregister: nginx_resultignore_errors: yes- name: start nginx servicesystemd:name: nginxstate: restartedenabled: yeswhen: nginx_result.rc is match "0"# 定义触发器handlers:# 当前的触发器我们的操作是用来重启服务的。- name: Restart Nginxsystemd:name: nginxstate: restartedwhen: nginx_result.rc is search "0"
(venv) [root@ansible99 playbook]# 2.第一次执行,会按照服务,触发HANDLER执行
(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 12-nginx-notify.yaml PLAY [kube_control_plane] **************************************************************************************************************************************************************************************TASK [Gathering Facts] *****************************************************************************************************************************************************************************************
ok: [master232]
ok: [master231]TASK [install nginx service] ***********************************************************************************************************************************************************************************
changed: [master232]
changed: [master231]TASK [configure nginx] *****************************************************************************************************************************************************************************************
changed: [master232]
changed: [master231]TASK [nginx -t] ************************************************************************************************************************************************************************************************
changed: [master231]
changed: [master232]TASK [start nginx service] *************************************************************************************************************************************************************************************
changed: [master231]
changed: [master232]RUNNING HANDLER [Restart Nginx] ********************************************************************************************************************************************************************************
changed: [master232]
changed: [master231]PLAY RECAP *****************************************************************************************************************************************************************************************************
master231 : ok=6 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
master232 : ok=6 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 (venv) [root@ansible99 playbook]# 2.第二次执行如果配置文件没有发生变化,则不会触发HANDLER
(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 12-nginx-notify.yaml PLAY [kube_control_plane] **************************************************************************************************************************************************************************************TASK [Gathering Facts] *****************************************************************************************************************************************************************************************
ok: [master231]
ok: [master232]TASK [install nginx service] ***********************************************************************************************************************************************************************************
ok: [master232]
ok: [master231]TASK [configure nginx] *****************************************************************************************************************************************************************************************
ok: [master231]
ok: [master232]TASK [nginx -t] ************************************************************************************************************************************************************************************************
changed: [master231]
changed: [master232]TASK [start nginx service] *************************************************************************************************************************************************************************************
changed: [master232]
changed: [master231]PLAY RECAP *****************************************************************************************************************************************************************************************************
master231 : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
master232 : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 (venv) [root@ansible99 playbook]#
4.循环语句
4.1 循环语句的作用
和其他编程语言类似,循环语句的作用就是减少重复性代码,让代码看起来更简洁。举个例子,如果我们创建10个文件,我们可以写10个file模块,那如果要创建1w个文件呢?
4.2 实战案例
1.编写playbook
(venv) [root@ansible99 playbook]# cat 13-loop-casedemo.yaml
- hosts: kube_control_plane# 执行时直接跳过 Gathering Facts 步骤(不再运行 setup 模块)gather_facts: falsetasks:- name: restart ssh nginx servicesystemd:name: "{{ item }}"state: restartedloop:- nginx- ssh- name: create filefile:path: /tmp/{{ item.path }}state: touchowner: "{{ item.owner }}"group: "{{ item.group }}"mode: "{{ item.mode }}"loop:- { path: a.txt, owner: yinzhengjie, group: yinzhengjie, mode: '0600' }- { path: b.txt, owner: root, group: root, mode: '0666' }- name: copy filecopy:src: "{{ item.src }}"dest: "{{ item.dest }}"owner: "{{ item.owner }}" loop:- { src: /etc/hosts, dest: /opt, owner: yinzhengjie }- { src: /etc/passwd, dest: /root, owner: root }- name: create groupgroup:name: "{{ item.name }}"gid: "{{ item.gid }}"loop:- { name: k8s, gid: '456'}- { name: bigdata, gid: '789'}- name: create useruser:name: "{{ item.name }}"uid: "{{ item.uid }}"group: "{{ item.group }}"shell: "{{ item.shell }}"create_home: "{{ item.home }}"loop:- { name: test01, uid: '111', group: k8s, shell: /bin/bash, home: true }- { name: test02, uid: '222', group: bigdata, shell: /sbin/nologin, home: false }(venv) [root@ansible99 playbook]#
(venv) [root@ansible99 playbook]# 2.执行剧本
(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 13-loop-casedemo.yaml
5.任务标签
5.1 什么是任务标签
默认情况下,ansible在执行一个playbook时,会执行playbook中定义的所有任务。ansible的标签功能给单独任务甚至整个playbook打上标签,然后利用这些标签来指定要运行playbook中的个别任务,活不执行指定的任务。
5.2 实战案例
1.编写playbook(venv) [root@ansible99 playbook]# cat 14-tags-casedemo.yaml
- hosts: kube_control_planegather_facts: falsetasks:- name: restart ssh nginx servicesystemd:name: "{{ item }}"state: restartedloop:- nginx- ssh# 给指定的个别任务打标签tags: xixi- name: create filefile:path: /tmp/{{ item.path }}state: touchowner: "{{ item.owner }}"group: "{{ item.group }}"mode: "{{ item.mode }}"loop:- { path: a.txt, owner: yinzhengjie, group: yinzhengjie, mode: '0600' }- { path: b.txt, owner: root, group: root, mode: '0666' }tags: xixi- name: copy filecopy:src: "{{ item.src }}"dest: "{{ item.dest }}"owner: "{{ item.owner }}" loop:- { src: /etc/hosts, dest: /opt, owner: yinzhengjie }- { src: /etc/passwd, dest: /root, owner: root }tags: haha- name: create groupgroup:name: "{{ item.name }}"gid: "{{ item.gid }}"loop:- { name: k8s, gid: '456'}- { name: bigdata, gid: '789'}- name: create useruser:name: "{{ item.name }}"uid: "{{ item.uid }}"group: "{{ item.group }}"shell: "{{ item.shell }}"create_home: "{{ item.home }}"loop:- { name: test01, uid: '111', group: k8s, shell: /bin/bash, home: true }- { name: test02, uid: '222', group: bigdata, shell: /sbin/nologin, home: false }(venv) [root@ansible99 playbook]# 2.查看剧本存在的标签列表
(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 14-tags-casedemo.yaml --list-tagsplaybook: 14-tags-casedemo.yamlplay #1 (kube_control_plane): kube_control_plane TAGS: []TASK TAGS: [haha, xixi]
(venv) [root@ansible99 playbook]# 3.只执行包含一个或多个tags的tasks
(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 14-tags-casedemo.yaml -t xixi(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 14-tags-casedemo.yaml -t xixi,haha4.跳过带有指定标签的tasks
(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 14-tags-casedemo.yaml --skip-tags xixi(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 14-tags-casedemo.yaml --skip-tags xixi,haha
6.文件复用-task拆解
6.1 什么是文件复用
在之前写playbook的过程中,我们发现写多个playbook没有办法一键执行,这样我们还要单个playbook挨个去执行,很鸡肋。所以在playbook中有一个功能,叫做'include_tasks'用来动态调用task任务列表。这样做的目的可以避免单个playbook文件内容过大的情况。当然,也支持直接导入一个完整的palybook,则需要使用'import_playbook'关键字导入即可。
6.2 实战案例
1.准备任务文件
(venv) [root@ansible99 playbook]# cat user-group.task
- name: delete groupgroup:name: "{{ item.name }}"gid: "{{ item.gid }}"state: absentloop:- { name: dba, gid: '456'}- { name: linux, gid: '789'}- name: delete useruser:name: "{{ item.name }}"uid: "{{ item.uid }}"group: "{{ item.group }}"shell: "{{ item.shell }}"create_home: "{{ item.home }}"state: absentloop:- { name: mongodb, uid: '333', group: dba, shell: /bin/bash, home: true }- { name: clickhouse, uid: '555', group: linux, shell: /sbin/nologin, home: false }(venv) [root@ansible99 playbook]# 2.准备剧本
(venv) [root@ansible99 playbook]# cat 15-include_tasks.yaml
- hosts: kube_control_planegather_facts: falsetasks:- name: xixiinclude_tasks: remove-nginx.task# 由于我关闭了facts的采集,此处就不要用ansible_hostname变量来判断了。when: inventory_hostname is match "master231"- name: hahainclude_tasks: user-group.taskwhen: inventory_hostname is match "master232"
(venv) [root@ansible99 playbook]# 3.测试验证
(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 15-include_tasks.yaml PLAY [kube_control_plane] **************************************************************************************************************************************************************************************TASK [xixi] ****************************************************************************************************************************************************************************************************
skipping: [master232]
included: /root/playbook/remove-nginx.task for master231TASK [remove nginx service] ************************************************************************************************************************************************************************************
changed: [master231]TASK [configure nginx] *****************************************************************************************************************************************************************************************
ok: [master231]TASK [haha] ****************************************************************************************************************************************************************************************************
skipping: [master231]
included: /root/playbook/user-group.task for master232TASK [delete group] ********************************************************************************************************************************************************************************************
ok: [master232] => (item={'name': 'dba', 'gid': '456'})
ok: [master232] => (item={'name': 'linux', 'gid': '789'})TASK [delete user] *********************************************************************************************************************************************************************************************
ok: [master232] => (item={'name': 'mongodb', 'uid': '333', 'group': 'dba', 'shell': '/bin/bash', 'home': True})
ok: [master232] => (item={'name': 'clickhouse', 'uid': '555', 'group': 'linux', 'shell': '/sbin/nologin', 'home': False})PLAY RECAP *****************************************************************************************************************************************************************************************************
master231 : ok=3 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
master232 : ok=3 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 (venv) [root@ansible99 playbook]#
7.抑制changed
7.1 什么是抑制changed
被管理主机没有发生变化,可以使用参数将change状态改为ok。
7.2 实战案例
1.编写剧本
(venv) [root@ansible99 playbook]# cat 16-changed.yaml
- hosts: kube_control_planegather_facts: falsetasks:- name: install nginx serviceapt:name: nginxstate: present- name: configure nginx copy:src: nginx.confdest: /root/nginx.confnotify: Restart Nginx- name: nginx -tcommand: nginx -tregister: nginx_resultignore_errors: yes# 如果没有任何变化,颜色变为绿色。changed_when: false- name: start nginx servicesystemd:name: nginxstate: restartedenabled: yeswhen: nginx_result.rc is match "0"handlers:- name: Restart Nginxsystemd:name: nginxstate: restartedwhen: nginx_result.rc is search "0"
(venv) [root@ansible99 playbook]# 2.测试验证
(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 16-changed.yaml
五.jinja2模板及Role角色
1.jinja2模板
1.1 什么是jinja2模板
jinja2是python大全功能模板引擎,ansible通常会使用jinja2模板来修改被管理主机的配置文件等。使用ansible的jinja2模板也就是使用template模块,该模块和copy模块一样,都是将文件复制到远端主机上去,但是区别在于,template模块可以获取到文件的变量,而copy则是原封不动的把文件内容复制过去。
1.2 实战案例-for循环和if语句
1.编写jinja2模板文件内容
(venv) [root@ansible99 playbook]# cat nginx.conf.j2
upstream {{ server_name }} {{% for apiserver_ip in range(231,234) %}server 10.0.0.{{ apiserver_ip }}:{{ apiserver_port }};{% endfor %}
}server {listen 80;proxy_pass {{ server_name }};location / {root /yinzhengjie/code;index index.html;proxy_pass http://www.yinzhengjie.com;proxy_set_header Host $http_host;}
}
(venv) [root@ansible99 playbook]#
(venv) [root@ansible99 playbook]# cat keepalived.conf.j2
global_defs {router_id {{ ansible_hostname }}
}vrrp_script chk_apiserver {script "/etc/keepalived/check_apiserver.sh"interval 2weight -20
}vrrp_instance VI_K8S_APISERVER {
{% if ansible_fqdn == "master231" %} state MASTERpriority 150
{% else %}state BACKUPpriority 100
{% endif %}interface ens192virtual_router_id 51advert_int 1nopreemptauthentication {auth_type PASSauth_pass yinzhengjie@k8s}virtual_ipaddress {10.0.0.100/24 dev ens192 label ens192:vip}track_script {chk_apiserver}
}
(venv) [root@ansible99 playbook]# 2.编写剧本
(venv) [root@ansible99 playbook]# cat 17-copy-nginx-conf.yaml
- hosts: kube_control_planegather_facts: truevars:- apiserver_port: 6443- server_name: www.yinzhengjie.comtasks:- name: copy nginx conftemplate:src: nginx.conf.j2dest: /root/apiserver.conf- name: copy keepalived conftemplate:src: keepalived.conf.j2dest: /root/keepalved.conf(venv) [root@ansible99 playbook]# 3.测试验证
(venv) [root@ansible99 playbook]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini 17-copy-nginx-conf.yaml
2.Roles角色
2.1 什么是Roles
roles对playbook的一种重新编排,我们可以将一个项目定义为一个角色,将该项目的所有项目都放在该角色目录。roles角色默认的目录有:- defaults:存放默认的配置信息。- files:存放的是配置文件,软件包,依赖库之类的文件。- handlers:定义触发器相关的动作。- meta:存放依赖的文件。- tasks:定义任务。- templates存放jinja2模板文件。- tests:存放测试的相关文件。- vars:存放变量的目录。- README.md:存放项目的说明文件。
2.2 实战案例-部署rsync服务
1.创建存储角色的目录
(venv) [root@ansible99 playbook]# mkdir roles
(venv) [root@ansible99 playbook]#
(venv) [root@ansible99 playbook]# cd roles/
(venv) [root@ansible99 roles]#
(venv) [root@ansible99 roles]# ll
total 8
drwxr-xr-x 2 root root 4096 Jun 15 19:21 ./
drwxr-xr-x 3 root root 4096 Jun 15 19:21 ../
(venv) [root@ansible99 roles]# 2.生成默认的角色目录结构
(venv) [root@ansible99 roles]# ansible-galaxy init k8s
- Role k8s was created successfully
(venv) [root@ansible99 roles]#
(venv) [root@ansible99 roles]# ll
total 12
drwxr-xr-x 3 root root 4096 Jun 15 19:21 ./
drwxr-xr-x 3 root root 4096 Jun 15 19:21 ../
drwxr-xr-x 10 root root 4096 Jun 15 19:21 k8s/
(venv) [root@ansible99 roles]#
(venv) [root@ansible99 roles]# tree k8s/
k8s/
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars└── main.yml9 directories, 8 files
(venv) [root@ansible99 roles]#
(venv) [root@ansible99 roles]#
(venv) [root@ansible99 roles]# cd k8s/
(venv) [root@ansible99 k8s]#
(venv) [root@ansible99 k8s]# ll
total 44
drwxr-xr-x 10 root root 4096 Jun 15 19:21 ./
drwxr-xr-x 3 root root 4096 Jun 15 19:21 ../
drwxr-xr-x 2 root root 4096 Jun 15 19:21 defaults/
drwxr-xr-x 2 root root 4096 Jun 15 19:21 files/
drwxr-xr-x 2 root root 4096 Jun 15 19:21 handlers/
drwxr-xr-x 2 root root 4096 Jun 15 19:21 meta/
-rw-r--r-- 1 root root 1328 Jun 15 19:21 README.md
drwxr-xr-x 2 root root 4096 Jun 15 19:21 tasks/
drwxr-xr-x 2 root root 4096 Jun 15 19:21 templates/
drwxr-xr-x 2 root root 4096 Jun 15 19:21 tests/
drwxr-xr-x 2 root root 4096 Jun 15 19:21 vars/
(venv) [root@ansible99 k8s]# 3.编写剧本文件内容
(venv) [root@ansible99 roles]# cat k8s/tasks/main.yml
---
# tasks file for k8s- name: Install Rsync Serverapt:name: rsyncstate: presenttags: xixi- name: Configure Rsync Server# 不用添加路径,他会自动去"template"目录下找文件template:src: "{{ item.src }}"dest: "{{ item.dest }}"mode: "{{ item.mode }}"loop:- { src: rsyncd.conf.j2, dest: /etc/rsyncd.conf, mode: '0644'}- { src: rsync.passwd, dest: /etc/rsync.passwd, mode: '0600' }notify: Restart Rsync Server- name: Create Group "{{ group }}"group:name: "{{ group }}"gid: 888- name: Create User "{{ user }}"user:name: "{{ user }}"uid: 666group: "{{ group }}"shell: /sbin/nologincreate_home: false- name: Create dir "{{ dir }}"file:path: "{{ dir }}"state: directoryowner: "{{ user }}"group: "{{ group }}"- name: Start Rsync Serversystemd:name: rsyncstate: startedenabled: yes
(venv) [root@ansible99 roles]# 4.编写配置文件目录
(venv) [root@ansible99 k8s]# cat templates/rsyncd.conf.j2
uid = {{ user }}
gid = {{ group }}
port = {{ port }}
fake super = yes
use chroot = no
max connections = 200
timeout = 600
ignore errors
read only = false
list = false
secrets file = /etc/rsync.passwd
log file = /var/log/rsyncd.log[backup]
path = {{ dir }}
comment = 备份目录[data]
path = /data
(venv) [root@ansible99 k8s]# 5.准备认证文件
(venv) [root@ansible99 k8s]# cat templates/rsync.passwd
rysnc_backup:123
(venv) [root@ansible99 k8s]# 6.定义变量
(venv) [root@ansible99 k8s]# cat vars/main.yml
---
# vars file for k8suser: yinzhengjie
group: k8s
port: 873
dir: /yinzhengjie/data/k8s
(venv) [root@ansible99 k8s]# 7.定义触发器
(venv) [root@ansible99 k8s]# cat handlers/main.yml
---
# handlers file for k8s- name: Restart Rsync Serversystemd:name: rsyncstate: restarted
(venv) [root@ansible99 k8s]# 8.删除不必要的文件
(venv) [root@ansible99 roles]# rm -rf k8s/{defaults,meta,tests,README.md}
(venv) [root@ansible99 roles]#
(venv) [root@ansible99 roles]# tree k8s
k8s
├── files
├── handlers
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
│ ├── rsyncd.conf.j2
│ └── rsync.passwd
└── vars└── main.yml6 directories, 5 files
(venv) [root@ansible99 roles]# 9.playbook调用角色
(venv) [root@ansible99 roles]# cat start.yaml
- hosts: allroles:- role: backupwhen: ansible_hostname is match "master232"
(venv) [root@ansible99 roles]# 10.测试验证
(venv) [root@ansible99 roles]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini start.yaml
2.3 实战案例-部署nfs服务
1.准备环境初始目录
(venv) [root@ansible99 roles]# mkdir nfs
(venv) [root@ansible99 roles]#
(venv) [root@ansible99 roles]# cd nfs/
(venv) [root@ansible99 nfs]#
(venv) [root@ansible99 nfs]# ls ../k8s/ | xargs mkdir
(venv) [root@ansible99 nfs]#
(venv) [root@ansible99 nfs]# ll
total 28
drwxr-xr-x 7 root root 4096 Jun 15 21:01 ./
drwxr-xr-x 4 root root 4096 Jun 15 21:01 ../
drwxr-xr-x 2 root root 4096 Jun 15 21:01 files/
drwxr-xr-x 2 root root 4096 Jun 15 21:01 handlers/
drwxr-xr-x 2 root root 4096 Jun 15 21:01 tasks/
drwxr-xr-x 2 root root 4096 Jun 15 21:01 templates/
drwxr-xr-x 2 root root 4096 Jun 15 21:01 vars/
(venv) [root@ansible99 nfs]#
(venv) [root@ansible99 nfs]# tree .
.
├── files
├── handlers
├── tasks
├── templates
└── vars6 directories, 0 files2.编写任务
(venv) [root@ansible99 nfs]# cat tasks/main.yaml
- name: Install nfs Serverapt:name: nfs-kernel-serverstate: present- name: Configure NFS Servertemplate:src: exports.j2dest: /etc/exportsnotify: Restart NFS Service- name: Create Group "{{ group }}"group:name: "{{ group }}"gid: "{{ gid }}"- name: Create User "{{ user }}"user:name: "{{ user }}"uid: "{{ uid }}"group: "{{ group }}"shell: /sbin/nologincreate_home: false- name: create "{{ dir }}"file:path: "{{ dir }}"state: directoryowner: "{{ user }}"group: "{{ group }}"- name: Start nfs Serversystemd:name: nfs-serverstate: started
(venv) [root@ansible99 nfs]# 3.编写handlers
(venv) [root@ansible99 nfs]# cat handlers/main.yaml
- name: Restart NFS Servicesystemd:name: nfs-serverstate: restarted(venv) [root@ansible99 nfs]# 4.准备模板文件
(venv) [root@ansible99 nfs]# cat templates/exports.j2
{{ dir }} {{ ip }}(rw,sync,all_squash,anonuid={{ uid }},anongid={{ gid }})
(venv) [root@ansible99 nfs]# 5.查看变量
(venv) [root@ansible99 nfs]# cat vars/main.yaml
user: yinzhengjie
group: k8s
dir: /yinzhengjida/data
ip: 10.0.0.0/24
uid: 666
gid: 888
(venv) [root@ansible99 nfs]# 6.编写playbook调用角色
(venv) [root@ansible99 nfs]# cd ..
(venv) [root@ansible99 roles]# ll
total 20
drwxr-xr-x 4 root root 4096 Jun 15 21:45 ./
drwxr-xr-x 3 root root 4096 Jun 15 19:21 ../
drwxr-xr-x 7 root root 4096 Jun 15 20:04 k8s/
drwxr-xr-x 7 root root 4096 Jun 15 21:01 nfs/
-rw-r--r-- 1 root root 154 Jun 15 21:45 start.yaml
(venv) [root@ansible99 roles]#
(venv) [root@ansible99 roles]# cat start.yaml
- hosts: allroles:- role: k8swhen: ansible_hostname is match "master232"- role: nfswhen: ansible_hostname is match "master231"
(venv) [root@ansible99 roles]# 7.测试验证
(venv) [root@ansible99 roles]# ansible-playbook -i /root/kubespray/inventory/yinzhengjie-k8s/inventory.ini start.yaml