ansible管理机密,事实以及简单循环

  • ansible 管理机密
  • Ansible Vault
  • 创建加密文件
  • 利用文件解密
  • playbook和ansible vault
  • 管理事实
  • 关闭事实收集
  • 创建自定义事实
  • 魔法变量
  • 简单循环
  • 循环散列或字典列表
  • 较早样式的循环关键字
  • 将Register变量与Loop一起使用


ansible 管理机密

Ansible Vault

Ansible可能需要访问密码或API密钥等敏感数据,以便能配置受管主机。通常,此信息可能以纯文本形式存储在清单变量或其他Ansible文件中。这存在在安全风险。

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

创建加密文件

[root@localhost project]# ansible-vault create  passwd
New Vault password: 
Confirm New Vault password:

cat查看不了

[root@localhost project]# cat passwd 
$ANSIBLE_VAULT;1.1;AES256
32353537316262353837323935643539303361656164353139313430343635336237323262336362
3566303565636337653435626330616530353235366630620a613161666539336435666266383766
31633537656531336532343265323535363435306635376564376331356231386434393833623633
3537353865646263610a613636396638396564363061343464316430373762633534386634613535
3833
[root@localhost project]# ansible-vault view  passwd
Vault password: 
passwd: 123
view加密查看
[root@localhost project]# ansible-vault edit  passwd
Vault password: 
编辑已加密文件
[root@localhost project]# ansible-vault decrypt passwd 
Vault password: 
Decryption successful
[root@localhost project]# cat pa
packages/ passwd    
[root@localhost project]# cat passwd 
passwd: 123
解密文件
[root@localhost project]# ansible-vault encrypt playbook/apache.yml 
New Vault password: 
Confirm New Vault password: 
Encryption successful
加密已存在yml文件
[root@localhost project]# ansible-vault rekey playbook/apache.yml 
Vault password: 
New Vault password: 
Confirm New Vault password: 
Rekey successful
重新加密/改密码

利用文件解密

[root@localhost project]# cat .key
123
创建隐藏密码文件
[root@localhost project]# ansible-vault view --vault-password-file=.key  playbook/apache.yml

利用文件解密

playbook和ansible vault

要运行可访问通过Ansible Vault加密的文件的playbook,需要向ansible-playbook命令提供加密密码。

---
- name: 111
  hosts: apache
  vars_files:
    - /etc/ansible/vars/usr.yml
指定加密变量地址
[root@localhost ansible]# ansible-playbook --vault-id @prompt playbook/useradd.yml 
输入加密密码即可提取加密变量运行剧本

管理事实

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

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

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

事实

变量

短主机名

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’]

[root@localhost ansible]# ansible apache  -m  setup | less
直接从命令行获取所有事实
[root@localhost ansible]# cat ss.yml 
---
- name: kkkk
  hosts: apache
  tasks:
    - name: 122
      debug:
        var: ansible_facts['hostname']
[root@localhost ansible]# ansible-playbook ss.yml 

PLAY [kkkk] *********************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************
ok: [192.168.216.172]

TASK [debug] ********************************************************************************************************************
ok: [192.168.216.172] => {
    "ansible_facts['hostname']": "localhost"
}

PLAY RECAP **********************************************************************************************************************
192.168.216.172            : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
提取hostname ,不加hostname则获取所有事实
[root@localhost ~]# cat  123.yml
---
- name: gather_facts
  hosts: all
  gather_facts: no
  tasks:
    - name: get gather_facts
      setup:
    - name: debug
      debug:
        var: ansible_facts['ansible_local']
获取单独自定义事实
TASK [debug] ********************************************************************************************************************
ok: [192.168.216.172] => {
    "ansible_facts['ansible_local']": {
        "123": {
            "123": {
                "adqdqf": "1", 
                "qfqfq": "2"
            }
        }
    }
}

关闭事实收集

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

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

---
- name: 111
  hosts: all
  gather_facts: no

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

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

创建自定义事实

除了使用系统捕获的事实外,我们还可以自定义事实,并将其本地存储在每个受管主机上。这些事实整合到setup模块在受管主机上运行时收集的标准事实列表中。它们让受管主机能够向Ansible提供任意变量,以用于调整play的行为。
有了自定义事实,我们可以为受管主机定义特定的值,供play用于填充配置文件或有条件地运行任务。动态自定义事实允许在play运行时以编程方式确定这些事实的值,甚至还可以确定提供哪些事实。

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

[root@localhost ~]# mkdir -p /etc/ansible/facts.d
[root@localhost ~]# cd /etc/ansible/facts.d
[root@localhost facts.d]# vim 123.fact
[root@localhost facts.d]# cat 123.fact 
[pack]
web=httpd
[users]
user1=123
user2=234
不需要下载ansible,只需要创建目录
[root@localhost ansible]# ansible apache -m setup|less

"ansible_local": {
            "123": {
                "pack": {
                    "web": "httpd"
                }, 
                "users": {
                    "user1": "123", 
                    "user2": "234"

魔法变量

魔法变量

说明

hostvars

包含受管主机的变量,可以用于获取另一台受管主机的变量的值。如果还没有为受管主机收集事实,则它不会包含该主机的事实。

group_names

列出当前受管主机所属的所有组

groups

列出清单中的所有组和主机

inventory_hostname

包含清单中配置的当前受管主机的主机名称。因为各种原因有可能与事实报告的主机名称不同

https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable。更多魔法变量

[root@localhost ansible]# ansible apache -m debug -a 'var=hostvars["localhost"]'
192.168.216.172 | SUCCESS => {
    "hostvars[\"localhost\"]": {
        "ansible_check_mode": false, 
        "ansible_connection": "local", 
        "ansible_diff_mode": false, 
        "ansible_facts": {}, 
        "ansible_forks": 5, 
        "ansible_inventory_sources": [
            "/etc/ansible/hosts"

简单循环

- 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列表不需要是简单值列表,当前item循环变量中每个键的值可以分别通过item.name和item.groups变量来检索。

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

较早样式的循环关键字

循环关键字

描述

with_items

行为与简单列表的loop关键字相同,例如字符串列表或散列/字典列表。但与loop不同的是,如果为with_items提供了列表的列表,它们将被扁平化为单级列表。循环变量item保存每次迭代过程中使用的列表项。

with_file

此关键字需要控制节点文件名列表。循环变量item在每次迭代过程中保存文件列表中相应文件的内容。

with_sequence

此关键字不需要列表,而是需要参数来根据数字序列生成值列表。循环变量item在每次迭代过程中保存生成的序列中的一个生成项的值。

[root@localhost playbook]# cat vars/999.yml 
user:
  - lhj
  - hjj
  - jhk
写一个变量
[root@localhost playbook]# cat useradd.yml 
---
- name: 111
  hosts: apache
  vars_files:
    - /etc/ansible/playbook/vars/999.yml
  tasks:
    - name: "{{ item }}"
      user: 
        name: "{{ item }}"
        state: present
      loop: "{{ user }}"
直接利用变量循环
[root@localhost playbook]# ansible-playbook useradd.yml 

PLAY [111] **********************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************
ok: [192.168.216.172]

TASK [{{ item }}] ***************************************************************************************************************
changed: [192.168.216.172] => (item=lhj)
changed: [192.168.216.172] => (item=hjj)
changed: [192.168.216.172] => (item=jhk)

PLAY RECAP **********************************************************************************************************************
192.168.216.172            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

字典列表

[root@localhost playbook]# cat vars/999.yml 
user:
  - name: lhj01
    uid: 2001
  - name: jiii1
    uid: 2011
  - name: tom01
    uid: 2000
[root@localhost playbook]# cat useradd.yml 
---
- name: 111
  hosts: apache
  vars_files:
    - /etc/ansible/playbook/vars/999.yml
  tasks:
    - name: "{{ item.name }}"
      user: 
        name: "{{ item.name }}"
        uid: "{{ item.uid }}"
        state: present
      loop: "{{ user }}"
[root@localhost playbook]# ansible-playbook useradd.yml 

PLAY [111] **********************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************
ok: [192.168.216.172]

TASK [{{ item.name }}] **********************************************************************************************************
changed: [192.168.216.172] => (item={u'name': u'lhj01', u'uid': 2001})
changed: [192.168.216.172] => (item={u'name': u'jiii1', u'uid': 2011})
changed: [192.168.216.172] => (item={u'name': u'tom01', u'uid': 2000})

PLAY RECAP **********************************************************************************************************************
192.168.216.172            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

将Register变量与Loop一起使用

[root@localhost playbook]# cat usr.yml 
---
- name: task1
  gather_facts: no
  hosts: apache
  tasks:
    - name: 12131
      shell: "echo hello {{ item }} "
      loop:
        - tom
        - jerry
        - emily
      register: result
    - name: 123
      debug:
        var: result
"stdout": "hello tom", 
                "stdout_lines": [
                    "hello tom"
                ]
            }, 
            {
                "ansible_loop_var": "item", 
                "changed": true, 
                "cmd": "echo hello jerry ", 
                "delta": "0:00:00.002544", 
                "end": "2021-07-24 07:17:19.810147", 
                "failed": false, 
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo hello jerry ", 
                        "_uses_shell": true, 
                        "argv": null, 
                        "chdir": null, 
                        "creates": null, 
                        "executable": null, 
                        "removes": null, 
                        "stdin": null, 
                        "stdin_add_newline": true, 
                        "strip_empty_ends": true, 
                        "warn": true
                    }
                }, 
                "item": "jerry", 
                "rc": 0, 
                "start": "2021-07-24 07:17:19.807603", 
                "stderr": "", 
                "stderr_lines": [], 
                "stdout": "hello jerry", 
                "stdout_lines": [
                    "hello jerry"
                ]
            }, 
            {
                "ansible_loop_var": "item", 
                "changed": true, 
                "cmd": "echo hello emily ",