ansible 优点
只需要SSH 和Python 即可使用
无客户端
ansible 功能强大,模块丰富
上手容易,门槛低
基亍Python 开发,做二次开发更容易
使用公司比较多,社区活跃
ansible 特性
模块化设计,调用特定的模块完成特定任务
基于Python 语言实现
Paramiko、PyYAML (半结构化语言)
Jinja2
其模块支持JSON 等标准输出格式,可以采用任何编程语言重写
部署简单
主从模式工作
支持自定义模块
支持playbook
易亍使用
支持多层部署
支持异构IT 环境
ansible 安装
软件依赖关系
(1)对管理主机
要求Python 2.6版本以上
ansible 使用以下模块,都需要安装
paramiko、PyYAML、Jinja2、httplib2、six
(2)对于被托管主机
<1>ansible 默认通过SSH 协议管理机器
<2>被管理主机要开启ssh 服务,允许ansible 主机登彔
<3>在托管节点上也需要安装Python2.5以上的版本
Ansible 的安装
pip install -y paramiko PyYAML Jinja2 httplib2 six #安装ansible 的依赖
apt install -y ansible #安装ansible
ansible 配置文件
配置文件目录: /etc/ansible/
执行文件目录: /usr/bin/
ib 依赖库: /usr/lib/python2.7/site-packages/ansible/
help 文件: /usr/lib/python2.7/site-packages/ansible
ansible 配置文件查找顺序
检查环境变量ANSIBLE_CONFIG 指向的路径文件(export
ANSIBLE_CONFIG=/etc/ansible.cfg);
./ansible.cfg,检查当前目录下的ansible.cfg 配置文件;
~/ansible.cfg 检查当前用户家目录下
/etc/ansible.cfg 检查etc 目录的配置文件。
ansible 配置文件参数详解/etc/ansible/ansible.cfg
ansible 有许多参数,下面我们列出一些常见的参数:
inventory = /etc/ansible/hosts #这个参数表示资源清单inventory 文件的位置
library = /usr/share/ansible #指向存放Ansible 模块的目录,支持多个目录方式,
只要用冒号(:)隔开就可以
forks = 5 #并发连接数,默认为5
sudo_user = root #设置默认执行命令的用户
remote_port = 22 #指定连接被管节点的管理端口,默认为22端
口,建议修改,能够更加安全
host_key_checking = False #设置是否检查SSH 主机的密钥,值为True/False。
关闭后第一次连接不会提示配置实例
timeout = 60 #设置SSH 连接的超时时间,单位为秒
log_path = /var/log/ansible.log #指定一个存储ansible 日志的文件(默认不记录
日志)
定义Inventory(主机列表)
ansible 的主要功用在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory file 中将其分组命名。
默认的inventory file 为/etc/ansible/hosts。
inventory file 可以有多个,且也可以通过Dynamic Inventory 来动态生成。
Inventory 文件格式:
inventory 文件遵循INI 文件风格,中括号中的字符为组名。可以将同一个主机同时归并到多个不同的组中;此外,当如若目标主机使用了非默认的SSH 端口,还可以在主机名称之后使用冒号加端口号来标明。
[webservers]
www1.com:2222
www2.com
[dbservers]
db1.com
db2.com
db3.com
如果主机名称遵循相似的命名模式,还可以使用列表的方式标识各主机,例如:
[webservers]
www[01:50].example.com
[databases]
db-[a:f].example.com
inventory 其他的参数
ansible 基于ssh 连接inventory 中指定的远程主机时,还可以通过参数指定其交互方式;这些参数如下所示:
ansible_ssh_host # 远程主机
ansible_ssh_port # 指定远程主机ssh 端口
ansible_ssh_user # ssh 连接远程主机的用户,默认root
ansible_ssh_pass # 连接远程主机使用的密码,在文件中明文,建议使用--ask-pass 或者使用SSH keys
ansible_sudo_pass # sudo 密码, 建议使用--ask-sudo-pass
ansible_connection # 指定连接类型: local, ssh, paramiko
ansible_ssh_private_key_file # ssh 连接使用的私钥
ansible_shell_type # 指定连接对端的shell 类型, 默认sh,支持csh,fish
ansible_python_interpreter # 指定对端使用的python 编译器的路径
SSH 服务的免密钥登录
Ansible 是基于ssh 连接的,为方便管理,一般我们会首先配置管理机登陆被管理机的免密认证,以及其它一些必要的配置。
示例:
1、准备虚拟机
4台虚拟机:
(ansible 192.168.200.10)
(node1 192.168.200.11)
(node2 192.168.200.12)
(node3 192.168.200.13)
2、配置免密登陆和hosts 解析
ssh-keygen 一直回车#生成密钥
ssh-copy-id node1 #拷贝私钥
所有机器都必须是免密登陆
4台主机上面配置/etc/hosts,以ansible 主机为例
vim /etc/hosts
192.168.200.10 ansible
192.168.200.11 node1
192.168.200.12 node2
192.168.200.13 node3
Copy 到每台主机:
for i in {10..13}; do scp /etc/hosts 192.168.200.$i:/etc/hosts; done
3、安装ansible
apt install -y ansible
4、配置主机清单
vim /etc/ansible/hosts
[web]
node1
node2
[db]
node3
5、结果测试
ansible all -m ping
node2 | SUCCESS => {
"changed": false,
"ping": "pong"
}
node1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
node3 | SUCCESS => {
"changed": false,
"ping": "pong"
}
ansible web -m ping
node2 | SUCCESS => {
"changed": false,
"ping": "pong"
}
node1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
ad-hoc 单行命令执行模式
批量执行单条任务,相当于在某个范围服务器组中的每一台上执行一个任务命令,如安装软件、copy 文件等
获得模块的帮助文档
ansible-doc -l 列出所有可用的模块, 版本2.7.7, 2078 个模块
ansible -s <module-name> 可以查看指定module 的用法
参看官方帮助文档
参看官方帮助文档
示例:
ansible-doc -s apt
ansible-doc -l| wc -l
语法格式
ansible <host-pattern> [options]
常用格式:
ansible 主机模式-m 模块[-a '参数'] [-i 主机清单文件]
常用选项:
-b,--become:特权方式运行命令。
-s, 以sudo 来运行命令
-m:要使用的模块名称。
-a,--args:制定模块所需的参数。
-u:制定连接的用户名。
-h,--help 显示帮助内容。
-v,--verbose 以详细信息模式运行命令,可以用来调试错误。
示例:
ansible all -m apt -a “name=apache2 state=present”-b
主机模式
ansible 支持主机列表的正则匹配
全量: all/*
逻辑或: :
逻辑非: !
逻辑与: &
切片:[]
正则匹配:以~开头
示例:
ansible all -m ping #所有默认inventory 文件中的机器
ansible "*" -m ping #同上
ansible 121.28.13.* -m ping #所有122.28.13.X 机器
ansible web1:web2 -m ping #所有属于组web1 或属于web2 的机器
ansible web1:!web2 -m ping #属于组web1,但不属于web2 的机器
ansible web1&web2 -m ping #属于组web1 又属于web2 的机器
ansible webserver[0] -m ping #属于组webserver 的第1 台机器
ansible webserver[0:5] -m ping #属于组webserver 的第1 到4 台机器
ansible "~(beta|web)\.example\.(com|org)" -m ping
示例:
多个组的并集
ansible web,db -m ping
或者
ansible 'web:db' -m ping
多个组的交集
ansible 'web:&db' -m ping
多个组的差集
ansible 'web:!db' -m ping
注意:其中括起组名的必须是单引号''
Ansible 常用的模块
文件模块
copy:把文件从本机拷贝到远程
file:设置文件的权限等属性
lineinfile:确保文件中存在或不存在某些行
syncchronize:能过rsync 同步内容
软件包模块
package:通过自动检测,使用操作系统原生的包管理器管理软件
apt:通过apt 进行软件包管理
mount:文件系统挂载
dnf:通过dnf 进行软件包管理
gem:管理Ruby gems
pip:从PyPI 进行python 包管理
系统模块
firewall:通过firewall 管理服务和端口
reboot:重启主机
service:管理服务
user:添加、删除、管理用户
网络工具模块
get_url:通过htp/htts/ftp 下载文件
nmcli:管理网络
uri:与Web 服务交互
1、ping 模块
ansible all -m ping #查看ping 客户端组情况
2、command 命令模块
ansible all -m command -a "uptime" #查看客户端负载信息
ansible all -m command -a "useradd deepintest" #在客户端添加用户
ansible all -m command -a "touch /deepintest" #在客户端建立文件
ansible all -m command -a "chdir=/tmp pwd" #先改变目录,再执行pwd
3、shell 模块
让远程主机在shell 进程下执行命令,从而支持shell 的特性,如管道等
ansible all -m shell -a "echo "deepintest:deepintest" | chpasswd"
chdir:在运行命令之前,切换到此目录。
ansible web -m shell -a "chdir=/tmp pwd"
executable:更改用于执行命令的shell(bash,sh)。应该是可执行文件的绝对路径。
4、script 模块
将deepin1 上的脚本在deepin2、deepin3 和deepin4 上运行
vim /tmp/deepinscript.sh
#!/bin/bash
touch /tmp/deepinscript
useradd deepinscript
echo "deepinscript:deepinscript" | chpasswd
在所有主机上批量执行deepinscript 脚本
ansible all -m script -a "/tmp/deepinscript.sh"
5、copy 模块
ansible all -m copy -a "src=/etc/fstab dest=/tmp/ owner=deepintest group=root mode=0600"
ansible all -m copy -a "src=/var/log/apt/ dest=/tmp/ owner=deepintest group=root mode=0750"
#src 主控端文件位置,dest 被控端目标位置,owner 文件复制过去后的所有者,group 文件复制过去后的所属组,mode 文件的权限设定
6、user 模块
ansible all -m user -a "name=deepinuser state=present groups=deepintest uid=2000 createhome=yes home=/tmp/deepinuser password=deepinuser shell=/bin/bash comment='The user for deepin' append=yes"
ansible all -m user -a "name=deepinuser state=absent remove=yes"
name:用户名
password:为用户设置登陆密码,此密码是明文密码加密后的密码
update_password:always/on_create
always:只有当密码不相同时才会更新密码(默认)
on_create:只为新用户设置密码
shell:用户的shell 设定
groups:用户组设定
home:指定用户的家目录
state:present/absent
append:yes/no
yes:增量添加group
no:全量变更group,只设置groups 指定的group 组(默认)
remove:配合state=absent 使用,删除用户的家目录->remove=yes
expires:设置用户的过期时间,值是一个时间戳
7、file 模块
ansible all -m file -a "src=/etc/fstab dest=/tmp/deepinfstab state=link"
ansible all -m file -a "path=/tmp/deepinfile state=touch owner=deepintest group=root mode=0600"
force:需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况
下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个
选项:yes|no
group:定义文件/目录的属组
mode:定义文件/目录的权限
owner:定义文件/目录的属主
path:必选项,定义文件/目录的路径
recurse:递归设置文件的属性,只对目录有效
src:被链接的源文件路径,只应用于state=link 的情况
dest:被链接到的路径,只应用于state=link 的情况
state:
directory:如果目录不存在,就创建目录
file:即使文件不存在,也不会被创建
link:创建软链接
hard:创建硬链接
touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
absent:删除目录、文件或者取消链接文件
8、mount 模块
ansible all -m mount -a "src=/dev/sr0 path=/mnt/cdrom fstype=iso9660 opts=ro state=mounted"
ansible all -m mount -a "src=/dev/sr0 path=/mnt/cdrom fstype=iso9660 opts=ro state=absent"
fstype:必选项,挂载文件的类型
path:必选项,挂载点
opts:传递给mount 命令的参数
src:必选项,要挂载的文件
state:
present 添加到fstab 中,不挂载
absent 删除fstab,并卸载资源
mounted 添加到fstab 中,并自动挂载
umounted 不删除fstab 信息,只卸载资源
9、service 模块
ansible all -m service -a "name=sshd state=started enabled=yes"
arguments:给命令行提供一些选项
enabled:是否开机启动yes|no, 要求状态(state)和启用(enabled)中至少有一个。
name:必选项,服务名称
runlevel:运行级别
sleep:如果执行了restarted,在则stop 和start 之间沉睡几秒钟
state :对当前服务执行启动,停止、重启、重新加载等操作
(started,stopped,restarted,reloaded)
10、setup 模块
ansible all -m setup #查看所有主机信息
ansible all -m setup -a "filter=ansible_hostname" #查看主机名
ansible all -m setup -a "filter=ansible_kernel" #查看内核信息
ansible all -m setup -a "filter=ansible_memory_mb" #查看内存信息
ansible all -m setup -a "filter=ansible_default_ipv4" #查看网卡ipv4 信息
ansible all -m setup -a "filter=*user*" #查看user 相关信息
11、debug 模块
ansible all -m debug -a "msg=hahahahahaha"
msg:调试输出的消息
var:将某个任务执行的输出作为变量传递给debug 模块,debug 会直接将其打印输出
verbosity:debug 的级别(默认是0 级,全部显示)
12、cron 计划任务模块
ansible all -m cron -a "name='deepincron' minute='30' hour='12' job='touch /tmp/deepincron' user=root"
ansible all -m cron -a 'minute="*/1" job="/usr/bin/date >> /date.txt" name="date job"'
minute= /hour= /day= /month= /weekday= 某个值不写,默认就是*
name:必选项,任务描述信息
job:执行的任务,要加引号
state:present(创建)/absent(删除)
13、get_url 模块
ansible all -m get_url -a 'url=http://192.168.200.10/favicon.ico dest=/tmp' #配置好url
sha256sum:下载完成后进行sha256 check;
timeout:下载超时时间,默认10s
url:下载的URL
url_password、url_username:主要用于需要用户名密码进行验证的情况
dest:将文件下载到哪里的绝对路径。如果dest 是目录,则使用服务器提供的文件名,
或者如果没有提供,将使用远程服务器上的URL 的基本名称。
headers:以格式“key:value,key:value”为请求添加自定义HTTP 标头。
14、synchronize 模块
用于在主机间同步数据
delete=yes 使两边的内容一样(即以推送方为主)
compress=yes 开启压缩,默认为开启
–exclude=.Git 忽略同步.git 结尾的文件
mode=pull 更改推送模式为拉取模式
示例:
在deepin1 上
mkdir /deepin
touch /deepin/file{1..99}
ansible all -m synchronize -a 'src=/deepin dest=/tmp/ compress=yes'
在deepin2 上
ll /tmp/deepin
在deepin1 上
mkdir /deepintest
ansible node1 -m synchronize -a ' mode=pull src=/tmp/deepin dest=/deepintest'
ll /deepintest/deepin
playbook 内容介绍和语法格式
playbook 模式(剧本模式)
Playbook 是Ansible 提供的最强大的任务执行方法。与ad-hoc 命令不同,Playbooks 配置在文件中,可以重用和共享给其他人。
playbooks 是以YAML 标记语言来定义的。每个playbook 由一个或多个play 组成。play
的目标是将一组主机映射到任务中去。每个play 包含一个或多个任务(task),这些任务每次执一次。
从根本上来讲,所谓task 无非是调用ansible 的一个module。将多个play 组织在一个
playbook 中,即可以让它们联同起来按事先编排的机制同唱一台大戏。
playbooks 的组成部分
Target section: 定义要运行playbook 的远程主机组
hosts: hosts 用于指定要执行指定任务的主机,其可以是一个或多个由冒号分隔主机组
user: 指定远程主机上的执行任务的用户,还可以指定sudo 用户等
Variable section: 定义playbook 运行时使用的变量
Task section: 定义要在远程主机上运行的任务列表
name: 每个任务都有name,建议描述任务执行步骤,未通过name 会用执行结果作为name
'module:options': 调用的module 和传入的参数args
Handler section: 定义task 完成后需要调用的任务
notify: 在Task Section 在每个play 的最后触发,调用在hendler 中定义的操作
handler: 也是task 的列表
示例:
---
-- hosts: master
user: root
vars:
- motd_warning: 'WARNING: Use by master ONLY'
tasks:
- name: setup a MOTD
copy: dest=/etc/motd content="{{ motd_warning }}"
notify: say something
handlers:
- name: say something
command: echo "copy OK"
yaml 语法格式
同级别数据元素必须有相同的缩进
子元素必须比父元素缩进更多
推荐缩进两个空格
每个文件首行是“---”,最后一行是“...”
playbook 是play 的列表,列表项表示为“-”
paly 本身是key:val 对的字典
帮助查看
ansible-doc apt
执行playbook
ansible-playbook --syntax-check **.yml //检测语法格式
ansible-playbook **.yml //执行playbook
Ansible 变量简介
Ansible 支持利用变量来存储值,并在Ansible 项目的所有文件中重复使用这些值。这可化项目的创建和维护,并减少错误的数量。
通过变量,可以轻松地在Ansible 项目中管理给定环境的动态值。例如:
要创建的用户
要安装的软件包
要重新启动的服务
要删除的文件
要从互联网检索的存档
命名变量
变量的名称必须以字母开头,并且只能包含字母、数字和下划线。
示例:web server:错误的变量名web_server:正确的变量名
定义变量
可以在Ansible 项目中的多个位置定义变量。这些变量大致可简化为三个范围级别:
全局范围:从命令行或Ansible 配置设置的变量
play 范围:在play 和相关结构中设置的变量
主机范围:由清单、事实收集或注册的任务,在主机组和个别主机上设置的变量
优先级:
命令行变量>>playbook 变量>>主机清单变量
ansible 变量优先级(由高到低)
1. ansible-playbook 命令中的变量,ansible-playbook -e var=value
2. task 变量
3. block 变量
4. role 中定义的变量和include 变量
5. set_fact
6. registered 变量
7. vars_files
8. var_prompt
9. play 变量
10. host facts
11. playbook 中设置的host_vars
12. playbook 中设置的group_vars
13. inventory 中设置的host_vars
14. inventory 中设置的group_vars
15. inventory 变量
16. role 中defaults/main.yml 中定义的变量
playbook 中的变量
变量在Ansible Playbook 中发挥着重要作用,因为它们可以简化playbook 中变量数据的管理。
在playbook 中定义变量
Playbook 变量可以通过多种方式定义。一种常见的方式是将变量放在playbook 开头的vars块中:
---
- hosts: 192.168.86.132
vars:
package_name: httpd
tasks:
- name: install httpd
yum:
name: '{{ package_name }}' #变量一定要写用引号
state: present
也可以在外部文件中定义playbook 变量。此时不使用playbook 中的vars 块,可以改为使用
vars_files 指令,后面跟上相对于playbook 位置的外部变量文件名称列表:
[root@ansible playbook]# mkdir vars && cd vars && echo "package_name: httpd" > httpd.yml
[root@ansible playbook]# vim test.yml
---
- hosts: 192.168.86.132
vars_files:
- vars/httpd.yml
tasks:
- name: install httpd
yum:
name: '{{ package_name }}'
state: present
注:
声明了变量后,可以在任务中使用这些变量。若要引用变量,可以将变量名放在双大括号内。在任务执行时,Ansible 会将变量替换为其值。需要注意的是:当变量用作开始一个值的第一元素时,必须使用引号。这可以防止Ansible 将变量引用视为YAML 字典的开头。
在inventory 主机列表中定义主机变量和组变量:
主机变量: 可以在inventory 中定义主机时为其添加主机变量以便于在playbook 中使用。
例如:
[webservers]
www1.com http_port=80 maxRequestsPerChild=808
www2.com http_port=8080 maxRequestsPerChild=909
组变量: 主机组变量针对组内所有的主机都生效。
示例:定义了2 个主机组变量ntp_server 和nfs_server
[webservers]
www1.com
www2.com
[webservers:vars]
ntp_server=ntp.com
nfs_server=nfs.com
测试:
vim variable.yaml
---
- hosts: all
gather_facts: False
tasks:
- name: diplay Host Variable from hostfile
debug: msg="The {{ inventory_hostname }} Value is {{ key }}"
执行:
ansible-playbook variable.yaml
注意:如果主机同时定义了主机变量和主机组变量,名字相同时,主机变量生效,主机组变量不生效;名字不同时,都可以调用。
从命令行覆盖变量
清单变量可被playbook 中设置的变量覆盖,这两种变量又可通过在命令行中传递参数到ansible 或ansible-playbook 命令来覆盖。在命令行上设置的变量称为额外变量,使用**-e**选择来指定额外变量
[root@ansible httpd]# ansible 192.168.86.132 -i inventory -e "ansible_passwrod=123456" -m ping
//也可以把变量写在一个文件中用-e 选项来指定
[root@ansible httpd]# vim xx
ansible_password: 123456
[root@ansible httpd]# ansible 192.168.86.132 -i inventory -e @xx -m ping
示例:使用已注册变量捕获命令输出
可以使用register 语句捕获命令输出。输出保存在一个临时变量中,然后在playbook 中可用于调试用途或者达成其他目的
---
- name:
hosts: 192.168.86.132
tasks:
- name:
user:
name: cvg
state: present
register: useradd_result
- debug: var=useradd_result //debug 模块用于将install_result 注册变量的值转储到终端。
[root@ansible ~]# ansible-playbook -C test.yml
管理机密
Ansible Vault
Ansible 可能需要访问密码或API 密钥等敏感数据,以便能配置受管主机,但是这些敏感数据是任何有权限访问Ansible 文件的用户都能查看,这样是不安全。
Ansible 提供的Ansible Vault 可以加密和解密任何由Ansible 使用的结构化数据文件。
创建加密文件
使用ansible-vault create filename 命令创建加密文件,然后输入的vault 密码
[root@ansible group_vars]# ansible-vault create webserve
New Vault password:
Confirm New Vault password:
还可以用vault 密码文件来存储vault 密码,而不是通过标准输入途径输入vault 密码。
这样做需要使用文件权限和其他方式来严密保护该文件。
[root@ansible group_vars]# vim vault_password
123456
[root@ansible group_vars]# ansible-vault create --vault-password-file=vault_password webserve
查看加密的文件
使用ansible-vault view filename 命令查看Ansible Vault 加密的文件
[root@ansible group_vars]# ansible-vault view webserve
Vault password:
ansible_password: 123456
编辑现有的加密文件
使用ansible-vault edit filename 命令。此命令将文件解密为一个临时文件,并允许编辑。保存时,它将复制其内容并删除临时文件。
[root@ansible group_vars]# ansible-vault edit webserve
Vault password:
注意:不要用vi/vim 直接编辑加密文件,这样会导致加密文件无法打开
加密现有的文件
使用ansible-vault encrypt filename 命令。此命令可取多个想要加密文件的名称作为参数。
//创建加密文件
[root@ansible group_vars]# vim webserve
ansible_password: 123456
[root@ansible group_vars]# ansible-vault encrypt webserve
New Vault password:
Confirm New Vault password:
Encryption successful
解密现有的文件
使用ansible-vault decrypt filename 命令永久解密。在解密单个文件时,可使用**_output**
选项以其他名称保存解密的文件。
[root@ansible group_vars]# ansible-vault decrypt webserve
Vault password:
Decryption successful
[root@ansible group_vars]# cat webserve
ansible_password: redhat
更改加密的密码
使用ansible-vault rekey filename 命令更改加密文件的密码。此命令可一次性更新多个数据文件的密钥。它将提示提供原始密码和新密码。
[root@ansible group_vars]# ansible-vault rekey webserve
Vault password: //当前密码
New Vault password: //输入要更改的新密码
Confirm New Vault password: //再次输入要更改的新密码
Rekey successful
在使用vault 密码文件时,请使用–new-vault-password-file 选项
ansible-vault rekey --new-vault-password-file=NEW_VAULT_PASSWORD_FILE webserve
playbook 和ansible vault
要运行可访问通过Ansible Vault 加密的文件的playbook,需要向ansible-playbook 命令提供加密密码。如果不提供密码,playbook 将返回错误
[root@ansible httpd]# ansible all -i inventory -m ping
ERROR! Attempting to decrypt but no vault secrets found
要为playbook 提供vault 密码,可使用–vault-id @prompt 选项。
[root@ansible httpd]# ansible 192.168.86.132 -i inventory --vault-id @prompt -m ping
Vault password (default):
192.168.86.132 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
也可使用–vault-password-file 选项指定以纯文本存储加密密码的文件。密码应当在该文件中存储为一行字符串。由于该文件包含敏感的纯文本密码,因此务必要通过文件权限和其他安全措施对其加以保护。
ansible all --vault-password-file=vault-pw-file webserve
也可以使用ANSIBLE_VAULT_PASSWORD_FILE 环境变量,指定密码文件的默认位置。
从Ansible2.4 开始,可以通过ansible-playbook 使用多个Ansible Vault 密码。要使用多
个密码,需要将多个**–vault-id 或–vault-password-file 选项传递给ansible-playbook**命令。
ansible all --vault-id one@prompt --vault-id two@prompt webserve
//这种用法一般不会使用
注意:@prompt 前面的vaultIDone 和two 可以是任何字符,甚至可以完全省略它们。不过,如果在使用ansible-vault 命令加密文件时使用–vault-id id 选项,则在运行ansible-playbook时,将最先尝试匹配ID 的密码。如果不匹配,将会尝试用户提供的其他密码。没有ID 的vaultID@prompt 实际上是default@prompt 的简写,这意味着提示输入vaultIDdefault 的密码。变量文件管理的推荐做法
设置Ansible 项目,简化管理,使敏感变量和其他变量保存在相互独立的文件中。然后,包含敏感变量的文件可通过ansible-vault 命令进行保护。
管理组变量和主机变量的首选方式是在playbook 级别上创建目录。group_vars 目录通常包含名称与它们所应用的主机组匹配的变量文件。host_vars 目录通常包含名称与它们所应用的受管主机名称匹配的变量文件。
除了使用group_vars 和host_vars 中的文件外,也可对每一主机组或受管主机使用目录。这些目录可包含多个变量文件,它们都由该主机组或受管主机使用
[root@ansible httpd]# tree .
.
├──files
├──group_vars
│└──webserve
│├──vars //不需要加密的变量
│└──vault //需要加密的变量,用ansible-vault 进行加密
├──host_vars
├──inventory
└──playbook.yml
描述Ansible 事实
setup 模块用来收集事实,每个play 在执行第一个任务之前会先自动运行setup 模块来收集事实。
Ansible 事实是Ansible 在受管主机上自动检测到的变量。事实中包含有与主机相关的信息,可以像play 中的常规变量、条件、循环或依赖于从受管主机收集的值的任何其他语句那样使用。
收集的事实可能包括:
主机名称
内核版本
网络接口
IP 地址
操作系统版本
各种环境变量
CPU 数量
提供的或可用的内存
可用磁盘空间
借助事实,可以方便地检索受管主机的状态,并根据该状态确定要执行的操作。
可以根据含有受管主机当前内核版本的事实运行条件任务,以此来重启服务器
可以根据通过事实报告的可用内存来自定义MySQL 配置文件
可以根据事实的值设置配置文件中使用的IPv4 地址
查看为受管主机收集的事实的一种方式是,运行一个收集事实并使用debug 模块显示
ansible_facts 变量值的简短playbook。
---
- name: fact
hosts: 192.168.86.132
tasks:
- name: fact
debug:
var: ansible_facts
//Playbook 以JSON(字典)格式显示ansible_facts 变量的内容。
[root@ansible ~]# ansible-playbook play.yml
Ansible 事实的变量名
事实变量
短主机名ansible_facts[‘hostname’]
完全限定域名ansible_facts[‘fqdn’]
IPv4 地址ansible_facts[ ‘default_ipv4’] [‘address’]
/dev/vda1 磁盘分区的大小ansible_facts[‘devices’] [‘vda’] [‘partitions’] [‘vda1’]
‘size’]
DNS 服务器列表ansible_facts[‘dns’] [‘nameservers’]
当前运行的内核版本ansible_facts[‘kernel’]
示例:
取得主机名
---
- name: fact
hosts: 192.168.86.132
tasks:
- name: fact
debug:
var: ansible_facts['hostname']
[root@ansible ~]# ansible-playbook play.yml
//取出sda 下的sda1 的分区大小
---
- name: fact
hosts: 192.168.86.132
tasks:
- name: fact
debug:
var: ansible_facts['devices']['sda']['partitions']['sda1']['size']
[root@ansible ~]# ansible-playbook play.yml
如果变量的值为散列/字典类型,则可使用下面这种语法来获取其值
ansible_facts[‘dns’] [‘nameservers’]也可以写为ansible_facts.dns.nameservers,不推荐使用这种方法
//取得DNS server 变量
---
- name: fact
hosts: 192.168.86.132
tasks:
- name: fact
debug:
var: ansible_facts.dns.nameservers
[root@ansible ~]# ansible-playbook play.yml
在playbook 中使用事实时,Ansible 将事实的变量名动态替换为对应的值
//取得机器名和对应的ip
---
- hosts: all
tasks:
- name: Prints various Ansible facts
debug:
msg: >
The machine and ipv4 address of {{ ansible_facts['machine'] }} is {{ ansible_facts.default_ipv4.address }}
[root@ansible ~]# ansible-playbook play.yml
Ansible 事实作为变量注入
在Ansible2.5 之前,事实是作为前缀为字符串**ansible_**的单个变量注入,而不是作为
ansible_facts 变量的一部分注入。例如,ansible_facts[ ‘distribution ’] 事实会被称为
ansible_distribution。
Ansible 事实名称对比
目前,Ansible 同时识别新的事实命名系统(使用ansible_facts)和旧的2.5 前“作为单独变量注入的事实”命名系统。
如果将Ansible 配置文件的**[default]部分中inject_facts_as_vars 参数设置为False**,可关闭旧命名系统。默认设置目前为True。
在未来的版本中旧的写法可能会默认更改为False,所有建议用新的形式
[root@ansible ~]# vim /etc/ansible/ansible.cfg
...
# inject_facts_as_vars = True
...
关闭事实收集
关闭收集事实的原因可能有:
不准备使用任何事实
希望加快play 速度
希望减小play 在受管主机上造成的负载
受管主机因为某种原因无法运行setup 模块(如:受管主机可能是路由器、交换机等设
备)
需要安装一些必备软件后再收集事实
将gather_facts 关键字设置为no 可以禁用setup
---
- hosts: all
gather_facts: no
tasks:
- name: Prints various Ansible facts
debug:
msg: >
The machine and ipv4 address of {{ ansible_facts['machine '] }}
is {{ ansible_facts.default_ipv4.address }}
[root@ansible ~]# ansible-playbook play.yml
即使play 设置了gather_facts: no,也可以随时通过运行使用setup 模块的任务来手动收集事实
---
- hosts: all
gather_facts: no
tasks:
- name: start setup
setup:
- name: Prints various Ansible facts
debug:
msg: >
The machine and ipv4 address of {{ ansible_facts['machine'] }} is {{ ansible_facts.default_ipv4.address }}
[root@ansible ~]# ansible-playbook play.yml
创建自定义事实
除了使用系统捕获的事实外,我们还可以自定义事实,并将其本地存储在每个受管主机
上。
这些事实整合到setup 模块在受管主机上运行时收集的标准事实列表中。
它们让受管主机能够向Ansible 提供任意变量,以用于调整play 的行为\
自定义事实可以在静态文件中定义,格式可为INI 文件或采用JSON。它们也可以是生
成JSON 输出的可执行脚本,如同动态清单脚本一样
默认情况下,setup 模块从各受管主机的**/etc/ansible/facts.d 目录下的文件和脚本中加载自定义事实。各个文件或脚本的名称必须以.fact**结尾才能被使用。
动态自定义事实脚本必须输出JSON 格式的事实,而且必须是可执行文件。
使用INI 格式编写自定义事实,INI 格式的自定义事实文件包含由一个部分定义的顶层值,后跟用于待定义的事实的键值对
[webserves]
web1 = 192.168.11.110
web2 = 192.168.66.66
使用JSON 格式编写自定义事实,JSON 数据可以存储在静态文本文件中,或者通过可执行脚本输出到标准输出
"webserves": {
"web1": "192.168.11.110",
"web2": "192.168.66.66"
}
自定义事实文件不能采用playbook 那样的YAML 格式。JSON 格式是最为接近的等效格式
自定义事实由setup 模块存储在ansible_facts.ansible_local 变量中。事实按照定义它们的文件的名称来整理
---
- hosts: all
tasks:
- name: Prints various Ansible facts
debug:
var: ansible_facts['ansible_local']['cwt']['webserves']['web1']
[root@ansible ~]# ansible-playbook play.yml
playbook 剧本的编写实例精讲
实例: 包含多个play 的playbook
vim tow.yml
---
- name: Execute NODE1 #一个play
hosts: node1 #执行的主机组名
tasks: #任务列表
- name: install http #描述任务
apt: #模块名
name: apache2 #安装的包名
state: present #允许安装
- name: Start service httpd, if not started #描述任务
service: #模块名
name: apache2 #启动的服务名
state: started #启动的服务
- name: Execute NODE2
hosts:
- node2
tasks:
- name: install gcc
apt:
name: gcc
state: present
执行:
ansible-playbook --syntax-check tow.yml #检查yml 语法
ansible all -m shell -a "apt update" #执行更新apt 源
ansible-playbook tow.yml #运维playbook 的yml 文件
curl 192.168.200.11 //验证可以访问到#验证
实例:循环
同时启动ssh 和apache
vim Circulates.yml
---
- name: xhlx
hosts: node1
tasks:
- name: sshd and apache2 are running
service:
name: "{{ item }}"
state: started
loop:
- sshd
- apache2
ansible-playbook --syntax-check Circulates.yml
ansible-playbook Circulates.yml
实例:变量及条件判断
变量my_service 已定义,如果定义了,安装相应的软件包,没定义则跳过、也不会报错
vim tjpd.yml
---
- name: panduan
hosts: all
vars: #定义变量名
my_service: apache2
tasks:
- name: "{{ my_service }} package is installed"
apt:
name: "{{ my_service }}"
when: my_service is defined
判断路径:
- hosts: all
remote_user: root
gather_facts: no
vars:
testpath1: "/etc"
testpath2: "/haha"
tasks:
- debug:
msg: "directory"
when: testpath1 is directory
- debug:
msg: "file"
when: testpath2 is file