ansible会在同一时间管理你的很多主机,使用一个列表或者组作为一个目录。一旦你的Inventory定义好了,你就可以使用一些pattern去操作你列表里的主机。
默认的设备目录文件是在/etc/ansible/hosts
。你也可以使用选项-i <path>
指定一个目录文件。你也可以同时使用多个目录文件,更或者也可以从一个动态的或者云资源更或者不同格式的目录(YAML,ini,etc)。
inventory文件可以是一种或者多种格式,取决于你的目录插件。最普遍的格式为INI和YAML。一个基础的INI文件etc/ansible/hosts
应该向下面的例子这样:
mail.example.com
[webservers]
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com
中括号里的标题是组名称,用于分类主机和确定你在何时和控制主机的目的。
这是YAML格式的inventory文件:
all:
hosts:
mail.example.com:
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
有两个默认组:all
和ungroup
。all
里面包含所有的主机。ungroup
里面包含了所有没有在组里的主机。所有的主机会至少属于2个组(all
和group
或者其他的组)。因为all
和ungroup
是一直存在的,所以他们也不必要以组名的形式存在于Inventory中。
你可以把一个主机归为多个组。例如生产上的一台web服务器在DC A里,它既属于[prod] [DC A]和[webservers]里。你可以按如下步骤创建组:
hosts:
mail.example.com:
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
east:
hosts:
foo.example.com:
one.example.com:
two.example.com:
west:
hosts:
bar.example.com:
three.example.com:
prod:
hosts:
foo.example.com:
one.example.com:
two.example.com:
test:
hosts:
bar.example.com:
three.example.com:
可以看到one.example.com
同时存在于dbservers
, east
, 和prod
组里.
你也可以使用嵌套的组来简化生产主机和测试主机:
all:
hosts:
mail.example.com:
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
east:
hosts:
foo.example.com:
one.example.com:
two.example.com:
west:
hosts:
bar.example.com:
three.example.com:
prod:
children:
east:
test:
children:
如果你有大量命名类似的主机,你可以使用一个范围参数来批量添加,而不用一个一个地单独添加。
INI格式:
[webservers]
www[01:50].example.com
YAML格式:
webservers:
hosts:
www[01:50].example.com:
对于数字模式,前面的0可以包含也可以不包含.你也可以定义一个字母范围:
[databases]
db-[a:f].example.com
你可以为一个主机或者主机组存储变量值。刚开始,你可以直接在主Inventory文件里添加主机或者组变量。当你添加越来越多的主机在你的Inventory里时候,你可能就想用单独的文件来存储主机和主机组的变量。
你可以轻松地给单一的主机配置变量,然后再playbook中使用它。在INI格式下:
[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909
YAML格式:
atlanta:
host1:
http_port: 80
maxRequestsPerChild: 808
host2:
http_port: 303
maxRequestsPerChild: 909
比如非标准SSH端口可以很好用于主机变量中。你可以把端口添加在主机名冒号的后面:
badwolf.example.com:5309
连接协议也可以在配置在主机变量里:
[targets]
localhost ansible_connection=local
other1.example.com ansible_connection=ssh ansible_user=myuser
other2.example.com ansible_connection=ssh ansible_user=myotheruser
注:如果使用非标准SSH端口的话,openssh连接会找到并使用它,但是paramiko连接方式不会。
在inventory里定义aliases:
INI:
jumper ansible_port=5555 ansible_host=192.0.2.50
YAML:
hosts:
jumper:
ansible_port: 5555
ansible_host: 192.0.2.50
在上面的例子中,ansible会连接主机别名“jumper” 的5555端口。
注:INI使用key=value
格式,他的值取决于在哪里声明他。
key=value
的值。所以需要一个方法去分辨空格是一个分隔符还是属于定义的值的一部分。:vars
中时候,INI的值会被解释成字符。比如var=FALSE
会被创建为一个字符‘FALSE’。与主机行不同,:vars
部分值接受一个单独的条目,所以所有在=
号后面的都是该条目的值。如果一个组的主机共享变量,你可以把变量一次性应用到组内。
INI格式:
[atlanta]
host1
host2
[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
In YAML:
atlanta:
hosts:
host1:
host2:
vars:
ntp_server: ntp.atlanta.example.com
proxy: proxy.atlanta.example.com
组变量是比较方便的方法能批量应用变量。但是在执行命令之前,ansible会应用变量到主机级别。如果主机属于多个组,那么ansible会从所有的组中读取值。如果在不同的组里给相同的变量分配了不同的值,ansible会根据内部规则选择哪些值进行合并。
使用:children
后缀在INI或者children:
在YMAL中应用:vars
或vars:
的组变量
INI格式:
[atlanta]
host1
host2
[raleigh]
host2
host3
[southeast:children]
atlanta
raleigh
[southeast:vars]
some_server=foo.southeast.example.com
halon_system_timeout=30
self_destruct_countdown=60
escape_pods=2
[usa:children]
southeast
northeast
southwest
northwest
在YAML中:
all:
children:
usa:
children:
southeast:
children:
atlanta:
hosts:
host1:
host2:
raleigh:
hosts:
host2:
host3:
vars:
some_server: foo.southeast.example.com
halon_system_timeout: 30
self_destruct_countdown: 60
escape_pods: 2
northeast:
northwest:
southwest:
如果需要存储列表或者哈希数据,再或者需要单独存放主机和组变量,需要查询组织主机和组变量环节。
子组有一些特性需要知悉:Child groups have a couple of properties to note:
虽然你可以存储变量到主inventory文件里,但是把主机和组变量分别存储到分开的文件中可以更方便我们的管理。主机和组变量文件必须是YAML格式。有效的文件扩展名包括‘.yml’, ‘.yaml’, ‘.json’或者无扩展名。
ansible会通过寻找相关的Inventory文件或者Playbook路径来加载主机和组变量。如果你的inventory文件在/etc/ansible/hosts
目录下,并且包含属于两个组‘raleigh’ 和‘webservers’的主机‘foosball’,那么这个主机会使用如下路径的YAML变量文件。
/etc/ansible/group_vars/raleigh # 扩展名可以是‘.yml‘, ‘.yaml‘, 或者‘.json‘
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball
例如,如果你以DC来分类你的主机,而且每个DC有自己的NTP服务或者DB服务器,那么你可以创建一个文件名为/etc/ansible/group_vars/raleigh
来存储你raleigh组的变量
---
ntp_server: acme.example.org
database_server: storage.example.org
你可以以主机名字或者组名字来创建目录。ansible会按照字典顺序来读取全部的目录。
一个名为‘raleigh’组的例子:
/etc/ansible/group_vars/raleigh/db_settings
/etc/ansible/group_vars/raleigh/cluster_settings
所有在‘raleigh’组的主机将可使用定义在这些文件中的变量。如果你变量文件很大的话,这个方式会帮助你整理变量文件以及在ansible加密某些组变量。
你也可以在playbook目录里添加group_vars/
和host_vars/
目录。ansible-playbook
命令会默认在目前工作目录里寻找这些目录。但是其他的ansible命令(比如ansible
,ansible-console
等)只会在inventory目录下寻找group_vars/
和host_vars/
目录。如果你想用其他的ansible命令从其他目录里加载组和主机变量,需要添加--playbook-dir
选项指定目录。如果你从playbook目录和inventory一起加载inventory文件,那Playbook目录中的变量会覆盖掉Inventory目录的变量。
把你的inventory文件和变量放在git上可以跟踪你的inventory和主机变量的改变过程。
默认情况下,在playbook执行前会将某主机的变量进行合并。这使ansible只关注于主机和任务,所以组的概念只是被限制于目录的主机匹配中。默认情况下,Ansible会按照优先级去覆盖那些为组或者主机定义的变量。从低到高的优先级顺序是:
默认情况下ansible会按照字母顺序合并相同级别的组,后加载的组会覆盖前面的组。比如 B 开头命名的组变量会覆盖 A 开头中同样匹配到的组变量。
你可以通过修改组变量中ansible_group_priority
选项来改变合并相同级别组变量时的优先级顺序。数字越大,优先级越高,如果不修改则优先级默认为1.
a_group:
testvar: a
ansible_group_priority: 10
b_group:
testvar: b
在这个例子中,如果这两个组有相同的优先级,那么变量会是testvar == b
。但是如果给a_group
一个更高的优先级,那么结果就会是testvar == a
.
注:ansible_group_priority
只能在inventory文件中设置,不能在group_vars/
设置,因为这个变量在加载group_vars
的时候被用到。
你可以通过使用命令行或者配置ANSIBLE_INVENTORY
来同时使用多inventory源(目录、动态目录脚本或者inventroy插件支持的其他文件)。当你想同时分别配置生产或者测试环境的时候,这个功能会很有用处。
使用命令行选中两个inventory。
ansible-playbook get_logs.yml -i staging -i production
此时要注意变量冲突的问题,如果冲突了的话,会按照变量合并的规则去处理。合并的顺序是按照Inventory源的参数顺序控制。如果[all:vars]
在staging inventory里定义myvar = 1
,但是production inventory定义myvar = 2
,那么playbook会使用myvar = 2
的值。如果上面的例子中使用的参数是-i production -i staging
,那么结果将会相反。
也可以只创建一个inventory目录,然后把多个inventory源或者其他类型的文件放在里面。这对于管理动态和静态主机来说很方便。下面这个invetory就包含了inventory插件源,动态inventory脚本和一个静态主机文件:
inventory/
openstack.yml # 配置inventory插件获取Openstack Cloud主机
dynamic-inventory.py # 使用动态inventory脚本添加主机
static-inventory # 添加静态的主机和组
group_vars/
all.yml # 分配变量到所有主机
你可以这样直接调用这个inventory目录:
ansible-playbook example.yml -i inventory
因为这些inventory的合并规则是遵循文件名字的字母表顺序,所以如果有变量冲突的话,可以给文件添加一个前缀来定义优先级:
inventory/
01-openstack.yml
02-dynamic-inventory.py
03-static-inventory
group_vars/
all.yml
如果01-openstack.yml
定义myvar = 1
,02-dynamic-inventory.py
定义myvar = 2
,03-static-inventory
定义myvar = 3
,那playbook会采用myvar = 3
。
以下是ansible控制主机涉及到的一些重要参数。
主机连接:
注:在使用默认ssh连接插件的时候,ansible不会释放一个通道去允许用户和SSH进程间手动接受密码或者解密秘钥。推荐使用ssh代理的方式。
ansible_connection
: 连接到主机的方式,可以是ansible连接插件的名字。SSH协议连接类型有:smart,ssh 或者paramiko。默认是smart。
一些通用的参数:
ansible_host
: 要连接的主机名称
ansible_port
: 连接端口
ansible_user
: 连接的用户名
ansible_password
: 主机的用户密码(不要使用明文密码,应该使用vault功能进行加密)
针对于SSH的参数:
ansible_ssh_private_key_file
: SSH使用的私钥,如果不想使用ssh代理的话,可以指定多个主机的私钥
ansible_ssh_common_args
: 参数会添加到sftp,scp,ssh的默认命令行中。通常用来配置ProxyCommand 。
ansible_sftp_extra_args
: 参数会添加到sftp的默认命令行中
ansible_scp_extra_args
: 参数会添加到scp的默认命令行中
ansible_ssh_extra_args
: 参数会添加到ssh的默认命令行中
ansible_ssh_pipelining
: 决定是否使用SSH pipelining,这个可以覆盖掉ansible.cfg
中的pipelining
参数
权限升级:
ansible_become
: 相当于ansible_sudo 和 ansible_su,允许强制提升用户权限。
ansible_become_method
: 设置权限升级的方式
ansible_become_user
:相当于ansible_sudo_user
或者ansible_su_user
, 允许某用户权限升级
ansible_become_password
: 允许你设置权限升级的密码(不要直接使用明文的方式)
ansible_become_exe
: 允许设置升级权限的可执行文件
ansible_become_flags
: 允许为权限升级方式设置标志位,也可以在ansible.cfg里全局设置
远程主机环境参数:
ansible_shell_type
: 远程主机的shell类型。一般不用设置。默认为sh
。
ansible_python_interpreter
:远程主机的Python路径
ansible_*_interpreter
:支持ruby, perl 。
一个Ansible-INI主机文件示例:
some_host ansible_port=2222 ansible_user=manager
aws_host ansible_ssh_private_key_file=/home/example/.ssh/aws.pem
freebsd_host ansible_python_interpreter=/usr/local/bin/python
ruby_module_host ansible_ruby_interpreter=/usr/bin/ruby.1.9.3
ansible并非仅使用ssh的连接类型。根据ansible_connection=<connector>
参数的设置,连接类型可以被更改。比如:
local
: 这个参数意味着你你的playbook将部署再本机上。
docker
: 这个参数是将playbook直接用docker client部署到docker容器里。
这个连接类型将会使用以下参数。
ansible_host
: 连接的Docker容器名
ansible_user
: 容器中的操作用户名,这个用户必须存在于容器内。
ansible_become
: 如果置位true,那就会使用become_user
在容器内进行操作
ansible_docker_extra_args
: 可以是一个包含Docker其他参数的字符串,单并不是特定于命令的。此参数主要用于配置要使用的远程Docker守护程序。
下面是个docker部署示例:
- name: create jenkins container
docker_container:
docker_host: myserver.net:4243
name: my_jenkins
image: jenkins
- name: add container to inventory
add_host:
name: my_jenkins
ansible_connection: docker
ansible_docker_extra_args: "--tlsverify --tlscacert=/path/to/ca.pem --tlscert=/path/to/client-cert.pem --tlskey=/path/to/client-key.pem -H=tcp://myserver.net:4243"
ansible_user: jenkins
changed_when: false
- name: create directory for ssh keys
delegate_to: my_jenkins
file:
path: "/var/jenkins_home/.ssh/jupiter"
state: directory
原文:https://www.cnblogs.com/felix-zong/p/14620249.html