Ansible 进阶 (2) playbook Var

1 基本语法

执行 deploy.yml

ansible-playbook deploy.yml

查看输出的细节

[root@controller ~]# ansible-playbook test.yml --verbose
Using /etc/ansible/ansible.cfg as config file

PLAY [test content] *******************************************************************************************************************************************************************************************

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

TASK [add content] ********************************************************************************************************************************************************************************************
changed: [192.168.143.192] => {"changed": true, "cmd": "echo \"Im awcloud\" >>  /tmp/playbooktest.txt", "delta": "0:00:00.003959", "end": "2022-04-08 11:44:55.482102", "rc": 0, "start": "2022-04-08 11:44:55.478143", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}

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

查看该脚本影响哪些hosts

[root@controller ~]# ansible-playbook test.yml --list-hosts

playbook: test.yml

  play #1 (web1): test content  TAGS: []
    pattern: ['web1']
    hosts (1):
      192.168.143.192
[root@controller ~]#

并行执行脚本

[root@controller ~]# ansible-playbook test.yml -f 10

PLAY [test content] *******************************************************************************************************************************************************************************************

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

TASK [add content] ********************************************************************************************************************************************************************************************
changed: [192.168.143.192]

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

2 基本结构

1.在什么机器上以什么身份执行
hosts
users
…

2.执行的任务是都有什么
tasks

3.善后的任务都有什么
handlers

例:

---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  user: root
  tasks:
  - name: ensure apache is at the latest version
    yum: pkg=httpd state=latest
  - name: write the apache config file
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running
    service: name=httpd state=started
  handlers:
    - name: restart apache
      service: name=httpd state=restarted

2.1 Tasks

tasks是从上到下顺序执行,如果中间发生错误,那么整个playbook会中止。修改文件后,再重新执行。

每一个task的对module的一次调用。使用不同的参数和变量而已。

每一个task最好有name属性,这个是供人读的,没有实际的操作。然后会在命令行里面输出,提示用户执行情况。
  1. 基本写法:
tasks:
  - name: make sure apache is running
    service: name=httpd state=running

当需要传入参数列表太长时,可以分隔到多行:

 tasks:
  - name: Copy ansible inventory file to client
    copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
            owner=root group=root mode=0644

或者用yml的字典传入参数

 tasks:
  - name: Copy ansible inventory file to client
    copy:
      src: /etc/ansible/hosts
      dest: /etc/ansible/hosts
      owner: root
      group: root
      mode: 0644
  1. 执行状态
    每个action会调用一个module,在module中会去检查当前系统状态是否需要重新执行。

    如果本次执行了,那么action会得到返回值changed;

    如果不需要执行,那么action得到返回值ok

例:

tasks:
  - name: Copy the /etc/hosts
    copy: src=/etc/hosts dest=/etc/hosts
# 第一次执行
[root@controller ~]# ansible-playbook test.yml

PLAY [test content] *******************************************************************************************************************************************************************************************

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

TASK [copy file] **********************************************************************************************************************************************************************************************
changed: [192.168.143.194]

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

# 第二次执行
[root@controller ~]# ansible-playbook test.yml

PLAY [test content] *******************************************************************************************************************************************************************************************

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

TASK [copy file] **********************************************************************************************************************************************************************************************
ok: [192.168.143.194]

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

由于第一次执行copy_hosts.yml的时候,已经拷贝过文件,那么ansible目标文件的状态避免重复执行.

2.2 Handler

主流的编程语言都会有event机制,那么handler就是playbook的event。

Handlers里面的每一个handler,也是对module的一次调用。而handlers与tasks不同,tasks会默认的按定义顺序执行每一个task,handlers则不会,它需要在tasks中被调用,才有可能被执行

Tasks中的任务都是有状态的,changed或者ok。 在Ansible中,只在task的执行状态为changed的时候,才会执行该task调用的handler,这也是handler与普通的event机制不同的地方。

应用场景:

在tasks中修改了apache的配置文件。需要重起apache。此外还安装了apache的插件。那么还需要重起apache。像这样的应该场景中,重起apache就可以设计成一个handler.


一个handler最多只执行一次:在所有的任务里表执行之后执行,如果有多个task notify同一个handler,那么只执行一次。

例:

---
- hosts: lb
  remote_user: root
  vars:
      random_number1: "{{ 10000 | random }}"
      random_number2: "{{ 10000000000 | random }}"
  tasks:
  - name: Copy the /etc/hosts to /tmp/hosts.{{ random_number1 }}
    copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number1 }}
    notify:
      - call in every action
  - name: Copy the /etc/hosts to /tmp/hosts.\{\{ random_number2 \}\}
    copy: src=/etc/hosts dest=/tmp/hosts.\{\{ random_number2 \}\}
    notify:
      - call in every action

  handlers:
  - name: call in every action
    debug: msg="call in every action, but execute only one time"

输出

PLAY [test content] *******************************************************************************************************************************************************************************************

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

TASK [Copy the /etc/hosts to /tmp/hosts.7288] *****************************************************************************************************************************************************************
changed: [192.168.143.194]

TASK [Copy the /etc/hosts to /tmp/hosts.\ random_number2}}] ***************************************************************************************************************************************************
changed: [192.168.143.194]

RUNNING HANDLER [call in every action] ************************************************************************************************************************************************************************
ok: [192.168.143.194] => {
    "msg": "call in every action, but execute only one time"
}

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

3 Var

在Playbook中,通过vars关键字自定义变量,使用时用{{ }}引用以来即可。

使用方法

用户定义变量名为http_port,其值为为80。在tasks firewalld中,通过{{ http_port }}引用。

---
- hosts: web
  vars:
    http_port: 80
  remote_user: root
  tasks:
  - name: insert firewalld rule for httpd
    firewalld: port=\{\{ http_port \}\}/tcp permanent=true state=enabled immediate=yes

当变量比较多的时候,或者变量需要在多个playbook中重用的时候,可以把变量放到一个单独的文件中。通过关键字var_files把文件中定义的变量引入playbook中,使用变量的方法和在本文件中定义的变量相同。

- hosts: web
  remote_user: root
  vars_files:
      - vars/server_vars.yml
  tasks:
  - name: insert firewalld rule for httpd
    firewalld: port=\{\{ http_port \}\}/tcp permanent=true state=enabled immediate=yes

其中,vars/server_vars.yml的内容为:在这里插入代码片

http_port: 80

复杂变量

定义的语法如下

foo:
  field1: one
  field2: two

访问复杂变量中的子属性,可以利用中括号或者点号:

foo['field1']
foo.field1

陷阱:
某些时候YAML和Ansible Playbook的变量语法不能在一起好好工作了。这里仅发生在指冒号后面的值不能以{开头的时候,如果有必要以{开头,必须加上引号。总之在YAML值的定义中,如果提示YMAL语法错误,都可以尝试下加入引号来解决。

错误:

- hosts: app_servers
  vars:
      app_path: \{\{ base_path \}\}/22

修改:

- hosts: app_servers
  vars:
       app_path: "\{\{ base_path \}\}/22"

3.1 远程节点的系统变量(facts)

ansible会通过module setup来收集主机的系统信息,这些收集到的系统信息叫做facts,这些facts信息可以直接以变量的形式使用。

命令行上通过调用setup module命令可以查看可以引用的facts变量

ansible all -m setup -u root

使用方法

---
- hosts: all
  user: root
  tasks:
  - name: echo system
    shell: echo \{\{ ansible_os_family \}\}
  - name install ntp on Debian linux
    apt: name=git state=installed
    when: ansible_os_family == "Debian"
  - name install ntp on redhat linux
    yum: name=git state=present
    when: ansible_os_family == "RedHat"

3.2 文件模板中使用的变量

在playbook中定义的变量,可以直接在template中使用,同时facts变量也可以直接在template中使用,当然也包含在inventory里面定义的host和group变量。只要是在playbook中可以访问的变量,都可以在template文件中使用。

---
- hosts: web
  vars:
    http_port: 80
    defined_name: "Hello My name is Jingjng"
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum: pkg=httpd state=latest

  - name: Write the configuration file
    template: src=templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
    notify:
    - restart apache

  - name: Write the default index.html file
    template: src=templates/index2.html.j2 dest=/var/www/html/index.html

  - name: ensure apache is running
    service: name=httpd state=started
  - name: insert firewalld rule for httpd
    firewalld: port=\{\{ http_port \}\}/tcp permanent=true state=enabled immediate=yes

  handlers:
    - name: restart apache
      service: name=httpd state=restarted

3.3 命令行中传递变量

定义命令行变量

在release.yml文件里,hosts和user都定义为变量,需要从命令行传递变量值。

---

- hosts: '\{\{ hosts \}\}'
  remote_user: '\{\{ user \}\}'

  tasks:
     - ...

使用命令行变量

ansible-playbook e33_var_in_command.yml --extra-vars "hosts=web user=root"

json格式传递参数:

ansible-playbook e33_var_in_command.yml --extra-vars "{'hosts':'vm-rhel7-1', 'user':'root'}"

还可以将参数放在文件里面:

ansible-playbook e33_var_in_command.yml --extra-vars "@vars.json"
<think>好的,用户的问题是关于如何在Ansible中将import_playbookvars结合使用。我需要先理解import_playbook的基本用法,以及如何在导入playbook时传递变量。 首先,根据Ansible的文档,import_playbook用于在当前的playbook中导入另一个playbook文件。这个指令通常用于组织复杂的配置,将不同的环境或角色分开。但用户提到的是如何在使用import_playbook时传递变量,这里可能需要区分导入playbook时变量的作用域问题。 接下来,我需要回忆Ansible中变量作用域的相关知识。在Ansible中,变量可以在多个层级定义,包括play级别、host级别、group级别等。当导入另一个playbook时,如果直接使用vars关键字,可能会遇到变量作用域的问题,因为import_playbook是在解析时静态导入的,变量可能需要提前定义。 然后,用户提供的引用内容中,引用[3]提到了导入playbook的顺序,但并没有直接说明如何传递变量。可能需要参考Ansible官方文档或其他可靠资料,确认如何在导入时传递变量。例如,是否可以在导入时使用vars关键字,或者需要在导入前定义变量。 此外,用户提供的引用中有提到使用ansible-playbook命令时通过命令行传递变量(引用[2]),这可能是一个相关的方法,但用户的问题更关注于在playbook内部使用import_playbook时如何传递变量。 可能的解决方案包括: 1. 在主playbook中使用vars_files导入变量文件,然后在导入的playbook中使用这些变量。 2. 在导入playbook时,通过设置host_vars或group_vars来传递变量。 3. 使用include_*模块,但注意include_playbook可能不支持动态变量传递,而import_playbook是静态的。 需要验证是否可以在import_playbook时直接传递变量。根据经验,import_playbook不支持在导入时直接添加vars参数,变量需要在被导入的playbook中定义,或者通过外部变量文件、命令行等方式传递。 因此,正确的做法可能是在主playbook中定义变量,或者使用vars_files引入变量,确保被导入的playbook可以访问这些变量。或者,在导入前通过set_fact模块设置变量,但需要确认其作用域是否覆盖导入的playbook。 最后,根据这些分析,整理出步骤清晰的回答,并生成相关问题,帮助用户进一步理解。</think>在Ansible中,`import_playbook` 用于将外部Playbook文件导入当前Playbook的执行流程。若需要将变量与导入操作结合使用,需注意以下几点: ### 1. 变量作用域 通过`vars`关键字定义的变量仅在当前Play或任务块内有效。由于`import_playbook`在 **解析阶段** 静态加载目标文件,因此 **无法直接通过`vars`参数传递变量** 到被导入的Playbook中[^3]。 ### 2. 变量传递方法 #### (1) 全局变量文件定义 在 **主Playbook** 中通过`vars_files`加载变量文件,这些变量会自动作用于所有导入的Playbook: ```yaml # main.yml - name: 主Playbook hosts: all vars_files: - vars/common.yml # 变量文件路径 - import_playbook: imported_playbook.yml ``` #### (2) 命令行传递变量 通过`ansible-playbook`命令的`-e`参数传递变量: ```bash ansible-playbook main.yml -e "ANSIBLE_VAR=somevalue" # 如引用[2] ``` 这些变量在所有Playbook中都可见。 #### (3) 被导入Playbook内部定义 在 **被导入的Playbook** 中直接声明变量: ```yaml # imported_playbook.yml - name: 被导入的Play hosts: web_servers vars: http_port: 8080 # 变量定义 tasks: - debug: msg: "Port is {{ http_port }}" ``` ### 3. 动态变量传递技巧 若需根据主Playbook逻辑动态传递变量,可采用以下模式: ```yaml # main.yml - name: 设置全局变量 hosts: localhost connection: local tasks: - set_fact: custom_var: "dynamic_value" run_once: true - import_playbook: imported_playbook.yml ``` 在`imported_playbook.yml`中通过`hostvars`引用: ```yaml # imported_playbook.yml - name: 使用动态变量 hosts: all tasks: - debug: msg: "{{ hostvars['localhost'].custom_var }}" ``` ### 验证示例 ```yaml # main.yml - hosts: localhost vars: imported_var: "Hello from main" # 主Playbook变量 tasks: - debug: msg: "{{ imported_var }}" - import_playbook: sub.yml # 导入子Playbook # sub.yml - hosts: localhost tasks: - debug: msg: "{{ imported_var }}" # 成功输出主Playbook定义的变量 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会长胖的斜杠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值