不求甚解--详解ansible-playbook中roles的用法

前言

本文将详细介绍ansible-playbook中roles的各种用法,它允许你将相关的任务、变量、处理器、文件和模板等集合在一起,以便于在不同的项目中复用

环境准备

组件版本
操作系统Ubuntu 22.04.4 LTS
ansible2.17.6

基本用法

文件结构

.
├── deploy.hosts
├── deploy.yaml
└── roles
    └── base
        └── tasks
            └── main.yaml

  • deploy.hosts作为目标机器的列表文件
    ▶ cat deploy.hosts
    10.22.11.166
    
  • deploy.yaml作为入口文件
    ▶ cat deploy.yaml
    - name: deploy
      hosts: all
      remote_user: wilson
      gather_facts: no
      vars:
        ansible_ssh_pass: '123456'
        ansible_python_interpreter: /usr/bin/python3
      roles:
        - base
    
    • name:指定作业的名字:deploy
    • hosts:all代表deploy.hosts文件中所有的机器(也可以指定机器的分类信息)
    • remote_user:目标机器的登录用户
    • gather_facts: 是否需要采集目标机器的基本数据,默认采集。脚本指定的是不采集,为了提高执行速度
    • vars.ansible_ssh_oass:目标机器登录用户的密码
    • vars.ansible_python_interpreter:目标机器python3的路径
    • roles:指定本次作业所使用的角色 base
  • roles目录作为ansible-playbook中一系列作业任务的集合,其中一个集合的名字叫做base
    • tasks中的main.yaml作为base的入口文件
      ▶ cat roles/base/tasks/main.yaml
      - name: first
        command: echo 'hello world'
      
      • base当前只有1个任务,就是登录到目标机器,执行hello world

运行

▶ ansible-playbook -i deploy.hosts deploy.yaml

PLAY [deploy] ****************************************************************************************************

TASK [base : first] **********************************************************************************************
changed: [10.22.11.166]

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

在屏幕上显示执行结果

需要改造roles/base/tasks/main.yaml

▶ cat roles/base/tasks/main.yaml
- name: first
  command: echo 'hello world'
  register: display_result
- name: display
  debug:
    msg: "{{ display_result }}"

把结果放入变量display_result,然后通过模版语言打印出来,并且是json格式的

运行:

▶ ansible-playbook -i deploy.hosts deploy.yaml

PLAY [deploy] ****************************************************************************************************

TASK [base : first] **********************************************************************************************
changed: [10.22.11.166]

TASK [base : display] ********************************************************************************************
ok: [10.22.11.166] => {
    "msg": {
        "changed": true,
        "cmd": [
            "echo",
            "hello world"
        ],
        "delta": "0:00:00.002740",
        "end": "2024-11-19 07:22:22.226036",
        "failed": false,
        "msg": "",
        "rc": 0,
        "start": "2024-11-19 07:22:22.223296",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "hello world",
        "stdout_lines": [
            "hello world"
        ]
    }
}

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

引用环境变量

将操作系统的环境变量传入,可以通过lookup来引用,比如:要使用PATH,可以通过lookup('env', 'PATH')

改造roles/base/tasks/main.yaml

▶ cat roles/base/tasks/main.yaml
- name: first
  debug:
    msg: "{{ lookup('env', 'PATH') }}"

运行:

▶ ansible-playbook -i deploy.hosts deploy.yaml

PLAY [deploy] ****************************************************************************************************

TASK [base : first] **********************************************************************************************
ok: [10.22.11.166] => {
    "msg": "/home/wilson/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin:/usr/local/go/bin:/usr/local/go/bin"
}

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

使用ansible变量

这里的ansible变量,其中一部分ansible默认的变量,一部分是ansible运行的时候,会默认去采集目标机器的基本信息,比如操作系统、cpu、内存、磁盘等等的基本信息

部分内置变量

变量名描述
inventory_hostname当前任务执行的主机名(来自 Inventory 文件)
ansible_facts包含所有收集到的主机事实(facts)
hostvars所有主机变量的集合,包含当前和其他主机

采集目标机器的基本信息

需要把之前采集ansible基本信息的开关打开gather_facts: yes,打开之后会牺牲运行速度

改造roles/base/tasks/main.yaml

- name: first
  debug:
    msg: "{{ hostvars }}"

运行:

由于数据量太大,只展示部分,并且json格式,可以直接拿想要的值

▶ ansible-playbook -i deploy.hosts deploy.yaml

PLAY [deploy] ******************************************************************

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

TASK [base : first] ************************************************************
ok: [10.22.11.166] => {
    "msg": {
        "10.22.11.166": {
            "ansible_all_ipv4_addresses": [
                "10.22.11.166"
            ],
            "ansible_all_ipv6_addresses": [
                "fe80::a00:27ff:fef6:82c4"
            ],
            "ansible_apparmor": {
                "status": "enabled"
            },
            "ansible_architecture": "x86_64",
            "ansible_bios_date": "12/01/2006",
            "ansible_bios_vendor": "innotek GmbH",
            "ansible_bios_version": "VirtualBox",
            "ansible_board_asset_tag": "NA",
            "ansible_board_name": "VirtualBox",
            "ansible_board_serial": "NA",
            "ansible_board_vendor": "Oracle Corporation",
            ...
            "inventory_dir": "/home/wilson/workspace/ansible",
            "inventory_file": "/home/wilson/workspace/ansible/deploy.hosts",
            "inventory_hostname": "10.22.11.166",
            "inventory_hostname_short": "10.22.11.166",
            "module_setup": true,
            "playbook_dir": "/home/wilson/workspace/ansible"
        }
    }
}

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

是否采集目标的基本信息

上面已经演示过,只需要gather_facts: yes即可

从命令行传入变量

ansible-playbook可以通过-e传入变量使用

▶ cat roles/base/tasks/main.yaml
- name: first
  debug:
    msg: "{{ app_name }} - {{ app_version }}"

运行:

▶ ansible-playbook -i deploy.hosts -e "app_name=prom app_version=1.0" deploy.yaml

PLAY [deploy] ****************************************************************************************************

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

TASK [base : first] **********************************************************************************************
ok: [10.22.11.166] => {
    "msg": "prom - 1.0"
}

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

动态选择host

1)将主机分组

修改deploy.hosts文件

▶ cat deploy.hosts
[ga]
10.22.11.166

[gb]
10.22.11.166
127.0.0.1

2)改造入口文件

▶ cat deploy.yaml
- name: deploy
  hosts: '{{h}}'
  remote_user: wilson
  gather_facts: no
  vars:
    ansible_ssh_pass: '123456'
    ansible_python_interpreter: /usr/bin/python3
  roles:
    - base

将hosts改在成为'{{h}}',通过传入h变量来动态定义

3)运行

指定h为ga

▶ ansible-playbook -i deploy.hosts -e "h=ga" deploy.yaml

PLAY [deploy] ****************************************************************************************************

TASK [base : first] **********************************************************************************************
ok: [10.22.11.166] => {
    "msg": "hello world"
}

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

指定h为gb

▶ ansible-playbook -i deploy.hosts -e "h=gb" deploy.yaml

PLAY [deploy] ****************************************************************************************************

TASK [base : first] **********************************************************************************************
ok: [10.22.11.166] => {
    "msg": "hello world"
}
ok: [127.0.0.1] => {
    "msg": "hello world"
}

PLAY RECAP *******************************************************************************************************
10.22.11.166               : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
127.0.0.1                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

条件选择when

▶ cat roles/base/tasks/main.yaml
- name: first
  debug:
    msg: "version 1"
  when: version == '1'

- name: second
  debug:
    msg: "version 2"
  when: version == '2'

定义临时变量

通过-e传入的变量来产生临时变量

- name: first
  set_fact:
    tag: "hello-{{ version }}"

- name: second
  debug:
    msg: "{{ tag }}"

运行:

▶ ansible-playbook -i deploy.hosts -e "version=2" deploy.yaml

...

TASK [base : second] *********************************************************************************************
ok: [10.22.11.166] => {
    "msg": "hello-2"
}

...

调用多个role

1)新增role: advance

.
├── deploy.hosts
├── deploy.yaml
└── roles
    ├── advance
    │   └── tasks
    │       └── main.yaml
    └── base
        └── tasks
            └── main.yaml

2)直接在入口文件deploy.yaml引用

.
├── deploy.hosts
├── deploy.yaml
└── roles
    ├── advance
    │   └── tasks
    │       └── main.yaml
    └── base
        └── tasks
            └── main.yaml

运行:

▶ ansible-playbook -i deploy.hosts -e "version=2" deploy.yaml

PLAY [deploy] ****************************************************************************************************

TASK [base : first] **********************************************************************************************
ok: [10.22.11.166]

TASK [base : second] *********************************************************************************************
ok: [10.22.11.166] => {
    "msg": "hello-2"
}

TASK [advance : new-first] ***************************************************************************************
ok: [10.22.11.166] => {
    "msg": "new hello world"
}

PLAY RECAP *******************************************************************************************************
10.22.11.166               : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

3)在roles base中引用 advance

▶ cat deploy.yaml
- name: deploy
  hosts: all
  remote_user: wilson
  gather_facts: no
  vars:
    ansible_ssh_pass: '123456'
    ansible_python_interpreter: /usr/bin/python3
  roles:
    - base

▶ cat roles/base/tasks/main.yaml
- name: base first
  debug:
    msg: "base {{ version }}"

- name: base second
  include_role:
    name: advance
  vars:
    role_pipe_from_base: "hello world from base"

- name: base third
  debug:
    msg: "{{ role_pipe_from_advance }}"
▶ cat roles/advance/tasks/main.yaml
- name: advance first
  debug:
    msg: "advance {{ version }}"

- name: advance second
  debug:
    msg: "{{ role_pipe_from_base }}"

- name: advance third
  set_fact:
    role_pipe_from_advance: "hello world from advance"

运行:

▶ ansible-playbook -i deploy.hosts -e "version=2" deploy.yaml

PLAY [deploy] ****************************************************************************************************

TASK [base : base first] *****************************************************************************************
ok: [10.22.11.166] => {
    "msg": "base 2"
}

TASK [base second] ***********************************************************************************************
included: advance for 10.22.11.166

TASK [advance : advance first] ***********************************************************************************
ok: [10.22.11.166] => {
    "msg": "advance 2"
}

TASK [advance : advance second] **********************************************************************************
ok: [10.22.11.166] => {
    "msg": "hello world from base"
}

TASK [advance : advance third] ***********************************************************************************
ok: [10.22.11.166]

TASK [base : base third] *****************************************************************************************
ok: [10.22.11.166] => {
    "msg": "hello world from advance"
}

PLAY RECAP *******************************************************************************************************
10.22.11.166               : ok=6    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

在这里插入图片描述

这个例子呈现了:

  • 传入变量version是共用的
  • 如何在role传递参数
  • 执行过程中定义的临时变量role_pipe_from_advance可以跨role持续
  • 多role执行是串行的

小结

  • 联系我,做深入的交流
    在这里插入图片描述

至此,本文结束
在下才疏学浅,有撒汤漏水的,请各位不吝赐教…

<think>好的,用户遇到了Ansible的错误提示:“Invalid callback for stdout specified: debug”,需要解决这个问题。首先,我得回想一下Ansible中关于回调插件的知识。回调插件用于控制任务执行结果的输出格式,用户可能在配置文件中指定了某个不正确的回调名称,或者插件本身有问题。 根据用户提供的引用内容,特别是引用[3]提到的AssertionError,说明Ansible在加载回调插件时遇到了问题,无法找到或正确加载指定的回调模块。用户提到的错误信息中的“debug”可能是指他们试图使用内置的debug回调插件,但可能配置有误。 首先,我应该检查用户是否在ansible.cfg中正确配置了stdout_callback参数。根据引用[1],正确的配置应该是在[defaults]部分设置stdout_callback,例如使用json格式。如果用户错误地设置为debug,但实际上debug可能不是一个有效的标准回调插件,或者版本不兼容。例如,在Ansible 2.5之后,debug回调插件被重命名为debug,而旧版本可能有不同的名称,或者需要启用插件。 然后,考虑用户使用的Ansible版本。引用[4]提到Ansible 1.9.6是1.x的最后一个版本,之后是2.x的重构。如果用户使用的是较旧的版本,可能需要确认回调插件名称是否正确。例如,在旧版本中,默认的回调插件可能是default,而debug可能需要通过启用插件或指定正确的名称。 另外,引用[3]的错误提示表明Ansible无法找到或加载指定的回调对象。这可能是因为插件路径配置错误,或者插件文件不存在。用户需要检查ansible.cfg中的callback_plugins路径是否正确指向包含回调插件的目录,如引用[2]提到的自定义回调路径是否正确。 接下来,可能的解决步骤包括: 1. 确认ansible.cfg中的stdout_callback设置是否正确,比如是否拼写错误,是否使用了支持的回调名称。 2. 检查Ansible版本,确认所使用的回调插件是否在该版本中有效。例如,在Ansible 2.5+中,debug插件可能需要通过启用或在配置中正确指定。 3. 确保回调插件的路径配置正确,特别是如果使用了自定义插件,如引用[2]中的例子,需要确认路径是否存在以及插件文件是否有正确的权限。 4. 如果使用的是内置插件,可能需要通过ansible-doc -t callback -l列出所有可用插件,确认是否存在debug这个名称。 5. 检查Ansible的日志或详细输出(使用-vvv参数)来获取更详细的错误信息,帮助定位问题。 例如,用户可能在配置文件中写了stdout_callback = debug,但实际上正确的名称可能是ansi或default,或者需要安装额外的插件。或者,可能用户的环境中有多个Ansible版本,导致配置文件被错误版本的Ansible读取。 此外,用户提到的错误信息中的“debug”可能是一个误导,比如用户可能想启用调试输出,但错误地配置了回调插件。正确的做法可能是使用-vvv参数运行命令,而不是修改回调插件。 总结可能的解决方案: - 修改ansible.cfg中的stdout_callback为正确的值,如json、yaml、default等。 - 确保Ansible版本与配置的回调插件兼容。 - 检查回调插件的安装和路径配置。 - 通过详细日志进一步诊断问题。 需要将这些步骤以清晰的方式呈现给用户,并给出具体的配置示例和命令,帮助他们逐步排查问题。</think>### 解决Ansible的'Invalid callback for stdout specified: debug'错误 当Ansible运行时出现`ERROR! Invalid callback for stdout specified: debug`错误,通常是由于回调插件配置错误或版本兼容性问题导致。以下是具体解决步骤: --- #### 1. **检查`ansible.cfg`中的回调配置** 在Ansible配置文件(`ansible.cfg`)中,`stdout_callback`参数需指向有效的回调插件名称。 - **错误示例**: ```ini [defaults] stdout_callback = debug # 旧版本可能不支持此名称 ``` - **正确示例**: ```ini [defaults] stdout_callback = json # 使用JSON格式输出(Ansible内置支持) # 或 stdout_callback = yaml # 使用YAML格式输出 # 或 stdout_callback = default # 默认输出格式 ``` > **注意**:`debug`在Ansible 2.5+中已被重命名或移除,需确认版本兼容性[^1][^3]。 --- #### 2. **验证Ansible版本与插件兼容性** - 运行`ansible --version`查看版本: - **Ansible 1.x**:最后一个版本是1.9.6,仅支持有限回调插件(如`default`)[^4]。 - **Ansible 2.x+**:需使用新插件名称(如`debug`需替换为`debug_meta`或`json`)。 - **列出可用回调插件**: ```bash ansible-doc -t callback -l # 查看所有支持的回调插件 ``` --- #### 3. **检查回调插件路径配置** 若使用**自定义回调插件**(如引用[2]中的`/opt/ansible_admin/callback`): 1. 确认`ansible.cfg`中配置了插件路径: ```ini [defaults] callback_plugins = /opt/ansible_admin/callback ``` 2. 确保插件文件存在且符合Ansible规范: - 文件名需以`.py`结尾(如`custom_debug.py`)。 - 文件需定义`CallbackModule`类并继承`CallbackBase`。 --- #### 4. **启用插件并调试** - **启用调试模式**运行Playbook: ```bash ansible-playbook playbook.yml -vvv # 输出详细日志 ``` - **常见错误场景**: - 插件文件权限不足 → 执行`chmod +x /path/to/plugin.py`。 - 插件代码语法错误 → 检查Python语法。 --- #### 5. **临时解决方案** 若需快速绕过错误,可**重置为默认输出**: ```ini [defaults] stdout_callback = default ``` --- ### 总结 此错误的核心原因包括: 1. 回调插件名称拼写错误或版本不兼容。 2. 自定义回调插件路径配置错误或代码缺陷。 3. Ansible版本过旧(如1.x)不支持新插件。 通过调整配置、更新插件或升级Ansible版本即可解决[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值