Ansible - 基础

Ansible

1、简介

ansible 是2013年推出的一款 IT 自动化和 DevOps 软件,2015年被RedHat收购。

是基于Python 研发,糅合很多老运维工具的优点,实现了批量操作系统配置,批量程序部署,批量运行命令等功能。


1.1、ansible 功能

  • 自动化部署APP
  • 自动化管理配置项
  • 自动化持续交付
  • 自动化(AWS)云服务管理

1.2、ansible 优点

  • 只需要 SSH 和 Python 即可使用
  • 无客户端
  • ansible 功能强大,模块丰富
  • 上手容易,门槛低
  • 基于 Python 开发,做二次开发更容易
  • 使用公司比较多,社区活跃

1.3、ansible 特性

  • 模块化设计,调用特定的模块完成特定任务
  • 基于 Python 语言实现
    • paramiko
    • PyYAML(半结构化语言)
    • Jinja2
  • 其模块支持 JSON 等标准输出格式,可以采用任何编程语言重写
  • 部署简单
  • 主从模式工作
  • 支持自定义模块
  • 支持 playbook
  • 易于使用
  • 支持多层部署
  • 支持异构 IT 环境

2、工作流程

  • 大体执行过程

可以理解为,ansible中有两个集合:主机集合HOST、命令集合CMD

  • 主机集合HOST中的各选定主机,同时执行命令集合CMD中的选定命令
  • 主机集合HOST中的主机可以同时运行部署
  • 命令集合CMD中的命令还是按顺序执行,不是同时执行。


3、安装部署


3.1、管理主机

  • 要求:Python 2.6 或 Python 2.7
  • 一般RedHat6 对应的是 2.6,RedHat7 对应的是 2.7
  • 需要安装模块
    • paramiko
    • PyYAML
    • Jinja2
    • httplib2
    • six

3.2、被管理主机

  • 也称为:托管主机
  • ansible 默认通过SSH 协议管理机器
  • 托管主机要开启SSH 服务,允许 ansible 主机登录
  • 在托管节点上也需要安装 Python 2.5 或以上版本
  • 如果托管节点开启了SELinx,需要安装 libselinux-python

3.3、安装

]# yum -y install ansible
]# ansible --version				# 查看版本及配置文件信息
ansible 2.4.2.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Apr 11 2018, 07:36:10) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)]


3.4、部署公钥

  • 由于 ansible 是通过 SSH 在远程执行命令的
  • SSH 远程执行命令必须要通过认证才行
  • 密码写入配置文件安全性很差,所以一般使用密钥对方式认证
  • 使用Key 方式认证
]# vim /etc/hosts					# 全部主机都需要声明
192.168.1.40 	ansible
192.168.1.41 	web1
192.168.1.42 	web2
192.168.1.43 	db1
192.168.1.44 	db2
192.168.1.45 	cache

--------------------------------------------------------------------------

]# cd /root/.ssh
]# ssh-keygen -t rsa -b 2048 -N '' -f key		# 生成自定义证书
]# ls /root/.ssh/
authorized_keys  key  key.pub  known_hosts
-f   # 定义密钥对名称。这里用自定义的名称,是为了避免与已有密钥冲突。

]# shh-copy-id -i key.pub 主机名				# 传送公钥(证书)给各主机

]# ssh -i key  web1                                    # 连接时需要指定私钥

4、托管主机的管理


4.1、主机的定义与分组

  • 默认的配置文件为:/etc/ansible/ansible.cfg
  • 默认的主机管理文件:/etc/ansible/hosts
  • 默认的已有的主机组:all、localhost
]# vim /etc/ansible/ansible.cfg
[defaults]
inventory = /etc/ansible/hosts		# 定义管理托管主机的配置文件
host_key_checking  = 	False		# SSH时,False:不用yes;Ture:要输yes	

------------------------------------------------------------------------------

]# vim /etc/ansible/hosts                # 管理托管主机的配置文件
... ...
[web]                                    # 定义一个组
web1
web2

[db]
db[1:20]                                 # 组成员有大量数值时,可参考。

[other]
cache  ansible_ssh_port=222              # 单个成员引用变量。

[app:children]                           # 定义一个组集合,成员是组,不是单台主机
web
db

[all:vars]                               # vars:定义一个变量,指定适用的组。
ansible_ssh_private_key_file="/root/.ssh/key"


4.2、自定义配置文件及主机管理文件

  • ansible 可以定义多个配置文件,各自定义主机集合的
  • 配置文件的读取顺序:
    • 首先检测ANSIBLE_CONFIG 变量定义的配置文件
    • 其次检查当前目录下的 ./ansible.cfg 文件
    • 再次检查当前用户家目录下 ~/ansible.cfg 文件
    • 最后检查默认的:/etc/ansible/ansible.cfg
]# mkdir /var/myansible
]# vim  /var/myansible/ansible.cfg            # 创建自定义配置文件
[defaults]
inventory = myhost                            # 定义主机管理配置文件。未指定绝对路径,则就在当前路径
host_key_checking = 	False

]# vim ./myhost                               # 在自定义的主机管理文件中再定义托管主机
[app1]
web1
db1

[app2]
web2
db2

[app:children]
app1
app2

----------------------------------------------------------------------------------
'注意:以上自定义了配置文件。那么在ansible操作这里定义的主机集合时,就需要进入该目录下操作'
]# cd /var/myansible
]# ansible  app1 --list-hosts
]# ansible  all --list-hosts

4.3、inventory 扩展变量

ansible_ssh_port                  # SSH 端口号:如果不是默认的端口,通过此变量可指定
ansible_ssh_user                  # 默认的ssh用户名
ansible_ssh_pass                  # SSH密码。(此方式并不安全,建议使用 --ask-pass 或 SSH密钥)
ansible_ssh_private_key_file      # SSH使用的私钥文件,适用于有多个密钥,而不想使用SSH代理时

vars                              # 变量定义。用于组名后面		
children                          # 子组定义。用于引用其它组名称


4.5、动态主机

  • 以上设置均为静态主机配置,除此之外,还可设置动态主机,这就让ansible 拥有无限可能
  • 静态主机,是指在文件/etc/ansible/hosts 中指定的主机和组
  • 动态主机,是指通过外部脚本获取主机列表,按照其要求格式返回给ansible 命令
  • JSON(JavaScript Object Notation)JavaScript 对象表示法:一种基于文本独立于语言的轻易级数据交换格式

5、基础命令


  • 格式
`]# ansible  主机集合  -m  模块名称  -a  模块参数

-i			# inventory文件路径,或可执行脚本
-k			# 使用交互式登录密码
-e			# 定义变量
-v			# 显示详细信息
  • 基础命令
ansible all --list-hosts
ansible all -m ping  -k            # ping模块,用于测试SSH的连通性。ping模块没有参数。
  • 模块手册
ansible-doc                        # 模块手册相当于shell的man帮助

]# ansible-doc -l                  # 列出所有模块
]# ansible-doc modulename          # 查看帮助

6、常用模块


command(默认模块)

  • 该模块由于是直接在SSHD进程下执行命令,并不具备bash的相关特性。所以,要注意以下问题
  • 命令中如有以下字符无法执行:>、<、|、&
`远程执行命令`
'格式:参数就相当于是命令'
ansible  组名或主机名	-m  模块  -a  '参数'

例:
]# ansible web  -m command -a 'uptime'			# 查看机器负载
]# ansible web,db1  -a  'date +%F_%T'			# 查看日期和时间。默认模块可不写
]# ansible all  -a 'ls /root'

shell

  • shell 模块用法基本和 command 一样,区别是:shell 模块是在SSHD进程下再启用/bin/sh 进行执行命令的,可以执行任意非交互式命令。
  • 交互式命令不能执行。如vim、top等
  • 变量解析
    • ansible 执行命令是二次解析
    • 第一次在本机解析,第二次在托管主机解析
    • 需要第二次解析的变量要使用转义(\)
  • 使用cd 时
    • ansible 是使用ssh 多次连接执行的
    • 连接退出后之前的状态就全部失效了
    • 解决方法:使用 chdir 代替 cd 命令。或直接使用绝对路径
'注意:在使用变量时,要注意解析过程。以下两条命令使用不同引号,得出的结果不一致'
]# ansible web -m shell -a "echo $HOSTNAME"
ansible.tedu.cn
ansible.tedu.cn
]# ansible web -m shell -a 'echo $HOSTNAME'
web1.tedu.cn
web2.tedu.cn


`原因:在于执行过程中的解析顺序不一致。以下为第一种解析详情:`
书写命令:			ansible xxx "echo $HOSTNAME"
解析命令:			本机[bash] 会先对变量进行替换 ----->  ansible xxx "echo ansible"
执行命令:			将命令echo ansible 传输给 托管主机

解析命令:			托管主机收到传输过来的命令 echo ansible 进行解析
执行命令:			托管主机执行命令 echo ansible
输出结果:			ansible

------------------------------------------------------------------------------

]# ansible web -m shell -a 'cd /tmp'
]# ansible web -m shell -a 'touch testfile'

# 以上两条命令是无法实现在/tmp目录下创建文件testfile的。需要用以下方法:

	]# ansible web -m shell -a 'chdir=/tmp  touch testfile'
或
	]# ansible web -m shell -a 'touch /tmp/testfile'

script

  • 在本地编写好脚本,然后使用 script 模块批量执行
  • 该脚本包括但不限于 shell 脚本,只要指定Sha-bang 解释器的脚本都可运行,Python、php、Java等都支持。
]# vim useradd.sh
#!/bin/bash
id nb
if [ $? -ne 0 ];then
	useradd wk
	echo 456 | passwd --stdin wk
fi

]# ansible web -m script -a '/root/useradd.sh'

yum

  • yum 模块:yum包管理器,用于管理软件包
'参数:'
name				# 要进行操作的软件包名字
state				# 动作(installed,removed)

]# ansible db -m yum -a 'name="mariadb-server"  state=installed'

]# ansible cache -m yum -a 'name="lrzsz"  state=removed'

service

  • service 模块:服务管理模块
'参数:'
name				# 必选项,服务名称
enabled				# 是否开机启动 yes 或 no
sleep				# 执行restarted,会在stop和start之间沉睡几秒钟
state				# 对当前服务执行:启动、停止、重启、重新加载等操作(started,stopped,restarted,reloaded)

]# ansible db -m service -a 'name=mariadb enabled=yes state=started'

copy

  • copy 模块:复制文件到远程主机
'参数:'
src                     # 本地文件。注意:若路径以"/"结尾,只复制目录里的内容。不以"/"结尾,复制整个目录
dest			# 远程主机的绝对路径,如果源文件是目录,那此路径必须也是目录

backup			# 覆盖前先备份原文件,备份文件会包含时间信息。有2个选项:yes/no
force			# 有2个选项:yes/no。yes:文件存在强制覆盖;no:不存在才复制。默认是yes

`复制文件`
]# ansible all -m copy -a 'src=/etc/resolv.conf dest=/etc/resolv.conf'
`复制目录`
]# ansible all -m copy -a 'src=/etc/yum.repos.d  dest=/etc/'

lineinfile

  • lineinfile 模块:类似 sed 的一种行编辑替换模块。效果是:整行替换
'参数:'
path			# 目标文件
regexp			# 正则表达式,搜索要修改的行
line			# 最终修改的结果

]# ansible db -m lineinfile -a \ 
-> 'path=/etc/my.cnf regexp="^binlog-format" line="binlog-format=mixed" 

replace

  • 也是类似 sed 的一种行编辑替换模块。但是效果是:精确替换
'参数:'
path			# 目标文件
regexp			# 正则表达式。搜索要修改的
replace			# 替换后的结果

]# ansible db -m replace -a 'path=/etc/my.cnf regexp=mixed  replace=row'

setup

  • 主要用于获取主机信息,playbooks 里经常会用的另一个参数 gather_facts 与该模块相关
  • setup 模块最常用的参数是 filter
filter			# 过虑所需要的信息
--tree:将所有主机的输出信息保存到指定目录下,以/etc/ansible/hosts里的主机名为文件名


]# ansible web -m setup -a 'filter=ansible_default_ipv4' --tree /tmp/


Playbook

1、ansible 的七种武器


  • ansible 命令

    • 用于执行临时性的工作,必须掌握
  • ansible-doc

    • 模块的文档说明,必须掌握
  • ansible-playbook

    • 日常应用中使用频率最高的命令,必须掌握
    • 工作机制:通过读取先编写好的 playbook 文件实现批量管理
    • 可以理解为:按一定条件组成的 ansible 任务集
  • ansible-galaxy

    • 从 github 上下载管理 Roles 的一款工具,与 python 的pip类似。里面有大量的经典案例,可用于以后工作中,需要知道
  • ansible-console

    • 是 ansible 为用户提供的交互式工具
    • 用户可在 ansible-console 虚拟出来的终端上像shell 一样使用 ansible 内置的各种命令
  • ansible-vault

    • 主要用于配置文件加密。没什么大用,了解即可
  • ansible-pull

    • ansible 的一种工作模式。
    • ansible 有2种模式:push、pull
      • 默认是push,可以理解为由ansible主动的发起配置工作。
      • 默认模式push,在大批量机器配置时,即使是使用高并发线程依旧需要花费很多时间
    • pull 模式:可以理解为由ansible 主机提供配置命令,由托管主机主动发起配置。
      • 此模式适用大批量机器配置场景(一般2000台以上)
      • 灵活性稍有欠缺
      • 但是,效率几乎可以无限提升
      • 对运维人员的技术水平和前瞻性规划有较高要求

2、JSON


2.1、JSON

  • JSON 是 JavaScript 对象表示法,是一种基于文本、独立于语言、轻量级数据交换的,格式
  • JSON 中的分隔符限于:单引号、小括号、中括号、大括号、冒号、逗号
  • 简而言之:JSON 不是语言,就是一个字符串,一种格式,这个字符串有特定的格式

2.2、JSON 特性

  • JSON 是纯文本
  • JSON 具有”自我描述性“(人类可读)
  • JSON 具有层级结构(值中存在值)
  • JSON 可通过 JavaScript 进行解析

2.3、JSON 语法规则

  • 数据在:名称/值
  • 数据由逗号分隔
  • 大括号保存对象
  • 中括号保存数组

2.4、JSON 书写格式

  • JSON 数据的书写格式:名称/值对
'两种基本形式'
[x,y,z]                  # 数组
k:v                      # 键值对		

k:{x:y}                  # 值为键值对

k:[x,y,z]                # 值为数组

k:[{x:1},{y:2},{z:3}]      # 值为数组 套 键值对


3、YAML


3.1、YAML

  • YAML (YAML Aii't Markup Language)
  • YAML 是一个可读性高,用来表达数据序列的格式
  • YAML 参考了多种语言,如:C、Python、Perl 等,并从XML、电子邮件的数据格式中获得灵感
  • CLARK EVANS 在2001年首次发表了这种语言,目前已有数种编程语言或脚本语言支持这种语言

3.2、YAML 基础语法

  • YAML 的结构通过空格来展示
  • 数组使用"- "(注意,这里是:减号加空格)来表示
  • 键值对使用:": "(冒号加空格)来表示
  • YAML 使用一个固定的缩进风格表示数据、用来表示数据层级结构关系
  • 一般每个缩进级别由两个以上空格组成
  • #表示注释
  • 重点注意
    • 不要使用 TAB,一定要用空格
    • 同一层级缩进必须对齐
'键值的表示方法'
# 采用冒号分隔
# 冒号后面必须有一个空格

'基本的2种形式表示:'
k: v                        # 第1种:冒号后面加空格
k:                          # 第2种:通过层级表示,层级之间至少有2个空格
  v

'复杂的键值2种表示方法:'
k: {x: y}
k:
  x:
    y


'数组的表示方法:'
# 使用一个短横杠加一个空格
k: [x,y]
k:
  - x
  - y
  - z

k: [{x: 1},{y: 2},{z: 3}]
k:
  - x: 1
  - y: 2
  - z: 3


k: [  {[ {x1: 1},{x2: 2},{x3: 3} ]},{[ {y1: 1},{y2: 2},{y3: 3} ]},{[ {},{},{} ]}  ]
k:
  - 
    x1: 1
    x2: 2
    x3: 3
  - 
    y1: 1
    y2: 2
    y3: 3
  - 
    z1: 1
    z2: 2
    z3: 3

4、Jinja2


4.1、Jinja2

  • 这是基于 Python 的模板引擎,包含:变量、表达式。两者在求值时会被替换为值
  • 模板中还有标签,控制模板的逻辑
  • playbook 的模板就是用 Jinja2 模板来处理的

4.2、基本语法

  • 模板的表达式都是包含在分隔符 "{{ }}" 内的
  • 控制语句都是包含在分隔符 "{% %}" 内的
  • 模板支持注释,都是包含在分隔符 "{# #}" 内,支持块注释
  • 在Jinja2 中,字符串必须加引号
{# 调用变量 #}
{{varname}}

{# 计算 #}
{{2+3}}

{# 判断 #}
{{1 in [1,2,3]}}


{# 控制语句 #}
{% if name == '诗仙' %}
  李白
{% elif name == '诗圣' %}
  杜甫
{% elif name == '诗魔' %}
  白居易
{% else %}
  李贺
{% endif %}


{% if name == ... ... %}
  ... ...
{% elif name == '于谦' %}
  {% for method in [抽烟,喝酒,烫头] %}
    {{do method}}
  {% endfor %}
  ... ...
{% endif %}

  • Jinja2 过滤器
    • 变量可以通过过虑器修改。
    • 过滤器与变量用管道符号(|)分割
    • 也可以用圆括号()传递可选参数
    • 多个过滤器可以链式调用,前一个过虑器的输出作为后一个过虑器的输入
    • 在线文档:http://docs.jinkan.org/docs/jinja2/templates.html # builtin-filters
{# 加密一个字符 #}
{{ 'abcd' | password_hash('sha512') }}

password_hash   这就是一个变量过虑器

5、playbook


5.1、简介

  • playbook 是 ansible 用于配置,部署和管理托管主机的剧本(相当于脚本)
  • 通过 playbook 的详细描述,执行其中的一系列 tasks ,可以让远端主机达到预期状态
  • 为什么要使用 playbook
    • 当设施或部署过于复杂时,执行 ad-hoc 命令就不再方便适用了
    • playbook 可以反复使用编写的代码,可以像函数一样,最大化利用代码
    • 在使用 ansible 过程中,处理的大部分操作都是在编写 playbook

5.2、语法格式

  • playbook 是由YAML 语言编写的,遵循YAML标准
  • 在同一行中,# 之后的内容表示注释
  • 同一个列表中的元素应该保持相同的缩进
  • playbook 由一个或多个 play 组成
  • play 中 hosts,variables,roles,tasks 等对象的表示方法都是键值中间以": "冒号空格分隔
  • YAML 的文件开始行都是以"---"3个小横杠开始的

5.3、构成、结果

  • playbook 的构成
    • hosts:定义将要执行的 playbook 的远程主机组
      • 主机的集合,以逗号为分隔符
      • remote_user 用户名:这是用来定义SSH连接主机时使用哪个用户连接。默认是root
    • vars:定义 playbook 运行时需要使用的变量
    • tasks:定义将要在远程主机上执行的任务列表
      • 命令的集合
      • 每个play 包含一个task 列表(任务列表)
      • 一个task 在其所对应的所有主机上执行完毕后,下一个task 都会执行
    • handlers:定义 task 执行完成以后需要调用的任务,即触发任务
  • playbook 执行结果
    • 使用 ansible-playbook 运行 playbook 文件,输出内容为 JSON 格式
    • 绿色代表执行成功
    • ***色代表系统状态发生改变
    • 红色代表执行失败

5.4、基本格式

]# vim myping.yml			# 创建playbook文件,后缀以.yml 结尾
---
- name: 这里是注释
  hosts: 主机组
  remote_user: root    SSH连接时的用户,默认是root,可不写
  tasks: 命令的集合
    - 模块名: 
        参数组
        
      
]# vim myping.yml
---
- name: test ping
  hosts: web,db
  remote_user: root
  tasks: 
    - ping: 
  
]# cat -A myping.yml			# 这个命令可以检查出格式中是否有tab。

]# ansible-playbook  mypb.yml  -f 5
-f     # 定义并发进程数量,默认是5。如需要自定义,一般设置为CPU的2~8倍。

6、语法进阶


vars 变量

---
- hosts: web
  remote_user: root
  vars:
    uname: lisi
  tasks: 
    - name: create user "{{uname}}"
      user: 
        name: "{{uname}}"
    - shell:echo 123 | passwd --stdin "{{uname}}"
  • 以上playbook并不完善,密码还是用的shell模块;user 模块本身是有密码参数password的
  • 但是user 模块的密码参数不能直接使用,因为password参数会把字符串直接写入/etc/shadow 中,会出现密码是明文的问题。
  • 所以,需要通过变量过虑器passwork_hash 来实现加密
---
- hosts: web
  remote_user: root
  vars:
    uname: lisi
    pwd: 123
  tasks: 
    - name: create user
      user: 
        name: "{{uname}}"
        passoword: "{{ pwd | passwork_hash('sha512') }}"
        
# password_hash 过虑器;sha512 Linux的加密方式
  • 变量的参数可以通过命令中进行传递,或者将参数以JSON 或 YAML 格式写成文本进行读取
]# vim args.yml
---
uname: zhangsan
pwd: 123

]# ansible-playbook user.yml -e @args.yml

或:
]# ansible-playbook user.yml -e [{uname: zhangsan},{pwd: 123}]

ignore_errors

  • ansible-playbook 对错误命令的处理方式
    • 默认情况判断 $?,如果值不为0就停止执行
  • 但有些情况我们需要忽略错误继续执行
  • ignore_errors:对错误的处理方式
    • Ture:忽略错误继续执行下一条命令
    • False:遇到错误即停止(默认)
--- 
- hosts: web1
  remote_user: root
  tasks: 
    - shell: mkdir /tmp/apache
      ignore_errors: Ture
    - name: restart service httpd
      service: 
        name: httpd
        state: restarted

tags

  • tags:给指定的任务定义一个调用标识。即打标签。
'使用格式'
- name: NAME
- module: arguments
- tags: TAG_ID				# TAG_ID 自定义标签名

'调用方式'
]# ansible-playbook xxx.yml -t TAG_ID 
---
- hosts: web
  remot_user: root
  tasks: 
    - name: modify index
      copy:
        src: /root/index.html
        dest: /var/www/html/index.html
        owner: root
        group: root
        mode: 0644
      tags: update_index
    - name: modify conf
      copy: 
        src: /root/httpd.conf
        dest: /etc/httpd/conf/httpd.conf
        owner: apache
        group: apache
        mode: 0644
      tags: update_conf
    - name: restart httpd
      service: 
        name: httpd
        state: restarted
        
        
]# ansible-playbook conf.yml -t update_conf

handlers

  • 触发任务:当关注的资源发生变化时采取的操作
  • notify 这个 action 可用于在每个 play 的最后被触发,这样可以避免有多次改变发生时,每次都执行指定的操作,从而变成:仅在所有的变化发生完成后一次性地执行指定操作
  • notify 是调用;handlers 是定义可以被触发执行的命令。即:notify 调用 handlers
    • 注意:handlers一定要有- name。因为 notify 调用时就是以 NAME 为标识
---
- hosts: web
  remot_user: root
  tasks: 
    - name: modify index
      copy:
        src: /root/index.html
        dest: /var/www/html/index.html
        owner: root
        group: root
        mode: 0644
      tags: update_index
    - name: modify conf
      copy: 
        src: /root/httpd.conf
        dest: /etc/httpd/conf/httpd.conf
        owner: apache
        group: apache
        mode: 0644
      tags: update_conf
      notify: 
        - restart httpd                   # 调用时就是填写handlers中的NAME
  handlers:                               # 注意:handlers中一定要有命名:- name
    - name: restart httpd
      service: 
        name: httpd
        state: restarted
  • 注意事项
    • 多个 task 触发同一个 notify 的时候,同一个服务只会触发一次
    • notify 可以触发多个条件,在生产环境中往往涉及到某一个配置文件发生改变,需要重启多个服务的场景,handlers 用到这里就非常适合
    • 结合 vars 可以写出非常普适的服务管理脚本

when

  • 满足特定的条件后再触发某一项操作,或,特定的条件终止某个行为。用when 做条件判断
  • 可将远程系统中的变量 facts 作为 when 的条件,facts可通过setup模块查看
---
- name: Install vim
  hosts: all
  tasks: 
    - name: when yum
      yum: 
        name: vim
        state: installed
      when: ansible_os_family == "RedHat"
    - name: when apt
      apt:
        name: vim
        state: installed
      when: ansible_os_family == "Debian"
      

register

  • 保存前一个命令的返回状态,在后面进行调用
  • 适用于需要判断前一个命令的状态,再决定是否执行下一步的操作
---
- hosts: web 
  remote_user: root
  tasks: 
    - shell: uptime | awk '{printf ("%.2f\n",$(NF-2))}'
      register: result                              # 注意:这里是一定写result的。
    - service:
        name: httpd
        state: stopped
      when: result.stdout|float > 0.7
      
      
      
]# awk 'BEGIN{while(1){}}' &                        # 此命令为提高CPU负载。一个死循环


此案例为:当系统负载超过一定值时,将httpd服务停止。
]# uptime
 19:23:09 up  8:48,  1 user,  load average: 0.00, 0.01, 0.05
]# uptime | awk '{printf ("%.2f\n",$(NF-2))}'		# 此命令为提取CPU数据中1分钟那段
0.00
result.stdout|float > 0.7				# stdout:标准输出;float:浮点数据型

with_items

  • with_items 是playbook 标准循环,可以用于迭代一个列表或字典,通过 {{ item }} 获取每次迭代的值
---
- hosts: web
  remote_user: root
  tasks:
    - name: add users
      user: 
        group: {{ item.group }}
        password: {{ item.passwd | password_hash('sha512') }}
      with_items:
        - uname: nb
          group: bin
          passwd: "123456"
        - uname: wk
          group: man
          passwd: banana
        - uname: dd
          group: daemon
          passwd: book
        - name: jj
          group: mysql
          passwd: 123qqq...A
        

include and roles

  • 在编写 playbook 的时候,随着项目越来越大,playbook 也越来越复杂,修改也很麻烦
  • 此时,可以把一些play、task 或 handler 放到其它文件中,通过 include 指令包含进来,容易管理
  • 注意:include 只能引入单个文件
---
- hosts: 
  tasks:
    - include: tasks/setup.yml
    - include: tasks/users.yml  user=plj	# users.yml中可通过 {{user}} 来使用这些变量
  ... ...
  handlers:
    - include: handlers/handlers.yml
    
  • roles 是加强版的 include,它可以引入一个项目的文件和目录
  • 一般所需的目录层级有
    • vars:变量层
    • tasks:任务层
    • handlers:触发条件
    • files:文件
    • template:模板
    • default:默认,优先级最低
  • 注意:roles 引用时规定了,只能引用的文件名为:main.yml
    • 假如:有一个play 包含了一个叫 "x" 的 role,则
      • x/tasks/main.yml
      • x/vars/main.yml
      • x/handler/main.yml
      • x/... ... /main.yml
    • 以上这些都会添加进这个 play

7、debug 调试


  • 几种简单的排错调试方法
    • 显示受到影响的主机:--list-hosts
    • 显示工作的task:--list-tasks
    • 显示将要运行的tag:--list-tags
  • debug 模块:可以在运行时输出更为详细的信息,帮助我们排错
---
- hosts: web 
  remote_user: root
  tasks: 
    - shell: uptime | awk '{printf ("%.2f\n",$(NF-2))}'
      register: result									
    - service:
        name: httpd
        state: stopped
      when: result.stdout|float > 0.7
    - name: show debug info
      debug:
        var: result                        # 定义要输出详情的变量。
posted @ 2021-01-17 10:31  亘古一顺  阅读(75)  评论(0)    收藏  举报