作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.主机清单管理
1.安装ansible
1.安装ansible
[root@ansible99 ~]# apt -y install ansible sshpass
2.关闭主机密钥检查
[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
EOF
2.定义主机列表
[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 '' -q
2.配置免密链接
[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.77
3.修改主机清单
[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. It
does not make sense in playbooks, but it is useful from `/usr/bin/ansible' to verify
the 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. For
Windows targets, use the [ansible.windows.win_ping] module instead. For Network
targets, use the [ansible.netcommon.net_ping] module instead.
ADDED IN: historical
OPTIONS (= is mandatory):
- data
Data to return for the `ping' return value.
If this parameter is set to `crash', the module will cause an exception.
default: pong
type: str
ATTRIBUTES:
check_mode:
description: Can run in check_mode and return changed status prediction without
modifying target
support: full
diff_mode:
description: Will return details on what has changed (or possibly needs changing
in check_mode), when in diff mode
support: none
platform:
[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: master
vars:
- file01: /tmp/xixi.txt
- file02: haha.txt
tasks:
- name: create {{ file01 }} file
file:
path: "{{ file01 }}"
owner: root
group: root
mode: 0644
state: touch
- name: create {{ file02 }} file
file:
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: master
vars_files:
- pkg.yml
tasks:
- name: Install package
apt:
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: master
tasks:
- name: Install package
apt:
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: master
tasks:
- name: Install package
apt:
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.232
tasks:
- name: Install nginx
apt:
name:
- nginx
state: present
- name: nginx check syntax
command: 'nginx -t'
# 注册变量
register: nginx_result
- name: print nginx_result variables
debug:
# 一般我们不需要查看所有的输出,看指定字段的数据,可以使用"."来取数据即可。
# msg: "{{ nginx_result }}"
msg: "{{ nginx_result.stderr_lines }}"
- name: list nginx conf dir
command: 'ls -lh /etc/nginx/'
register: list_result
- name: print list_result variables
debug:
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: master
vars_files:
- pkg2.yml
tasks:
- name: remove "{{ lnmp.tools.pkg }}" package
apt:
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: master
vars_files:
- pkg2.yml
tasks:
- name: install "{{ lnmp['tools']['pkg'] }}" package
apt:
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 info
debug:
msg: '"{{ ansible_hostname }}" --- "{{ ansible_default_ipv4.address }}" --- {{ ansible_virtualization_type }}'
- name: mkdir dir
file:
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_plane
tasks:
- name: copy server.info
template:
src: server.info
dest: /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.yaml
PLAY [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_plane
tasks:
- name: remove wget
apt:
name: wget
state: absent
when: ansible_hostname is match "master"
- name: install tree
apt:
name: tree
state: present
when: ansible_hostname == "master232"
- name: remove curl
apt:
name: curl
state: absent
when:
- 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 lrzsz
apt:
name: lrzsz
state: present
when: (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_plane
tasks:
- name: install nginx service
apt:
name: nginx
state: present
- name: configure nginx
copy:
src: nginx.conf
dest: /root/nginx.conf
- name: nginx -t
command: nginx -t
register: nginx_result
# ansible遇到错误就会退出剧本往下执行,如果有错误我们护理后,才能继续往下执行哟。
ignore_errors: yes
- name: print nginx_result
debug:
msg: "{{ nginx_result }}"
- name: start nginx service
systemd:
name: nginx
state: restarted
enabled: 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_plane
tasks:
- name: install nginx service
apt:
name: nginx
state: present
- name: configure nginx
copy:
src: nginx.conf
dest: /root/nginx.conf
# 监控配置文件是否发生变化,如果有发生变化则触发同名称的handlers重启服务。
notify: Restart Nginx
- name: nginx -t
command: nginx -t
register: nginx_result
ignore_errors: yes
- name: start nginx service
systemd:
name: nginx
state: restarted
enabled: yes
when: nginx_result.rc is match "0"
# 定义触发器
handlers:
# 当前的触发器我们的操作是用来重启服务的。
- name: Restart Nginx
systemd:
name: nginx
state: restarted
when: 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: false
tasks:
- name: restart ssh nginx service
systemd:
name: "{{ item }}"
state: restarted
loop:
- nginx
- ssh
- name: create file
file:
path: /tmp/{{ item.path }}
state: touch
owner: "{{ 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 file
copy:
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 group
group:
name: "{{ item.name }}"
gid: "{{ item.gid }}"
loop:
- { name: k8s, gid: '456'}
- { name: bigdata, gid: '789'}
- name: create user
user:
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_plane
gather_facts: false
tasks:
- name: restart ssh nginx service
systemd:
name: "{{ item }}"
state: restarted
loop:
- nginx
- ssh
# 给指定的个别任务打标签
tags: xixi
- name: create file
file:
path: /tmp/{{ item.path }}
state: touch
owner: "{{ 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 file
copy:
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 group
group:
name: "{{ item.name }}"
gid: "{{ item.gid }}"
loop:
- { name: k8s, gid: '456'}
- { name: bigdata, gid: '789'}
- name: create user
user:
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-tags
playbook: 14-tags-casedemo.yaml
play #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,haha
4.跳过带有指定标签的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 group
group:
name: "{{ item.name }}"
gid: "{{ item.gid }}"
state: absent
loop:
- { name: dba, gid: '456'}
- { name: linux, gid: '789'}
- name: delete user
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
group: "{{ item.group }}"
shell: "{{ item.shell }}"
create_home: "{{ item.home }}"
state: absent
loop:
- { 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_plane
gather_facts: false
tasks:
- name: xixi
include_tasks: remove-nginx.task
# 由于我关闭了facts的采集,此处就不要用ansible_hostname变量来判断了。
when: inventory_hostname is match "master231"
- name: haha
include_tasks: user-group.task
when: 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 master231
TASK [remove nginx service] ************************************************************************************************************************************************************************************
changed: [master231]
TASK [configure nginx] *****************************************************************************************************************************************************************************************
ok: [master231]
TASK [haha] ****************************************************************************************************************************************************************************************************
skipping: [master231]
included: /root/playbook/user-group.task for master232
TASK [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_plane
gather_facts: false
tasks:
- name: install nginx service
apt:
name: nginx
state: present
- name: configure nginx
copy:
src: nginx.conf
dest: /root/nginx.conf
notify: Restart Nginx
- name: nginx -t
command: nginx -t
register: nginx_result
ignore_errors: yes
# 如果没有任何变化,颜色变为绿色。
changed_when: false
- name: start nginx service
systemd:
name: nginx
state: restarted
enabled: yes
when: nginx_result.rc is match "0"
handlers:
- name: Restart Nginx
systemd:
name: nginx
state: restarted
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 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 2
weight -20
}
vrrp_instance VI_K8S_APISERVER {
{% if ansible_fqdn == "master231" %}
state MASTER
priority 150
{% else %}
state BACKUP
priority 100
{% endif %}
interface ens192
virtual_router_id 51
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_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_plane
gather_facts: true
vars:
- apiserver_port: 6443
- server_name: www.yinzhengjie.com
tasks:
- name: copy nginx conf
template:
src: nginx.conf.j2
dest: /root/apiserver.conf
- name: copy keepalived conf
template:
src: keepalived.conf.j2
dest: /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.yml
9 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 Server
apt:
name: rsync
state: present
tags: 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: 666
group: "{{ group }}"
shell: /sbin/nologin
create_home: false
- name: Create dir "{{ dir }}"
file:
path: "{{ dir }}"
state: directory
owner: "{{ user }}"
group: "{{ group }}"
- name: Start Rsync Server
systemd:
name: rsync
state: started
enabled: 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 k8s
user: 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 Server
systemd:
name: rsync
state: 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.yml
6 directories, 5 files
(venv) [root@ansible99 roles]#
9.playbook调用角色
(venv) [root@ansible99 roles]# cat start.yaml
- hosts: all
roles:
- role: backup
when: 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
└── vars
6 directories, 0 files
2.编写任务
(venv) [root@ansible99 nfs]# cat tasks/main.yaml
- name: Install nfs Server
apt:
name: nfs-kernel-server
state: present
- name: Configure NFS Server
template:
src: exports.j2
dest: /etc/exports
notify: 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/nologin
create_home: false
- name: create "{{ dir }}"
file:
path: "{{ dir }}"
state: directory
owner: "{{ user }}"
group: "{{ group }}"
- name: Start nfs Server
systemd:
name: nfs-server
state: started
(venv) [root@ansible99 nfs]#
3.编写handlers
(venv) [root@ansible99 nfs]# cat handlers/main.yaml
- name: Restart NFS Service
systemd:
name: nfs-server
state: 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: all
roles:
- role: k8s
when: ansible_hostname is match "master232"
- role: nfs
when: 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