【Ansible】让你掌握关键要点的贴心提示 第二篇

使用Ansible时,我个人遇到了一些问题并进行了研究,现在我想将它们作为小贴士总结起来。当积累到一定数量的小贴士后,我会发布第三篇!

本次介绍的小贴士

    1. OS用户的密码无需事先进行哈希处理!

 

    1. 将role内的变量设为仅在role内使用的私有变量

 

    1. 在Ansible模块中使用*(星号)

 

    1. 想要安装RPM包

 

    1. 想要在使用become时自动输入sudo密码

 

    1. 想要在使用ansible-vault时通过环境变量传递密码

 

    1. 将需要重复写入的参数进行整合!

 

    当变量中包含变量时,在Ansible中使用eval进行处理

OS用户的密码无需提前进行哈希化!


使用password_hash

以前提到过的技巧是在事前进行加密的步骤,但是仔细查看参考资料后发现有一种可以进行加密的写法。

我們可以滿足以下需求。

    • sha256

 

    sha512

使用方法

  - name: ユーザー作成
    user:
      name: test
      #SHA256の時はこちら
      password: "{{ 'password' |password_hash('sha256', 'mysecretsalt') }}"
      #SHA512の時はこちら
      password: "{{ 'password' |password_hash('sha512', 'mysecretsalt') }}"
      home: /home/test

然而需要注意的是,如果按照以下方式将变量列成列表并进行循环,执行结果中的密码将会以明文形式传递。

  vars:
    test:
      - name: test1
        password: password
        home: /home/test1

      - name: test2
        password: password
        home: /home/test2

  tasks:
    - user:
        name: "{{ item.name }}"
        password: "{{ item.password |password_hash('sha256', 'mysecretsalt') }}"
        home: "{{ item.home }}"
      with_items:
        - "{{ test }}"

密码以明文形式可见!

PLAY ***************************************************************************

TASK [user] ********************************************************************
changed: [rhel6_d] => (item={u'home': u'/home/test1', u'password': u'password', u'name': u'test1'})
changed: [rhel6_d] => (item={u'home': u'/home/test2', u'password': u'password', u'name': u'test2'})

因此,如果要将其列入列表,我们需要添加no_log:True,以便不输出。

  vars:
    test:
      - name: test1
        password: password
        home: /home/test1

      - name: test2
        password: password
        home: /home/test2

  tasks:
    - user:
        name: "{{ item.name }}"
        password: "{{ item.password |password_hash('sha256', 'mysecretsalt') }}"
        home: "{{ item.home }}"
      with_items:
        - "{{ test }}"
      no_log: True

这样会发生。

TASK [user] ********************************************************************
changed: [rhel6_d] => (item=(censored due to no_log))
changed: [rhel6_d] => (item=(censored due to no_log))

将角色内的变量转换为仅在角色内部使用的私有变量。

使用private_role_vars = yes

被role调用或定义的变量,即使在处理转移到另一个role中,也会被继承。这也是Ansible变量命名规则中要求在开头加上role名称的原因。

然而,如果无法这样做,就需要在角色中封闭变量,在ansible.cfg文件中添加以下内容。

private_role_vars = yes

在Ansible模块中使用*(星号)

使用 with_fileglob

- copy: 
    src: {{ item }} 
    dest: /path

  with_fileglob:
    - "/etcsysconfig/network-scripts/ifcfg-*"

顺便一提,在使用 fetch 模块中,虽然使用 with_fileglob 会显示输出结果正常,但有可能无法获取文件的情况。这是因为 with_fileglob 的解析是在本地主机上进行的,而 fetch 则在目标机器(受配置管理的服务器)上执行。

因此,如果要指定特定情况,可以使用shell模块进行find搜索并将注册的值放入with_items。
如果有其他更好的方法,请告诉我。

我想要安装RPM软件包。

使用yum模块

通过使用yum模块,在name属性中可以完整地指定路径,从而可以通过指定本地上的RPM文件进行安装。

yum:
  name: xxxxx.rpm
  state: present

使用参考:Ansible 可处理 RPM 包。

在使用become时,希望能自动输入sudo密码。

使用ansible_become_pass

自动输入无效!对于那些已经将sudo密码设置为NOPASSWD的人来说,这是个好消息。

在过去,我们有sudo_password之类的设置,但从推荐使用become之后,在ansible.cfg中无法再指定它了。那么该怎么办呢?答案是,现在有ansible_become_pass可供使用。

这个东西有两种用法.

    • インベントリファイルで指定

 

    変数ファイルで指定(変数として作成する)
[target]
hostname1 ansible_become_pass=xxxx
ansible_become_pass: xxxx

发展案例(通过环境变量传递)

ansible_become_pass: "{{ lookup('env','SUDO_PASSWD') }}"

希望在使用ansible-vault时可以通过环境变量传递密码。

当使用类似Jenkins的CI工具或者不想保存Vault密码文件时,可以使用的技巧。

— 我们将使用“vault-password-file”来解锁。

–vault-password-file可以接受不仅仅是文件作为参数,还可以接受具有执行权限的脚本,并将其标准输出用作密码。

即通过解析脚本中的环境变量并将其输出到标准输出,就不再需要将vault密码保存在本地了。这是一种类似于动态清单的用法。

#!/bin/bash
echo $VAULT_PASS
export VAULT_PASS=xxx
ansible-playbook site.yml --vault-password-file vault.sh

记录

如果你希望使用过程替换的方式來完成,甚至连创建shell都不需要!那么在Mac系统中,只需要利用过程替换,就可以实现以下功能。(在CentOS系统上无法实现)

ansible-playbook site.yml --vault-password-file <(echo $VAULT_PASS)

在Centos系的Linux中,对于进程替换时的临时文件,使用pipe:[xxxxxxxx]进行管理。

[server ]# ll <(date)
lr-x------ 1 root root 64  4月  8 11:01 /dev/fd/63 -> pipe:[24349835]

在执行ansible-vault命令时,以下文件中包含了os.path.realpath(引用实际文件路径)并且写有pipe:[xxxxxxxx],这导致了它无法正常工作。(当删除realpath时,就可以正常运行了)


this_path = os.path.realpath(to_bytes(os.path.expanduser(vault_password_file), errors='strict'))
if not os.path.exists(to_bytes(this_path, errors='strict')):
  raise AnsibleFileNotFound("The vault password file %s was not found" % this_path)

在Mac上,由于Centos的进程管理机制(proc周边)有所不同,使用进程替换的方式似乎可以解决这个问题。

整理需要多次写的参数!

使用YAML的合并语法。

参考:你可以在ansible-playbook中使用YAML的合并语法!

 - file:
     path: /tmp/a
     << : &DEF
       owner: ansible
       group: ansible
       mode: 0755
       state: directory
 - file:
     path: /tmp/b
     << : *DEF

我将owner/group/mode/state的设置放入DEF变量,并且将其重复使用。这将使得之后的权限设置更加简洁。(变量名称可以是任意的<< : &和<< : *非常重要)

这个看起来好像可以用在很多方面!

如果在Ansible中的eval变量中有变量的情况

{{ somvar_{{other_var}} }}

要做这样的事情时,可以按以下步骤进行。

{{['somevar_'  + other_var] }}

host_varsを使ってる時はこっちらしい
{{ hostvars[inventory_hostname]['somevar_'  + other_var] }}
广告
将在 10 秒后关闭
bannerAds