Ansible学习-playbook基础部分(二)
Ansible-playbook基本介绍
playbook(剧本)
playbook 是由一个或者多个 play 组成的列表。 play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible 中task 定义好的角色。从根本上来讲,task就是调用 ansible 的一个 Module 。将多个play组织在一个playbook中,即可以让她们联动起来,按照事先编排的机制同唱一台大戏。
举例:
想象你要布置两间客房,给管家留了一张清单。每间客房都先检查床头有没有台灯,没有就放一盏。然后检查台灯有没有亮,没亮就打开。
这张清单就是 Playbook,管家就是 Ansible。
- 主机清单 inventory 相当于房间名册,记录有哪些房间。
- hosts 指定这次要布置哪几间房。
- tasks 是要按顺序做的事,先确保有台灯,再确保灯亮着。
如果管家再检查一遍,发现两间房的台灯都已经亮着,就直接通过。这就是幂等。对应到刚才的例子安装Nginx,台灯就是 Nginx,「有台灯」对应已安装,「灯亮着」对应服务正在运行。
如果Nginx 已经安装并且已经在运行中,就不会重复安装或重启它。这就是 Ansible 里常说的幂等。

1. YAML介绍
一种可读性高的表达资料序列的格式,很多语言都支持YAML文本,和脚本语言的交互性很好,使用实现语言的数据类型,有一个一致的信息模型;易于实现,可以基于流来处理,表达能力强,拓展性好。
Ansible 大多数为标量
标量:单个不可再分的值
标量包括:字符串,布尔值,整数,浮点数,Null,时间,日期
标量的写法
name: wang
或者
name:
wang
对象:键值对的集合,又称映射(mapping)/ 哈希(hashes)/ 字典(dictionary)
字典由多个key和value组成,key和value之间用: 分隔,冒号后必须有一个空格,所有k/v可以放在一行,或者每个k/v分别放在不同行
account: {name:wang,age:34}
或者
account:
name: wang
age: 18
数组(List列表):一组按次序排列的值,又称序列/列表
列表由多个元素组成,每个元素放在不同的行,且元素前均使用 -打头,并且-后面有一个空格,或者将所有元素用[]括起来,放在同一行
course: [linux,python,java]
或者
course:
-linux: haowan
-java: haixing

2. playbook 核心组件
2.1 hosts:执行远程主机列表
---
- hosts: webservers
remote_user: root # 基于什么用户去跑,可不写,需要提权时要写,可不写
gather_fast: no # 可不写,不收集主机相关信息,可以提高效率
# 如果用系统变量,一定要为yes
ignore_errors: yes # 忽略错误继续执行,也可以写再每一个tasks下,
force_handlers: yes # 强制触发handler
2.2 task:任务集
由多个 task 的元素组成的列表,实现每个 task 是一个字典,一个完整的代码块功能,最少元素需要 name 和 task,一个 name 只能包括一个 task。
检查语法是否有问题
---
- hosts: 192.168.155.120
tasks:
- name: this is ping
ping:
- name: this is shell command
shell: ls -l /
- name: wall
command: wall "hello wall"
- name: httpd stats
service:
name: crond
state: restarted
- hosts: 192.168.155.130
tasks:
- name: create User
user:
name: user1
state: present
uid: 1000
group: root
shell: /bin/bash
- name: copy file to user1's home
copy:
src: /etc/hosts
dest: /home/user1
ansible-playbook --syntax-check 1.yaml
ansible-playbook -C 1.yaml

task 谁写再前面先执行谁。
2.3 handler:执行远程主机列表
当关注的资源发生变化是采取一定的操作,可以避免多次有改变时每次都执行指定的操作,取而代之,仅仅在所有的变化发射完成后一次性执行指定操作,在notify中调用handler中定义的操作。
注意:
- 单独定义,然后基于notify中调用handler中定义的操作。
- 如果多个task通知了相同的handlers,此 handlers 仅会在所有 task 结束之后运行一次。 - handlers 是在前面的 task 都成功执行后才会执行,如果前面任何一个 task 失败,会导致handler 跳过执行。
安装 httpd → 改 Listen 8080 → state: started
# 探测服务是否存在
- hosts: 192.168.155.120
tasks:
- name: install httpd
dnf:
name: httpd
state: installed
- name: configure file change
replace:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen.*'
replace: "Listen 8080"
- name: httpd enable start
service:
name: httpd
state: started
enable: yes
但是如果如果 httpd 已经在跑,改了配置文件它不会重启,Listen 8080 不会生效。
用 handler:配置变更时通知 restart,且只在变更时触发(幂等):
---
# 探测服务是否存在
# 安装 httpd → 改 Listen 8080 → state: started
- hosts: 192.168.155.120
tasks:
- name: install httpd
dnf:
name: httpd
state: installed
- name: configure file change
replace:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen.*'
replace: "Listen 8080"
notify: restart httpd # 如果本次这个任务真的改变了文件内容(状态为 changed),那就去触发名叫 restart httpd 的 handler。
- name: httpd enable start
service:
name: httpd
state: started
enable: yes
handlers:
- name: restart httpd
service:
name: httpd
state: restarted
最后触发
2.4 tags:定义标签
在 playbook 文件中,可以利用tags组件,为特定task指定标签,当执行playbook时,可以只执行特定tags
的task,而非整个 playbook 文件,可以一个 task 对应多个tag,也可以多个 task 对应一个 tag 。
运行方式: ansible-playbook --list-tags file.yaml查看所有
---
- hosts: 192.168.155.120
tasks:
- name: install httpd
dnf:
name: httpd
state: installed
- name: configure file change
replace:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen.*'
replace: "Listen 8080"
notify: restart httpd
- name: httpd enable start
service:
name: httpd
state: started
enable: yes
- name: check http configure
shell: httpd -t
- name: copy configure file
copy:
src: /root/anaconda-ks.cfg
dest: /var/www/html/
tags: file
handlers:
- name: restart httpd
service:
name: httpd
state: restarted

2.5 变量
变量名:只能由字母、数字、下划线组成,且只能以字母开头
变量来源:
-
ansible setup facts 远程主机的所有变量都可以直接调用
-
在/etc/ansible/hosts 中定义
普通变量:主机组中主机单独定义,优先级低于公共变量
公共(组)变量:针对主机中所有主机定义统一变量
[dbservers] ## ## db01.intranet.mydomain.net ## db02.intranet.mydomain.net ## 10.25.1.56 192.168.155.120 192.168.155.110 # ansible_connection=local 也就是这个变量 -
通过命令行指定变量:优先级最高
ansible-playbook -e varname=valie--- - hosts: 192.168.155.120 tasks: - name: "install pkname " dnf: name: "{{ pkname }}" state: installed - name: start httpd service: name: "{{ pkname }}" state: started
-
在 playbook 中定义(推荐)
--- - hosts: 192.168.155.120 vars: - pkname: httpd - src_path: /root/anaconda-ks.cfg tasks: - name: "install pkname " dnf: name: "{{ pkname }}" state: installed - name: start httpd service: name: "{{ pkname }}" state: started - name: copy file copy: src: "{{ src_path }}" dest: /tmp/ -
在独立的变量YAML文件中定义(推荐)
--- # vars.yaml pkname: httpd src_path: /root/anaconda-ks.cfg --- - hosts: 192.168.155.120 vars_files: - vars.yaml # 默认同一个路径 tasks: - name: "install pkname " dnf: name: "{{ pkname }}" state: installed - name: start httpd service: name: "{{ pkname }}" state: started - name: copy file copy: src: "{{ src_path }}" dest: /tmp/ -
在 role 中定义
变量定义:
variable=value
variable: value
调用变量
{{ variable }} 有时候需要家双引号 "{{ variable }}"调用主机收集信息时
ansible-playbook -e 选项指定 # -e 的方式优先级高于 playbook 内部的vars 变量
举例:
ansible-playbook test.yaml -e "hosts=www user=root"
1)Setup内置变量
setup 模块主要用来收集主机的信息,这些facts 信息可以直接以变量的形式调用,但是主机数量较多,会影响速度。
常用
ansible all -m setup -a "filter=ansible_processor_vcpus" # 逻辑CPU核心总数
ansible all -m setup -a "filter=ansible_all_ipv4_addresses" # 所有IPv4地址列表
ansible all -m setup -a "filter=ansible_architecture" # 系统架构,如 x86_64
ansible all -m setup -a "filter=ansible_uptime_seconds" # 系统运行时间(秒)
ansible all -m setup -a "filter=ansible_processor" # CPU详细信息列表
ansible all -m setup -a "filter=ansible_env" # 系统环境变量
# 其他比较常用的 Facts 变量
ansible all -m setup -a "filter=ansible_os_family" # 系统家族,如 RedHat / Debian
ansible all -m setup -a "filter=ansible_distribution" # 发行版名称,如 CentOS / Ubuntu
ansible all -m setup -a "filter=ansible_kernel" # 内核版本号
ansible all -m setup -a "filter=ansible_fqdn" # 完整限定域名 FQDN
ansible all -m setup -a "filter=ansible_pkg_mgr" # 包管理工具,如 yum / apt
ansible all -m setup -a "filter=ansible_memtotal_mb" # 内存总量(MB)
ansible all -m setup -a "filter=ansible_memfree_mb" # 内存剩余量(MB)
ansible all -m setup -a "filter=ansible_swaptotal_mb" # Swap 总量(MB)
ansible all -m setup -a "filter=ansible_swapfree_mb" # Swap 剩余量(MB)
ansible all -m setup -a "filter=ansible_mounts" # 磁盘挂载信息列表
ansible all -m setup -a "filter=ansible_devices" # 磁盘设备信息字典
ansible all -m setup -a "filter=ansible_default_ipv4" # 默认IPv4路由/网卡信息
ansible all -m setup -a "filter=ansible_all_ipv6_addresses" # 所有IPv6地址列表
ansible all -m setup -a "filter=ansible_python_version" # 被控主机 Python 版本
ansible all -m setup -a "filter=ansible_date_time" # 日期时间信息字典
# 通配符批量查看
ansible all -m setup -a "filter=ansible_*_mb" # 所有内存相关变量
ansible all -m setup -a "filter=ansible_processor*" # 所有CPU相关变量
ansible all -m setup -a "filter=ansible_*ipv*" # 所有IP相关变量
ansible all -m setup -a "filter=ansible_default_ipv4*" # 默认IPv4相关变量
---
- hosts: all
remote_user: root
gather_facts: yes # 必须为 YES
tasks:
- name: show {{ ansible_nodename }}
shell: echo {{ ansible_nodename }}
2)注册变量 register && debug
上面那种只能进行运行无法显示,只能用注册变量,注册变量必须跟shell绑定
- hosts: all
tasks:
- name: "show hostname"
shell: echo "{{ ansible_nodename }}"
register: name # 讲shell命令执行的变量放在name变量中
- name: "show value"
debug:
msg: "{{ name }}" # 讲register里面的键显示出来

上面那样显示太多,无法准确显示想要的信息
- hosts: all
tasks:
- name: "get message"
shell: "awk -F: 'NR==1{print $1}' /etc/passwd"
register: username
- debug:
var: username.stdout_lines

安装httpd, 并且检测运行状态
---
- hosts: 192.168.155.120
vars:
pkname: httpd
service_name: httpd
tasks:
- name: "install {{ pkname }}"
dnf:
name: "{{ pkname }}"
state: present
- name: "start {{ service_name }}"
service:
name: "{{ service_name }}"
state: restarted
- name: check status
shell: ps -aux | grep {{ service_name }}
register: check_service
- name: debug
debug:
var: check_service.stdout_lines # var: "{{ check_service.stdout_lines }}"
playbook一共七个模块,还剩template和role没有完成编写,这个文章的学习思路呢,就建议多写yaml文件,将其中的每个部分都自己纯手写一下。因为最重要的部分也就是这个剧本部分。


浙公网安备 33010602011771号