设为首页 收藏本站
查看: 1047|回复: 0

[经验分享] ansible 番外篇之变量与fact

[复制链接]

尚未签到

发表于 2018-1-2 23:17:03 | 显示全部楼层 |阅读模式
变量与 fact
  在 Ansible 中, 变量的作用域是按照主机划分的, 只有针对特定主机讨论变量的值才有意义.

1. 变量

1.1. 定义变量
  vars : 定义变量的列表或字典
  
vars_file : 指定 定义变量的文件列表
  vars 区段的定义, 实际上是在 当前 play 中针对一组主机定义了变量, 但 Ansible 实际做法其实时, 对这个群组的每一个主机创建一个变量的副本.
  ansible 允许定义于主机或群组有关的变量, 这些变量可以定义在 inventory 文件中, 也可以定义在与 inventory 文件放在一起的独立文件中.
  Ansible 变量定义位置

变量标识
描述
vars
playbook 区段, 为字典列表
vars_file
playbook 区段, 为指向文件的列表
host_vars
目录, 主机变量
group_vars
目录, 群组变量
主机变量
inventory中, 单独针对主机的变量
群组变量
inventory中, 单独针对单个群组的变量
1.2. 显示变量: debug 模块
  

- debug: var=myvarname  

1.3. register 注册变量: 基于 task 的执行结果, 设置变量的值.
  示例:
  

- name: Run MyProg  command: /opt/myprog
  register: result
  ignore_errors: True
  

  
- debug: var=result
  

  ignore_errors 语句, 可以实现, 在 task 失败的时候, 是否忽略错误, 继续执行下面的 task, 默认为 False.
  访问变量中字典的key, 有两种方式:


  • {{ login.stdout }}
  • {{ ansible_eth1["ipv4"]["address"] }}
  当 task 在目标主机, 没有执行命令时, 即当目标主机已经符合目标结果时, 输出中没有 stdout,stderr,stdout_lines 三个键值.
  如果在 playbook 中使用了注册变量, 那么无论模块是否改变了主机的状态, 请确保你了解变量的内容, 否则, 当你的 playbook 尝试访问注册变量中不存的 key时, 可能会导致失败.

1.4. set_fact 定义新变量
  使用 set_fact 模块在 task 中设置 fact(与定义一个新变量是一样的). 可以在 register 关键字后, 立即使用 set_fact , 这样使得变量引用更简单.
  

- name: get snapshot>shell: >  aws ec2 describe-snapshot --filters Name=tag:Name, Valuse=my-snapshot | jq --raw-outpuy ".Snapshots[].SnapshtId"
  register: snap_result
  
- set_fact: snap={{ snap_result.stdout }}
  

  
- name: delete old snapshot
  command: aws ec2 delete-snapshot --snapshot-id "{{ snap }}"
  

1.5. 内置变量

参数
说明
hostvars
字典, key 为 Ansible 主机的名字, value 为所有变量名与相应变量值映射组成的字典
inventory_hostname
当前主机被 Ansible 识别的名字, 如果定义了别名, 则为别名.
group_names
列表, 由当前主机所属的所有群组组成
groups
字典, key 为 ansible 群组名, value 为群组成员的主机名所组成的列表. 包括 all 分组和 ungrouped 分组
play_hosts
列表, 成员是当前 play 涉及的主机的 inventory 主机名.
ansible_version
字典, 由 Ansible 版本信息组成.

  •   hostvars :
      在 Ansible 中, 变量的作用域是按照主机划分的, 只有针对特定主机讨论变量的值才有意义.
      有时候 , 针对一组主机定义的变量, 该变量实际始于特定的主机相关联的.
      
    例如 vars 区段的定义, 实际上是在 当前 play 中针对一组主机定义了变量, 但 Ansible 实际做法其实时, 对这个群组的每一个主机创建一个变量的副本.
      hostvars变量包含了在所有主机上定义的所有变量, 并以 ansible 识别的主机名作为 key. 如果 Ansible 还未对主机采集 fact, 那么除非启动 fact 缓存, 否则无法使用 hostvars 访问fact.
      有时, 在某一个主机上运行的 task 可能会需要在另一台主机上定义的变量. 例如, web 服务器, 可能需要 数据库服务器的 ansible_eth1.ipv4.address 这个 fact. 如果 数据库服务器为 db.example.com, 那么, 其变量引用为:
      

    {{ hostvars['db.example.com'].ansible_eth1.ipv4.address }}  

      - debug: var=hostvars[inventory_hostname] : 输出与当前主机相关联的所有变量.

  •   groups :
      代表当前 inventory 所定义的所有组的集合, 为一个字典.
      示例: web 负载均衡配置文件
      

    backend web-backend  
    {% for host in groups.web %}
      server {{ host.inventory_hostname }} {{ host.ansible_default_ipv4.address }}:80
      
    {% endfor %}

1.6. 在命令行设置变量
  向 ansible-playbook 传入 -e var=value 参数设置变量或传递参数, 有最高优先级. 可以覆盖已定义的变量值.
  

$ ansible-playbook example.yml -e token=123456  

  希望在变量中出现空格, 需要使用引号:
  

$ ansible-playbook playbooks/greeting.yml -e 'greeting="Oops you have another hello world"'  

  @filename.yml 传递参数:
  

$ cat greetvars.yml  greeting: "ops you have another hello world"
  

  
$ ansible-playbook playbooks/greeting.yml -e @greetvars.yml
  

2. fact
  当 Ansible 采集 fact 的时候, 他会连接到目标主机收集各种详细信息: CPU 架构,操作系统,IP地址,内存信息,磁盘信息等. 这些信息保存在被称为 fact 的变量中. fact 与其他变量的行为一模一样.

2.1. setup 模块
  

实现 fact 收集的模块. 一般无需再 playbook 中调用该模块, Ansible 会在采集 fact 时, 自动调用.  

  
`$ ansible server_name -m setup -a 'filter=ansible_eth*'`
  

  
其返回值为一个字典, 字典的 key 是 ansible_fact, 他的 value 是一个有实际 fact 的名字与值组成的字典.
  

  
setup 模块支持 filter 参数, 可以实现 shell 通配符的匹配过滤.
  

2.2. 模块返回 fact
  

如果一个模块返回一个字典且包含名为 ansible_facts 的key, 那么 ansible 将会根据对应的 value 创建响应的变量, 并分配给相对应的主机. 对于返回 fact 的模块, 并不需要使用注册变量, 因为 ansible 会自动创建.  

  
可以自动返回 fact 的模块: $ ansible-doc --list |grep facts
  
- ec2_facts
  
- docker_image_facts
  

2.3. 本地 fact
  

可将一个或者多个文件放置在目标主机的 /etc/ansible/facts.d/ 目录下, 如果该目录下的文件以 init格式, JSON格式 或者输出JSON格式的可执行文件(无需参数), 以这种形式加载的 fact 是 ansible_local 的特殊变量.  

  
示例:
  

  # 目标主机
  $ /etc/ansible/facts.d/books.fact
[book]

  title=Ansible: Up and Running
  author=Lorin Hochstein
  publisher=P'Reilly Media
  

  # ansible 主机
  $ cat playbooks/local.yml
  

  - name: get local variables
  hosts: host_c
  gather_facts: True
  tasks:
  - name: print local variables;
  debug: var=ansible_local

  - name: print book>
  debug: msg="The Book>  

  
注意 ansible_local 变量值的结构, 因为 fact 文件的名称为 books, 所以 ansible_local 变量是一个字典, 且包含一个名为 "books" 的 key.
  

3. 变量优先级:
  以下优先级依次降低


  •   命令行参数

  •   其他

  •   通过 inventory 文件或 YAML 文件定义的主机变量或群组变量

  •   Fact

  •   在 role 的 defaults/mail.yml 文件中的变量.

4. 过滤器: 变量加工处理
  Ansible 除了使用 Jinja2 作为模板之外, 还将其用于变量求值. 即, 可以在 playbook 中在 {{}} 内使用过滤器.
  
除了可以用 Jinja2 的内置过滤器外, Ansible 还有一些自己扩展的过滤器.
  有些参数, 需要参数, 有些则不需要.
  Jinja2 内置过滤器
  
Ansible 过滤器

4.1. default : 设置默认值.
  

# 设置 HOST 变量的默认值, 如果 database 没有被定义, 则使用 localhost .  
"HOST": "{{ database | default('localhost') }}"
  

4.2. 用于注册变量的过滤器
  对注册变量状态检查状态的过滤器

名称
描述
failed
如果注册变量的值是任务 failed , 则返回 True
changed
如果注册变量的值是任务 changed , 则返回 True
success
如果注册变量的值是任务 success , 则返回 True
skipped
如果注册变量的值是任务 skipped , 则返回 True  示例:
  

- name: Run myprog  command: /opt/myprog
  register: result
  ignore_errors: True
  
- debug: var=result
  
- debug: msg="Stop Running the playbook if myprog failed"
  failed_when: result|failed
  

4.3. 用于文件路径的过滤器
  用于处理包含控制主机文件系统的路径的变量.

过滤器
描述
basename
文件路径中的目录
dirname
文件路径中的目录
expanduser
将文件路径中的 ~ 替换为用户家目录
realpath
处理符号链接后的文件实际路径  示例:
  

vars:  homepages: /usr/share/nginx/html/index.html
  
tasks:
  - name: copy home page
  copy: src=files/{{ homepages| basename }} desc={{ homepages }}
  

4.4. 自定义过滤器
  Ansible 会在存放 playbook 的目录下的 filter_plugins 目录中寻找自定义过滤器. 也可以放在 /usr/share/ansible_plugins/filter_plugins/ 目录下, 或者 环境变量ANSIBLE_FILTER_PLUGINS 环境变量设置的目录.
  

# filter_plugins/surround_by_quotes.py  
def surround_by_quote(a_list):
  return ['"%S"' % an_element for an_element in a_list]
  

  
class FilterModule(object):
  def filters(self):
  return {'surround_by_quote': surround_by_quote}
  

  surround_by_quote 函数定义了 Jinja2 过滤器.
  
FilterModule 类定义了一个 filter 方法, 该方法返回由过滤器名称和函数本身组成的字典. FilterModule 是 Ansible 相关代码, 他使得 Jinja2 过滤器可以再 Ansible 中使用.

5. lookup: 从多种来源读取配置数据.
  lookup 官方文档说明
  
Ansible 所有的 lookup 插件都是在控制主机, 而不是远程主机上执行的
  支持的数据来源表:

名称
描述
file
文件的内容
password
随机生成密码
pipe
本地命令执行的输出
env
环境变量
template
Jinja2 模板渲染的结果
csvfile
.csv 文件中的条目
dnstxt
DNS 的 TXT 记录
redis_ke
对 Redis 的key 进行查询
etcd
对 etcd 中的key 进行查询

  •   file
      示例: 在 playbook 中调用 lookup
      

    - name: Add my public key as an EC2 key  ec2_key: name=mykey key_material="{{ lookup('file', '/home/me/.ssh/id_rsa.pub') }}"
      

      示例: 使用 Jinja2 模板
      

    # authorized_keys.j2  
    {{ lookup('file', '/home/me/.ssh/id_rsa.pub') }}
      

      
    # playbook
      
    - name: copy authorized_host file
      template: src=authorized_keys.j2 desc=/home/deploy/.ssh/authorized_keys

  •   pipe
      在控制主机上调用一个外部程序, 并将这个程序的输出打印到标准输出上.
      示例: 得到最新的 git commit 使用的 SHA-1 算法的值.
      

    - name: get SHA of most recent commit  debug: msg="{{ lookup('pipe', 'git rev-parse HEAD') }}"

  •   env
      获取在控制主机上的某个环境变量的值.
      示例:
      

    - name: get the current shell  debug: msg="{{ lookup('env', 'SHELL') }}"

  •   password
      随机生成一个密码, 并将这个密码写入到参数指定的(控制主机)文件中.
      示例: 生成 deploy 的 Postgre 用户和密码, 并将密码写入到 deploy-password.txt 中:
      

    - name: create deploy postgre user  postgresql_user:
      name: deploy
      password: "{{ lookup('password', 'deploy-password.txt') }}"

  •   template
      指定一个 Jinji2 模板文件, 并返回这个模板渲染的结果.
      

    # message.j2  
    This host runs {{ ansible_distribution }}
      

      
    # task
      
    - name: output message from template
      debug: msg="{{ lookup('template', 'message.j2') }}"

  •   csvfile
      从 csv 文件中读取一个条目.
      

    # users.csv  
    username, email
      
    lorin, lorin@example.com
      
    john, john@example.com
      
    sue, sue@example.com
      

      
    # 调用 : 查看名为 users.csv 的文件, 使用逗号作为分隔符来定位区域, 寻找第一列的值是 sue 的那一行, 返回第二列(索引从 0 开始)的值.
      
    lookup('csvfile', 'sue file=users.csv delimiter=, col=1') --> sue@example.com
      

      
    # 用户名被存储在 username 变量中, 可以用 "+" 连接其他参数, 构建完整的参数字符串.
      
    lookup('csvfile', username + 'file=users.csv delimiter=, col=1')

  •   dnstxt
      需要安装 dnspython 包, $ pip install dnspython
      TXT 记录是 DNS 中一个可以附加在主机名上的任意字符串, 一旦为主机名关联了一条 TXT 记录, 则任何人都可以使用 DNS 客户端获取这段文本.
      

    # 使用 dig 查看 TXT 记录  
    $ dig +short ansiblebook.com TXT
      
    "isbn=97801491915325"
      

      
    # task
      
    - name: look up TXT record
      debug: msg="{{ lookup('dnstxt', 'ansiblebook.com') }}"

  •   redis-kv
      需要安装 redis 包: $ pip install pip
      
    可以使用 redis-kv 获取一个 key 的value, key 必须为字符串.
      

    # 设置一个值:  
    $ redis-cli SET weather sunny
      

      
    # task
      
    - name: look up value in redis
      debug: msg="{{ lookup('redis_kv', 'redis://localhost:6379,weather') }}"

  •   etcd
      etcd lookup 默认在 http://127.0.0.1:4001 上查找 etcd 服务器, 可以在执行 ansible-playbook 之前, 通过设置 ANSIBLE_ETCD_URL 改变这个值.
      

    # 设置测试值  
    $ curl -L http://127.0.0.1:4001/v2/keys/weather -XPUT -d value=cloudy
      

      
    # task
      
    - name: loop up value in etcd
      debug: msg="{{ lookup('etcd', 'weather') }}"


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-430982-1-1.html 上篇帖子: 1、Ansible初识简要介绍及安装 下篇帖子: 【Ansible 文档】【译文】动态inventory
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表