管理变量 机密和事实

 1. 管理变量

命名变量

变量的名称必须以字母开头,并且只能包含字母、数字和下划线。

无效和有效的Ansible变量名称示例

无效的变量名称    有效的变量名称
web server    web_server
remote.file    remote_file
1st file    file_1
file1
remoteserver$1    remote_server_1
remote_server1
定义变量

可以在Ansible项目中的多个位置定义变量。不过,这些变量大致可简化为三个范围级别:

全局范围:从命令行或Ansible配置设置的变量
Play范围:在play和相关结构中设置的变量
主机范围:由清单、事实收集或注册的任务,在主机组和个别主机上设置的变量
如果在多个xeklh定义了相同名称的变量,则采用优先级别最高的变量。窄范围优先于更广泛的范围:由清单定义的变量将被playbook定义的变量覆盖,后者将被命令行中定义的变量覆盖。

 

1.2 playbook中的变量
变量在Ansible Playbook中发挥着重要作用,因为它们可以简化playbook中变量数据的管理。

1.2.1 在Playbook中定义变量

编写playbook时,可以定义自己的变量,然后在任务中调用这些值。例如,名为web_package的变量可以使用值httpd来定义。然后,任务可以使用yum模块调用该变量来安装httpd软件包。

Playbook变量可以通过多种方式定义。一种常见的方式是将变量放在playbook开头的vars块中:
 

 

---
- hosts: web01.example.com
  vars: 
    - web/httpd
  tasks:
    - name: provides repo file
      copy:
        src: files/CentOS-Base.repo
        dest: /etc/yum.repos.d/
    - name: install httpd
      dnf:
        name: " {{ web }} "
        state: latest
    - name: provides web site
      copy:
        src: files/htmlxunakuhei
        dest: /var/www/html/
    - name: config {{ web }}
      copy:
        src: files/httpd-vhosts.conf
        dest: /etc/httpd/conf.d/
    - name: run {{ web }}
      service:
        name: " {{ web }} "
        state: started
        enabled: yes
    - name: close firewalld
      service:
        name: firewalld
        state: stopped
        enabled: no
 

 也可以在外部文件中定义playbook变量。此时不使用playbook中的vars块,可以改为使用vars_files指令,后面跟上相对于playbook位置的外部变量文件名称列表:

[root@localhost ansible]# cat vars/httpd 
web: httpd
 
---
- hosts: web01.example.com
  vars_files:
    - vars/httpd
  tasks:
    - name: provides repo file
      copy:
        src: files/CentOS-Base.repo
        dest: /etc/yum.repos.d/
    - name: install httpd
      dnf:
        name: " {{ web }} "
        state: latest
    - name: provides web site
      copy:
        src: files/htmlxunakuhei
        dest: /var/www/html/
    - name: config {{ web }}
      copy:
        src: files/httpd-vhosts.conf
        dest: /etc/httpd/conf.d/
    - name: run {{ web }}
      service:
        name: " {{ web }} "
        state: started
        enabled: yes
    - name: close firewalld
      service:
        name: firewalld
        state: stopped
        enabled: no

 

 

2. 管理机密

2.1 Ansible Vault

Ansible可能需要访问密码或API密钥等敏感数据,以便能配置受管主机。通常,此信息可能以纯文本形式存储在清单变量或其他Ansible文件中。但若如此,任何有权访问Ansible文件的用户或存储这些Ansible文件的版本控制系统都能够访问此敏感数据。这显示存在安全风险。

Ansible提供的Ansible Vault可以加密和解密任何由Ansible使用的结构化数据文件。若要使用Ansible Vault,可通过一个名为ansible-vault的命令行工具创建、编辑、加密、解密和查看文件。Ansible Vault可以加密任何由Ansible使用的结构化数据文件。这可能包括清单变量、playbook中含有的变量文件、在执行playbook时作为参数传递的变量文件,或者Ansible角色中定义的变量。

2.1.1 创建加密的文件

要创建新的加密文件,可使用ansible-vault create filename命令。该命令将提示输入新的vault密码,然后利用默认编辑器vi打开文件。我们可以设置和导出EDITOR环境变量,通过设置和导出指定其他默认编辑器。例如,若要将默认编辑器设为nano,可设置为export EDITOR=nano

[root@localhost ~]# ansible-vault create abc
New Vault password: 
Confirm New Vault password: 
[root@localhost ~]# ll
total 12
-rw-------   1 root root  419 May 30 14:46 abc
[root@localhost ~]# cat abc
$ANSIBLE_VAULT;1.1;AES256
39643337343939343330616236343237313163653539336236333837623336356233353634646333
3664613166643966623334363531373362313763373830310a393230303165396563313464393239
38646432653066303638623334643662346538643939656166376461376230623339363266633032
3933613735626233370a643233663461666136323931343730343933316437366431306539613232
63646339646337373839303862656435353364613066666336386462343636613235

[root@localhost ~]# ansible-vault view abc
Vault password: 
name: httpd
port: 80

 我们还可以用vault密码文件来存储vault密码,而不是通过标准输入途径输入vault密码。这样做需要使用文件权限和其他方式来

2.1.2 查看加密的文件

可以使用ansible-vault view filename命令查看Ansible Vault加密的文件,而不必打开它进行编辑。

ansible-vault view secret.yml

严密保护该文件。

2.1.3 编辑现有的加密文件

要编辑现有的加密文件,Ansible Vault提供了ansible-vault edit filename命令。此命令将文件解密为一个临时文件,并允许编辑。保存时,它将复制其内容并删除临时文件。

ansible-vault edit secret.yml

编辑时需要输入加密文件的加密密码。

edit子命令始终重写文件,因此只应在进行更改时使用它。要查看文件的内容而不进行更改时,应使用view子命令。

2.1.4 加密现有的文件

要加密已存在的文件,请使用ansible-vault encrypt filename命令。此命令可取多个欲加密文件的名称作为参数。

ansible-vault encrypt secret1.yml secret2.yml

使用--output=OUTPUT_FILE选项,可将加密文件保存为新的名称。只能通过--output选项使用一个输入文件。

2.1.5 解密现有的文件

现有的加密文件可以通过ansible-vault decrypt filename命令永久解密。在解密单个文件时,可使用--output选项以其他名称保存解密的文件。

ansible-vault decrypt secret1.yml --output=secret1-decrypted.yml

2.1.6 更改加密文件的密码

使用ansible-vault rekey filename命令更改加密文件的密码。此命令可一次性更新多个数据文件的密钥。它将提示提供原始密码和新密码。

ansible-vault rekey secret.yml

在使用vault密码文件时,请使用--new-vault-password-file选项:

ansible-vault rekey --new-vault-password-file=NEW_VAULT_PASSWORD_FILE secret.yml

2.2 playbook和ansible vault

要运行可访问通过Ansible Vault加密的文件的playbook,需要向ansible-playbook命令提供加密密码。如果不提供密码,playbook将返回错误:

[root@localhost ~]# ansible-playbook site.yml
ERROR: A Vault password must be specified to decrypt vars/api_key.yml

要为playbook提供vault密码,可使用--vault-id选项。例如,要以交互方式提供vault密码,请使用下例中所示的--vault-id @prompt:

[root@localhost ansible]# ansible-playbook -C --vault-id @prompt mysql.yml 
Vault password (default): 
 
PLAY [web01.example.com] *******************************************************************
 
TASK [Gathering Facts] *********************************************************************
ok: [web01.example.com]
 
TASK [install mariadb] *********************************************************************
changed: [web01.example.com]
 
TASK [install mariadb-server] **************************************************************
changed: [web01.example.com]
 
TASK [run mysql] ***************************************************************************
changed: [web01.example.com]
 
PLAY RECAP *********************************************************************************
web01.example.com          : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

此外,也可使用--vault-password-file选项指定以纯文本存储加密密码的文件。密码应当在该文件中存储为一行字符串。由于该文件包含敏感的纯文本密码,因此务必要通过文件权限和其他安全措施对其加以保护。

ansible-playbook --vault-password-file=vault-pw-file site.yml

也可以使用ANSIBLE_VAULT_PASSWORD_FILE环境变量,指定密码文件的默认位置。

从Ansible2.4开始,可以通过ansible-playbook使用多个Ansible Vault密码。要使用多个密码,需要将多个--vault-id--vault-password-file选项传递给ansible-playbook命令。

ansible-playbook --vault-id one@prompt --vault-id two@prompt site.yml

注意:@prompt前面的vaultIDonetwo可以是任何字符,甚至可以完全省略它们。不过,如果在使用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中的文件外,也可对每一主机组或受管主机使用目录。这些目录可包含多个变量文件,它们都由该主机组或受管主机使用。例如,在playbook.yml的以下项目目录中,webservers的主机组的成员将使用group_vars/webservers/vars文件中的变量,而172.16.103.129将使用host_vars/172.16.103.129/vars和host_vars/172.16.103.129/vault中的变量:
 

.
├── ansible.cfg
├── group_vars
│   └── webservers
│       └── vars
├── host_vars
│   └── 172.16.103.129
│       ├── vars
│       └── vault
├── inventory
└── playbook.yml

在这种情况中,其好处在于用于172.16.103.129的大部分变量可以放在vars文件中,敏感变量则可单独放在vault文件中保密。然后使用ansible-vault加密vault文件,而将vars文件保留为纯文本。

在本例中,host_vars/172.16.103.129目录内使用的文件名没有什么特别之处。该目录可以包含更多文件,一些由Ansible Vault加密,另一些则不加密。

Playbook变量(与清单变量相对)也可通过Ansible Vault保护。敏感的playbook变量可以放在单独的文件中,此文件通过Ansible Vault加密,并能vars_files指令包含在该playbook中。这也是推荐做法,因为playbook变量的优先级高于清单变量。

如果需要在playbook中使用多个vault密码,请确保每个加密文件分配一个vaultID,并在运行playbook时输入具有该vaultID的匹配密码。这可确保在解密vault加密文件时先选择正确的密码,这比强制Ansible尝试用户提供的所有vault密码直至找到正确的密码要快。

管理事实
借助事实,可以方便地检索受管主机的状态,并根据该状态确定要执行的操作。例如:

可以根据含有受管主机当前内核版本的事实运行条件任务,以此来重启服务器
可以根据通过事实报告的可用内存来自定义MySQL配置文件
可以根据事实的值设置配置文件中使用的IPv4地址
通常,每个play在执行第一个任务之前会先自动运行setup模块来收集事实。

查看为受管主机收集的事实的一种方式是,运行一个收集事实并使用debug模块显示ansible_facts变量值的简短playbook。
 

[root@localhost ansible]# vim facts.yml
 
---
- hosts: web01.example.com
  tasks:
    - name: Fact dump
  hosts: all
  tasks:
    - name: Print all facts
      debug:
        var: ansible_facts

运行该playbook时,事实将显示在作业输出中:

[root@localhost ansible]# ansible-playbook -C facts.yml
 },
        "default_ipv4": {
            "address": "192.168.80.13",
            "alias": "ens33",
            "broadcast": "192.168.80.255",
            "gateway": "192.168.80.2",
            "interface": "ens33",
            "macaddress": "00:0c:29:0d:53:85",
            "mtu": 1500,
            "netmask": "255.255.255.0",
            "network": "192.168.80.0",
            "type": "ether"
 
"model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "35643392",
                "sectorsize": "512",
                "size": "17.00 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1

Playbook以JSON格式显示ansible_facts变量的内容。

下表显示了可能从受管节点收集的并可在playbook中使用的一些事实:
Ansible事实的示例

事实    变量
短主机名    ansible_facts['hostname']
完全限定域名    ansible_facts['fqdn']
IPv4地址    ansible_facts['default_ipv4']['address']
所有网络接口的名称列表    ansible_facts['interfaces']
/dev/vda1磁盘分区的大小    ansible_facts['devices']['vda']['partitions']['vda1']['size']
DNS服务器列表    ansible_facts['dns']['nameservers']
当前运行的内核版本    ansible_facts['kernel']
如果变量的值为散列/字典类型,则可使用两种语法来获取其值。比如:
ansible_facts['default_ipv4']['address']也可以写成ansible_facts.default_ipv4.address
ansible_facts['dns']['nameservers']也可以写成ansible_facts.dns.nameservers
在playbook中使用事实时,Ansible将事实的变量名动态替换为对应的值:
 

[root@localhost ansible]# vim facts.yml
 
---
- hosts: web01.example.com
  tasks:
    - name: Prints various Ansible facts
    debug:
      msg: >
        The default IPv4 address of {{ ansible_facts.fqdn }}
        is {{ ansible_facts.default_ipv4.address }}

 Ansible事实作为变量注入
在Ansible2.5之前,事实是作为前缀为字符串ansible_的单个变量注入,而不是作为ansible_facts变量的一部分注入。例如,ansible_facts['distribution']事实会被称为ansible_distribution。

许多较旧的playbook仍然使用作为变量注入的事实,而不是在ansible_facts变量下创建命名空间的新语法。我们可以使用临时命令来运行setup模块,以此形式显示所有事实的值。以下示例中使用一个临时命令在受管主机172.16.103.129上运行setup模块:

ansible 172.16.103.129 -m setup

选定的Ansible事实名称比较

ansible_facts形式旧事实变量形式
ansible_facts['hostname']ansible_hostname
ansible_facts['fqdn']ansible_fqdn
ansible_facts['default_ipv4']['address']ansible_default_ipv4['address']
ansible_facts['interfaces']ansible_interfaces
ansible_facts['devices']['vda']['partitions']['vda1']['size']ansible_devices['vda']['partitions']['vda1']['size']
ansible_facts['dns']['nameservers']ansible_dns['nameservers']
ansible_facts['kernel']ansible_kernel

 

目前,Ansible同时识别新的事实命名系统(使用ansible_facts)和旧的2.5前“作为单独变量注入的事实”命名系统。

将Ansible配置文件的[default]部分中inject_facts_as_vars参数设置为False,可关闭旧命名系统。默认设置目前为True。

inject_facts_as_vars的默认值在Ansible的未来版本中可能会更改为False。如果设置为False,则只能使用新的ansible_facts.*命名系统引用Ansible事实。所以建议大家一开始就要适应这种方式。

 关闭事实收集
有时我们不想为play收集事实。这样做的原因可能有:

不准备使用任何事实
希望加快play速度
希望减小play在受管主机上造成的负载
受管主机因为某种原因无法运行setup模块
需要安装一些必备软件后再收集事实
以上种种原因导致我们可能想要永久或暂时关闭事实收集的功能,要为play禁用事实收集功能,可将gather_facts关键字设置为no:
 

[root@localhost ansible]# vim facts.yml
 
---
- name: This play gathers no facts automatically
  hosts: large_farm
  gather_facts: no
 
[root@mingzi ansible]# ansible-playbook -C facts.yml 
[WARNING]: Could not match supplied host pattern, ignoring: large_farm
 
PLAY [This play gathers no facts automatically] ********************************************
skipping: no hosts matched
 
PLAY RECAP *********************************************************************************

即使play设置了gather_facts: no,也可以随时通过运行使用setup模块的任务来手动收集事实:

[root@localhost ansible]# vim facts.yml
 
---
- name: gather_facts
  hosts: 192.168.80.13
  gather_facts: no
  tasks:
    - name: get gather_facts
      setup:
    - name: debug
      debug:
        var: ansible_factsi
 
 
[root@mingzi ansible]# ansible-playbook -C facts.yml 
[WARNING]: Could not match supplied host pattern, ignoring: 192.168.80.13
 
PLAY [gather_facts] ************************************************************************
skipping: no hosts matched
 
PLAY RECAP *********************************************************************************
 

创建自定义事实
除了使用系统捕获的事实外,我们还可以自定义事实,并将其本地存储在每个受管主机上。这些事实整合到setup模块在受管主机上运行时收集的标准事实列表中。它们让受管主机能够向Ansible提供任意变量,以用于调整play的行为。

自定义事实可以在静态文件中定义,格式可为INI文件或采用JSON。它们也可以是生成JSON输出的可执行脚本,如同动态清单脚本一样。

有了自定义事实,我们可以为受管主机定义特定的值,供play用于填充配置文件或有条件地运行任务。动态自定义事实允许在play运行时以编程方式确定这些事实的值,甚至还可以确定提供哪些事实。

默认情况下,setup模块从各受管主机的/etc/ansible/facts.d目录下的文件和脚本中加载自定义事实。各个文件或脚本的名称必须以.fact结尾才能被使用。动态自定义事实脚本必须输出JSON格式的事实,而且必须是可执行文件。

以下是采用INI格式编写的静态自定义事实文件。INI格式的自定义事实文件包含由一个部分定义的顶层值,后跟用于待定义的事实的键值对:
 

[packages]
web_package = httpd
db_package = mariadb-server
 
[users]
user1 = xixi
user2 = hehe

同样的事实可能以JSON格式提供。以下JSON事实等同于以上示例中INI格式指定的事实。JSON数据可以存储在静态文本文件中,或者通过可执行脚本输出到标准输出:

{
  "packages": {
    "web_package": "httpd",
    "db_package": "mariadb-server"
  },
  "users": {
    "user1": "xixi",
    "user2": "hehe"
  }
}

自定义事实文件不能采用playbook那样的YAML格式。JSON格式是最为接近的等效格式。

自定义事实由setup模块存储在ansible_facts.ansible_local变量中。
事实按照定义它们的文件的名称来整理。例如,假设前面的自定义事实由受管主机上保存为/etc/ansible/facts.d/custom.fact的文件生成。在这种情况下,ansible_facts.ansible_local['custom']['users']['user1']的值为joe。

可以利用临时命令在受管主机上运行setup模块来检查自定义事实的结构。
 

 自定义事实的使用方式与playbook中的默认事实

---
- hosts: all
  tasks:
  - name: Prints various Ansible facts
    debug:
      msg: >
        The package to install on {{ ansible_facts['fqdn'] }}
        is {{ ansible_facts['ansible_local']['cutstom']['packages']['web_package'] }}

3.5 使用魔法变量

一些变量并非事实或通过setup模块配置,但也由Ansible自动设置。这些魔法变量也可用于获取与特定受管主机相关的信息。

最常用的有四个:

魔法变量说明
hostvars包含受管主机的变量,可以用于获取另一台受管主机的变量的值。
如果还没有为受管主机收集事实,则它不会包含该主机的事实。
group_names列出当前受管主机所属的所有组
groups列出清单中的所有组和主机
inventory_hostname包含清单中配置的当前受管主机的主机名称。
因为各种原因有可能与事实报告的主机名称不同

 

另外还有许多其他的“魔法变量”。有关更多信息,请参见以下链接:
Using Variables — Ansible Documentation。
若要深入了解它们的值,一个途径是使用debug模块报告特定主机的hostvars变量的内容:

ansible 192.168.80.13 -m debug -a 'var=hostvars["localhost"]'
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值