天天看点

ansible机密,事实,循环一,管理机密二,管理事实三,循环

一,管理机密

1,Ansible Vault

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

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

2,创建机密的文件

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

[[email protected] ~]# ansible-vault create secret.yml
New Vault password: redhat
Confirm New Vault password: redhat
           

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

ansible-vault create --vault-password-file=vault-pass secret.yml
           

3,查看加密的文件

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

ansible-vault view secret.yml
           

查看时需要输入加密文件的加密密码。

4,编辑现有加密文件

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

ansible-vault edit secret.yml
           

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

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

5,加密现有文件

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

ansible-vault encrypt secret1.yml secret2.yml
           

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

6,解密现有的文件

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

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

7,更改加密文件的密码

使用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
           

二,管理事实

1,描述Ansible事实

Ansible事实是Ansible在受管主机上自动检测到的变量。事实中包含有与主机相关的信息,可以像play中的常规变量、条件、循环或依赖于从受管主机收集的值的任何其他语句那样使用。

为受管主机收集的一些事实可能包括:

  • 主机名称
  • 内核版本
  • 网络接口
  • IP地址
  • 操作系统版本
  • 各种环境变量
  • CPU数量
  • 提供的或可用的内存
  • 可用磁盘空间

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

  • 可以根据含有受管主机当前内核版本的事实运行条件任务,以此来重启服务器
  • 可以根据通过事实报告的可用内存来自定义MySQL配置文件
  • 可以根据事实的值设置配置文件中使用的IPv4地址

通常,每个play在执行第一个任务之前会先自动运行setup模块来收集事实。

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

- name: Fact dump
  hosts: all
  tasks:
    - name: Print all facts
      debug:
        var: ansible_facts
           

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

ansible-playbook facts.yml
           

如果变量的值为散列/字典类型,则可使用两种语法来获取其值。比如:

  • ansible_facts[‘default_ipv4’][‘address’]也可以写成ansible_facts.default_ipv4.address
  • ansible_facts[‘dns’][‘nameservers’]也可以写成ansible_facts.dns.nameservers

    在playbook中使用事实时,Ansible将事实的变量名动态替换为对应的值:

---
- hosts: all
  tasks:
  - name: Prints various Ansible facts
    debug:
      msg: >
        The default IPv4 address of {{ ansible_facts.fqdn }}
        is {{ ansible_facts.default_ipv4.address }}
           

2,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)和旧的2.5前“作为单独变量注入的事实”命名系统。

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

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

3,关闭事实收集

  • 有时我们不想为play收集事实。这样做的原因可能有:
  • 不准备使用任何事实
  • 希望加快play速度
  • 希望减小play在受管主机上造成的负载
  • 受管主机因为某种原因无法运行setup模块
  • 需要安装一些必备软件后再收集事实

    以上种种原因导致我们可能想要永久或暂时关闭事实收集的功能,要为play禁用事实收集功能,可将gather_facts关键字设置为no:

---
- name: This play gathers no facts automatically
  hosts: large_farm
  gather_facts: no
           

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

---
- name: gather_facts
  hosts: 172.16.103.129
  gather_facts: no
  tasks:
    - name: get gather_facts
      setup:
    - name: debug
      debug:
        var: ansible_facts
           

4,创建自定义事实

除了使用系统捕获的事实外,我们还可以自定义事实,并将其本地存储在每个受管主机上。这些事实整合到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 = joe
user2 = jane
           

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

{
  "packages": {
    "web_package": "httpd",
    "db_package": "mariadb-server"
  },
  "users": {
    "user1": "joe",
    "user2": "jane"
  }
}
           

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

自定义事实由setup模块存储在ansible_facts.ansible_local变量中。

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

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

ansible 172.16.103.129 -m 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'] }}
           

三,循环

1,利用循环迭代任务

通过利用循环,我们无需编写多个使用同一模块的任务。例如,他们不必编写五个任务来确保存在五个用户,而是只需编写一个任务来对含有五个用户的列表迭代,从而确保它们都存在。

Ansible支持使用loop关键字对一组项目迭代任务。可以配置循环以利用列表中的各个项目、列表中各个文件的内容、生成的数字序列或更为复杂的结构来重复任务。

2,简单循环

对一组项目迭代任务。loop关键字添加到任务中,将应对其迭代任务的项目列表取为值。循环变量item保存每个迭代过程中使用的值。

请思考以下代码片段,它使用两次service模块来确保两个网络服务处于运行状态:

- name: Postfix is running
  service:
    name: postfix
    state: started
    
- name: Devecot is running
  service:
    name: dovecot
    state: started
           

这两个任务可以重新编写为使用一个简单循环,从而只需一个任务来确保两个服务都在运行:

- name: Postfix and Devecot are running
  service:
    name: "{{ item }}"
    state: started
  loop:
    - postfix
    - dovecot
           

可以通过一个变量提供loop所使用的列表。在以下示例中,变量mail_services含有需要处于运行状态的服务的列表。

vars:
  mail_services:
    - postfix
    - dovecot

tasks:
  - name: Postfix and Dovecot are running
    service:
      name: "{{ item }}"
      state: started
    loop: "{{ mail_services }}"
           

3,循环散列或字典列表

loop列表不需要是简单值列表。在以下示例中,列表中的每个项实际上是散列或字典。示例中的每个散列或字典具有两个键,即name和groups,当前item循环变量中每个键的值可以分别通过item.name和item.groups变量来检索。

- name: Users exist and are in the correct groups
  user:
    name: "{{ item.name }}"
    state: present
    groups: "{{ item.groups }}"
  loop:
    - name: jane
      groups: wheel
    - name: joe
      groups: root
           

这一示例中结果是用户jane存在且为组wheel的成员,并且用户joe存在且为组root的成员。

4,较早样式的循环关键字

在Ansible2.5之前,大多数playbook使用不同的循环语法。提供了多个循环关键字,前缀为whth_,后面跟Ansible查找插件的名称。这种循环语法在现有playbook中很常见,但在将来的某个时候可能会被弃用。

较早样式的Ansible循环

  • with_items #行为与简单列表的loop关键字相同,例如字符串列表或散列/字典列表。

    但与loop不同的是,如果为with_items提供了列表的列表,

    它们将被扁平化为单级列表。循环变量item保存每次迭代过程中使用的列表项。

  • with_file #此关键字需要控制节点文件名列表。循环变量item在每次迭代过程中保存文件列表中相应文件的内容。
  • with_sequence #此关键字不需要列表,而是需要参数来根据数字序列生成值列表。

    循环变量item在每次迭代过程中保存生成的序列中的一个生成项的值。

    playbook中的with_items的示例如下所示:

vars:
  data:
    - user0
    - user1
    - user2
tasks:
  - name: "with_items"
    debug:
      msg: "{{ item }}"
    with_items: "{{ data }}"
           

继续阅读