Ansible Playbook原理与实践(Principles and Practice of Ansible Playbook)

news2024/12/29 10:49:34

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。

本人主要分享计算机核心技术:系统维护、数据库、网络安全、自动化运维、容器技术、云计算、人工智能、运维开发、算法结构、物联网、JAVA 、Python、PHP、C、C++等。
不同类型针对性训练,提升逻辑思维,剑指大厂,非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。

云平台管理之Ansible Playbook 原理与实践

Ansible Playbook 简介

Ansible Playbook 是 Ansible 的核心组件之一,它允许用户以 YAML 格式编写配置文件,用于描述希望远程系统执行的一系列任务。Playbook 提供了一种方式来编排和执行这些任务,确保配置的一致性,或者简单地执行一些常见的任务。Playbook 的使用使得 Ansible 成为一个强大的配置管理工具,尤其适用于需要跨多个系统执行多个操作的情况。

Playbook 的基本原理包括:

  • ‌配置管理‌:通过 Playbook,可以定义和执行一系列任务,以管理和配置远程系统的状态。
  • ‌编排任务‌:Playbook 可以对任务进行排序和编排,确保按照正确的顺序执行任务。
  • ‌并行处理‌:通过异步执行和适当的配置,Playbook 可以实现并行处理多个任务,提高工作效率。
  • ‌权限管理‌:通过使用 become 功能,Playbook 可以以不同的用户权限执行任务,满足不同的系统需求。

实践方面,使用 Playbook 可以大大简化复杂的应用部署和配置管理过程。通过编写 Playbook,可以清晰地定义部署流程、配置变更、系统状态检查等任务,并通过 Ansible 引擎执行这些任务。Playbook 的使用不仅提高了工作效率,还减少了人为错误的可能性,使得 IT 基础设施的管理更加可靠和高效‌。

Playbooks是Ansible的配置,部署和编排语言。playbook是由一个或多个play组成的列表,play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓的task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联合起来按事先编排的机制完成某一任务。

Ansible Palybook的编写是基于YAML语言的。YAML语言,即Yet Another Markup Language,是一种能被计算机直接识别的标记语言,同时也方便人的阅读,且方便和脚本语言交互。但是,YAML的配置即为严格,在配置时必须注重空格的数量。总的来看,YAML语言特性如下:

  • 1、可读性强
  • 2、和脚本语言的交互性好
  • 3、使用实现语言的数据类型
  • 4、一致的信息模型
  • 5、易于实现
  • 6、可以基于流来处理
  • 7、可扩展性强

Ansible Playbook 组件

Ansible的Playbook有以下组件:

  • Target
    • 定义playbook的远程主机组,即控制的下游设备信息
  • Variable
    • 定义Playbook所使用的变量。
  • Task
    • 定义Playbook控制下游设备要执行的命令。
  • Handler
    • 定义在Palybook在Task执行完毕后要调用的任务。
Ansible Playbook各组件参数

Ansible的上述组件的参数如下:

Target常用参数

代码语言:javascript

hosts #定义Ansible用户控制的下游设备
remote_user #定义执行Ansible设置的用户
sudo #设置为yes时,执行任务时使用root权限
sudo_user #指定sudo的普通用户
connection #默认基于ssh链接客户端
gather_facts #获取远程主机facts基础信息
Variable常用参数
vars  #定义变量
vars_files  #指定变量文件
vars_prompt #用户交互模式自定义变量
setup #通过远程gather_facts获取的信息
Task常用参数
name #任务的名称,在Ansible运行的过程中起到提示的作用,会打印在屏幕上
action #Ansible控制下游设备的命令,通过Ansible的各个模块来进行控制
template #Ansible控制下游设备的模板
handler #定义一个调用,该调用在Handler处被定义,在所有的Task结束后被执行。

Playbook基本语法

playbook使用yaml语法格式,后缀可以是yaml,也可以是yml。

[root@localhost ~]$ vim test.yaml
---      #表示文档开始
- hosts: test       # "- "表示一个块序列的节点,注意:横杠后面有空格,可以写主机名,主机组名,多个使用逗号隔开
  remote_user: root      #指定在进行远程操作时使用root用户进行操作
  tasks:       #使用tasks关键字指明要进行操作的任务列表,之后的行都属于tasks键值对中的值。
  - name: Ping  #每个任务都以"- "开头,每个任务都有自己的名字,任务名使用name关键字进行指定
    ping:         #ansible模块
  - name: make directory test  #第二个任务使用file模块,使用file模块时,指定了path参数与state参数的值。
    file:     #ansible模块
       path: /data/test   #模块的参数
       state: directory   
    
---                             #标记文件的开始
- hosts: webservers             #指定该playbook在哪个服务器上执行
  vars:                         #表示下面是定义的变量,
    http_port: 80               #变量的形式,key: value,这里http_port是变量名,80是值
    max_clients: 200
  remote_user: root             #指定远程的用户名,这里缩进和vars保持了一致,说明变量的代码块已经结束。
  tasks:                        #下面构成playbook的tasks,每个task都有 - name: 开始,name指定该任务的名称。
  - name: ensure apache is at the latest version  #指定该任务的名称。
    yum: pkg=httpd state=latest                   #yum说明要是用的模板名称,后面指定对应的参数,这两行结合起来就相当于一个shell命令。

  - name: write the apache config file            #每个task之间可以使用空行来做区分。
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf

#需要说明的是缩进的意义和python中缩进的意义是一样,是来区分代码块的。

检测语法

[root@localhost ~]$ ansible-playbook  --syntax-check  /path/to/playbook.yaml

测试运行

[root@localhost ~]$ ansible-playbook -C /path/to/playbook.yaml

运行

[root@localhost ~]$ ansible-playbook  /path/to/playbook.yaml
示例:Playbook 创建用户
[root@localhost ~]$ vim sysuser.yml
---
- hosts: all
  remote_user: root

  tasks:
    - name: create mysql user
      user: name=mysql system=yes uid=36
    - name: create a group
      group: name=httpd system=yes
Playbook示例 安装nginx服务
[root@localhost ~]$ vim nginx.yml
- hosts: all
  remote_user: root

  tasks:
    - name: add group nginx
      user: name=nginx state=present
    - name: add user nginx
      user: name=nginx state=present group=nginx
    - name: Install Nginx
      yum: name=nginx state=present
    - name: Start Nginx
      service: name=nginx state=started enabled=yes
tags: 添加标签

可以指定某一个任务添加一个标签,添加标签以后,想执行某个动作可以做出挑选来执行,多个动作可以使用同一个标签。

示例:httpd.yml

代码语言:javascript复制

- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: Install httpd
      yum: name=httpd state=present
      tage: install 
    - name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      tags: conf
    - name: start httpd service
      tags: service
      service: name=httpd state=started enabled=yes

ansible-playbook -t install,conf httpd.yml   指定执行install,conf 两个标签
handlers
handlers和notify结合使用触发条件

Handlers 实际上就是一个触发器是task列表,这些task与前述的task并没有本质上的不同,用于当关注的资源发生变化时,才会采取一定的操作。

Notify此action可用于在每个play的最后被触发

这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作

在系统中,我们修改了服务器的配置文件,这时候就需要重启操作服务,就可以使用到handlers。配合 notify使用。

代码语言:javascript

---
- hosts: control-node
  remote_user: root
  vars:
    - pkg: httpd
    - name: template configuration file
      template: src=template.j2 dest=/etc/foo.conf  #修改了配置文件然后依次启动memcached和apache服务。
        notify:                               #使用notify来声明引用handlers。
         - restart memcached
         - restart apache
    
  handlers:                               #下面定义了两个handlers
    - name: restart memcached
      service:  name=memcached state=restarted
    - name: restart apache
      service: name=apache state=restarted

在使用handlers的过程中,有以下几点需要注意:

  • handlers只有在其所在的任务被执行时,都会被运行;
  • handlers只会在Play的末尾运行一次;如果想在一个Playbook的中间运行handlers,则需要使用meta模块来实现,例如:- meta: flush_handlers。
  • 如果一个Play在运行到调用handlers的语句之前失败了,那么这个handlers将不会被执行。我们可以使用mega模块的–force-handlers选项来强制执行handlers,即使在handlers所在Play中途运行失败也能执行。
register 和when

register 用于注册一个变量,保存命令的结果(shell或command模块),这个变量可以在后面的task、when语句或模板文件中使用。

代码语言:javascript

- shell: /bin/pwd
  register: pwd_result
debug:
    #msg: "{{ pwd_result }}"   # 输出全部信息
    #msg: "{{ pwd_result.cmd }}"   # 引用方式一
    msg: "{{ pwd_result['stdout_lines'] }}"  # 引用方式二

when 相当于shell脚本里的if 判断,when语句就是用来实现这个功能的,它是一个jinja2的语法,但是不需要双大括号,用法很简单。

- name: echo date  #执行了一个 date 命令,register 关键字将 date 命令的输出存储到 date_output 变量名
  command: date 
  register: date_output 

 - name: echo date_output   #用 when 对关键字对分析后的进行判断,如果匹配,则执行这个 task,不匹配就不执行
   command: echo "30"
   when: date_output.stdout.split(' ')[2] == "30"

这里第 1 个 task 是执行了一个 date 命令,register 关键字将 date 命令的输出存储到 date_output 变量名。第 2 个 task 对输出进行分析,并使用 when 对关键字对分析后的进行判断,如果匹配,则执行这个 task,不匹配就不执行。这里要重点说下的,因为 register 获取到的输出内容都是字符串,而 ansible 又是 python 写的,你可以使用 python 字符串的方法对其做处理,比如本文中使用的 split,还可以使用 find 方法。

示例
tasks:
  - name: "shutdown RedHat flavored systems"
    shell: /sbin/shutdown -h now
    when: ansible_os_family == "RedHat"  #当系统属于红帽系列,执行shell模块
循环

标准循环关键字:”with_items” ,对迭代项的引用,固定变量名为"item”,使用with_item属性给定要迭代的元素。

[root@localhost ~]$ cat xh.yml 
---
- hosts: all
  gather_facts: no
  tasks:
    - name: dispaly list
      debug: msg="{{item}}"
      with_items:
        - one
        - two
        - three
        - four
[root@localhost ~]$ ansible-playbook -i hosts xh.yml 
 
PLAY [all] *************************************************************************************************************
TASK [dispaly xunhuan] *************************************************************************************************
ok: [192.168.52.129] => (item=one) => {
    "changed": false, 
    "item": "one", 
    "msg": "one"
}
ok: [192.168.52.129] => (item=two) => {
    "changed": false, 
    "item": "two", 
    "msg": "two"
}
ok: [192.168.52.129] => (item=three) => {
    "changed": false, 
    "item": "three", 
    "msg": "three"
}
ok: [192.168.52.129] => (item=four) => {
    "changed": false, 
    "item": "four", 
    "msg": "four"
}

安装一堆软件包。

---
    - hosts: localhost
      tasks: 
        - yum: name="{{item}}" state=installed
          with_items: 
            - pkg1
            - pkg2
            - pkg3

它会一个一个迭代到特殊变量"{{item}}"处。

loop等价于with_list,从名字上可以知道它是遍历数组(列表)的,所以在loop指令中,每个元素都以列表的方式去定义。列表有多少个元素,就循环执行file模块多少次,每轮循环中,都会将本次迭代的列表元素保存在控制变量 item中。

安装多个软件

tasks:
  - name: "Install Packages"
    yum: name={{ item }}  state=latest
    loop:
      - httpd
      - mysql-server
      - php
模板templates

Jinja2语言,使用字面量,有下面形式

字符串:使用单引号或双引号
数字:整数,浮点数
列表:[item1, item2, …]
元组:(item1, item2, …)
字典:{key1:value1, key2:value2, …}
布尔型:true/false
算术运算:+, -, *, /, //, %, **
比较操作:==, !=, >, >=, <, <=
逻辑运算:and,or,not
流表达式:For,If,When
template 的使用

templates是ansible的一个模块,其功能是根据模板文件动态生成配置文件,templates文件必须存放于templates目录下,且命名为".j2"结尾,yaml/yml文件需要和templates目录平级,这样我们在yml文件中调用模板的时候,就不需要写模板文件的路径,否则需要描述模板文件的路径,因为template模块会自动去找templates目录下的模板文件.

./  
├── temnginx.yml  
└── templates  
└── nginx.conf.j2
template示例

示例:利用template 同步nginx配置文件,准备templates/nginx.conf.j2文件。

vim temnginx.yml
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

ansible-playbook temnginx.yml

for循环使用

{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
}
{% endfor %}

if单分支选择使用

{% if vhost.server_name is defined %}
    server_name {{ vhost.server_name }}
{% endif %}

if多分支选择使用

{%if vhost.port is undefined %}
    http_port=80
{%elif vhost.port == 81%}
    http_port=81
{%else%}
    http_port = 83
{%endif%}

单行注释

{#% for i in list %#}
roles
Roles介绍

ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令引入即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷的include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。主要使用场景代码复用度较高的情况下。

Roles目录结构

各目录含义解释

roles:          <--所有的角色必须放在roles目录下,这个目录可以自定义位置,默认的位置在/etc/ansible/roles
  project:      <---具体的角色项目名称,比如nginx、tomcat、php
    files:     <--用来存放由copy模块或script模块调用的文件。
    templates: <--用来存放jinjia2模板,template模块会自动在此目录中寻找jinjia2模板文件。
    tasks:     <--此目录应当包含一个main.yml文件,用于定义此角色的任务列表,此文件可以使用include包含其它的位于此目录的task文件。
      main.yml
    handlers:  <--此目录应当包含一个main.yml文件,用于定义此角色中触发条件时执行的动作。
      main.yml
    vars:      <--此目录应当包含一个main.yml文件,用于定义此角色用到的变量。
      main.yml
    defaults:  <--此目录应当包含一个main.yml文件,用于为当前角色设定默认变量。
      main.yml
    meta:      <--此目录应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系。
      main.yml

roles/example_role/files/           #所有文件,都将可存放在这里
roles/example_role/templates/       #所有模板都存放在这里
roles/example_role/tasks/main.yml   #主函数,包括在其中的所有任务将被执行
roles/example_role/handlers/main.yml  #所有包括其中的 handlers 将被执行
roles/example_role/vars/main.yml    #所有包括在其中的变量将在roles中生效
roles/example_role/meta/main.yml    #roles所有依赖将被正常登入
Roles示例

通过ansible roles安装配置httpd服务,此处的roles使用默认的路径/etc/ansible/roles

#在ansible目录下面,建立roles目录
#修改配置文件,使系统能够读取roles目录
[root@ansible ~]$ cat /etc/ansible/ansible.cfg | grep roles
# additional paths to search for roles in, colon separated
#roles_path    = /etc/ansible/roles  #roles默认路径
# by default, variables from roles will be visible in the global variable

创建role的步骤:

  • (1) 创建以roles命名的目录。
  • (2) 在roles目录中分别创建以各角色名称命名的目录,如webservers等。
  • (3) 在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建 。
  • (4) 在playbook文件中,调用各角色。

实验: 创建httpd角色

#创建roles目录
mkdir roles/{httpd,mysql,redis}/tasks -pv
mkdir  roles/httpd/{handlers,files}
#查看目录结构
tree roles/
    roles/
    ├── httpd
    │   ├── files
    │   ├── handlers
    │   └── tasks
    ├── mysql
    │   └── tasks
    └── redis
        └── tasks
#创建目标文件
cd roles/httpd/tasks/
touch install.yml config.yml service.yml
#vim install.yml
   - name: install httpd package
     yum: name=httpd
     
   vim config.yml
   - name: config file  
     copy: src=httpd.conf dest=/etc/httpd/conf/ backup=yes 
   
   vim service.yml
   - name: start service 
     service: name=httpd state=started enabled=yes
     
#创建main.yml主控文件,调用以上单独的yml文件,
   main.yml定义了谁先执行谁后执行的顺序
   vim main.yml
   - include: install.yml
   - include: config.yml
   - include: service.yml
   
#准备httpd.conf文件,放到httpd单独的文件目录下
   cp /app/ansible/flies/httpd.conf ../files/
   
#创建一个网页
   vim flies/index.html
   <h1> welcome to weixiaodong home <\h1>

#创建网页的yml文件
   vim tasks/index.yml
   - name: index.html
     copy: src=index.html dest=/var/www/html 

#将网页的yml文件写进mian.yml文件中
   vim mian.yml
   - include: install.yml
   - include: config.yml
   - include: index.yml
   - include: service.yml
   
#在handlers目录下创建handler文件mian.yml
vim handlers/main.yml
- name: restart service httpd
  service: name=httpd state=restarted

#创建文件调用httpd角色
cd /app/ansidle/roles
vim role_httpd.yml
---
# httpd role
- hosts: appsrvs
  remote_user: root 
  roles:       #调用角色
    - role: httpd  
    
#查看目录结构
tree 
.
httpd
├── files
│   ├── httpd.conf
│   └── index.html
├── handlers
│   └── main.yml
└── tasks
    ├── config.yml
    ├── index.yml
    ├── install.yml
    ├── main.yml
        └── service.yml

ansible-playbook role_httpd.yml

创建目录

[root@ansible ~]$ cd /etc/ansible/roles/
# 创建需要用到的目录
[root@ansible roles]$ mkdir -p httpd/{handlers,tasks,templates,vars}
[root@ansible roles]$ cd httpd/
[root@ansible httpd]$ tree .
.
├── handlers
├── tasks
├── templates
└── vars

4 directories, 0 file

变量文件准备vars/main.yml

[root@ansible httpd]$ vim vars/main.yml
PORT: 8088        #指定httpd监听的端口
USERNAME: www     #指定httpd运行用户
GROUPNAME: www    #指定httpd运行组

配置文件模板准备templates/httpd.conf.j2

# copy一个本地的配置文件放在templates/下并已j2为后缀
[root@ansible httpd]$ cp /etc/httpd/conf/httpd.conf templates/httpd.conf.j2

# 进行一些修改,调用上面定义的变量
[root@ansible httpd]$ vim templates/httpd.conf.j2
Listen {{ PORT }} 
User {{ USERNAME }}
Group {{ GROUPNAME }}

任务剧本编写,创建用户、创建组、安装软件、配置、启动等

# 创建组的task
[root@ansible httpd]$ vim tasks/group.yml
- name: Create a Startup Group
  group: name=www gid=60 system=yes

# 创建用户的task
[root@ansible httpd]$ vim tasks/user.yml
- name: Create Startup Users
  user: name=www uid=60 system=yes shell=/sbin/nologin

# 安装软件的task
[root@ansible httpd]$ vim tasks/install.yml
- name: Install Package Httpd
  yum: name=httpd state=installed

# 配置软件的task
[root@ansible httpd]$ vim tasks/config.yml
- name: Copy Httpd Template File
  template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
  notify: Restart Httpd

# 启动软件的task
[root@ansible httpd]$ vim tasks/start.yml
- name: Start Httpd Service
  service: name=httpd state=started enabled=yes

# 编写main.yml,将上面的这些task引入进来
[root@ansible httpd]$ vim tasks/main.yml
- include: group.yml
- include: user.yml
- include: install.yml
- include: config.yml
- include: start.ym

编写重启httpd的handlers,handlers/main.yml

[root@ansible httpd]$ vim handlers/main.yml
# 这里的名字需要和task中的notify保持一致
- name: Restart Httpd
  service: name=httpd state=restarted

编写主的httpd_roles.yml文件调用httpd角色

[root@ansible httpd]$ cd ..
[root@ansible roles]$ vim httpd_roles.yml
---
- hosts: all
  remote_user: root
  roles:
    - role: httpd        #指定角色名称

整体的一个目录结构查看

[root@ansible roles]$ tree .
.
├── httpd
│   ├── handlers
│   │   └── main.yml
│   ├── tasks
│   │   ├── config.yml
│   │   ├── group.yml
│   │   ├── install.yml
│   │   ├── main.yml
│   │   ├── start.yml
│   │   └── user.yml
│   ├── templates
│   │   └── httpd.conf.j2
│   └── vars
│       └── main.yml
└── httpd_roles.yml

5 directories, 10 files

测试playbook语法是否正确

[root@ansible roles]$ ansible-playbook -C httpd_roles.ym

上面的测试没有问题,正式执行playbook

[root@ansible roles]$ ansible-playbook httpd_roles.ym

Ansible性能调优

相比于其他的自动化配置工具,Ansible的一个突出特性就是它是基于SSH链接对下游设备进行控制的,这样做的突出好处就是方便,下游设备不需要安装客户端软件。但是这也不可避免的带来一个问题,即Ansible的执行速度较慢。并且,随着Ansible控制设备的增多,Ansible的执行速度会越来越慢。

关于Ansible执行速度的问题,尽管是Ansible的硬伤,但是我们还是可以对其进行部分的优化,尽量的加快Ansible的执行速度。对Ansible的优化可以有两个思路,一个是优化SSH链接,使得SSH的传输速度变快。

另一个如下图所示:

每次Ansible Playbook在执行时,都会收集下游设备的信息,这个过程通常要耗费较长的时间。因此,我们可以考虑使用Redis对这些信息进行缓存,从而加快收集信息的速度,如果业务环境允许,我们也可以直接控制Ansible设备跳过该步骤。

Ansible SSH链接调优
SSH关闭密钥检测

在默认情况下,以SSH登录远程设备时,该设备会检查远程主机的公钥,并且将该公钥记录在~/.ssh/known_hosts文件中,当下次该主机访问时,OpenSSH会核对公钥。如果公钥不同,则OpenSSH会发出警告,如果公钥相同,则OpenSSH则会提示输入密码。

SSH对主机公钥的检查是根据StrictHostKeyChecking变量来设定的,StrictHostKeyChecking的检查级别包括:no(不检查),ask(是否检查要询问),yes(每次都检查),False(关闭检查)。

我们可以在Ansible的配置文件中defaults模块下加入如下代码:

host_key_checking = False

加入后,配置文件如下所示:

这样,Ansible就可以关闭密钥检测了。

OpenSSH链接优化

在使用OpenSSH服务时,默认情况下服务器端会根据客户端的IP地址进行DNS反向解析,得到客户端的主机名,然后根据获取到的主机名再次进行DNS查询得到IP地址,比较这两个IP地址是否一样。这样做可以在一定程度上提高安全性,但是却会浪费时间,因此,我们可以通过关闭这一特性,来实现加速SSH链接速度的目的。 关闭该特新需要进入到/etc/ssh/sshd_config目录下,找到UseDNS的参数,将其修改为no,修改后的配置文件如下所示:

之后,重启SSHD服务即可生效。

SSH pipelining链接加速

SSH的pipelining是另一个加速Ansible执行速度的方法。在Ansible的设置中,SSH的pipelining功能时默认关闭的,这是为了兼容不同的sudo配置,主要是requieretty选项。因此,如果我们不需要在Ansible的控制中使用sudo选项,可以关闭这一选项以加快SSH链接速度。

如果要关闭这一项,可以打开Ansible的配置文件/etc/ansible/ansbile.cfg,将pipelining = False改为True即可,修改后的配置文件如下所示:

Ansible Facts调优
关闭Gather Facts

为了减少Ansible在收集客户端信息时的时间,我们首先想到的就是直接删除这一选项。要删除这一步骤,我们可以在palybook文件中添加一行:

gather_facts: no

添加后的Playbook文件如下所示:

这样,我们在执行该Playbook时,就不会再次进行gather_facts的步骤了,结果如下所示:

将Facts信息存入Redis缓存

除了删除这一步之外,我们还可以考虑将客户端信息写入内存,以加快信息查询。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2185866.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

环绕航线规划软件,适配大疆御3e、M300/350适用大疆机型: 经纬M300 rtk、M350rtk、御3e等行业机,能支持kml,㎞z导入。

环绕航线规划软件,适配大疆御3e、M300/350 适用大疆机型: 经纬M300 rtk、M350rtk、御3e等行业机,能支持kml,㎞z导入。 环绕航线规划软件介绍 名称 环绕航线规划软件 (Orbit Flight Planning Software) 适用机型 大疆经纬 M300 RTK大疆经纬 M350 RTK大疆御 3E 行业机功能特…

【技术详解】SpringMVC框架全面解析:从入门到精通(SpringMVC)

文章目录 【技术详解】SpringMVC框架全面解析&#xff1a;从入门到精通(SpringMVC)SpringMVC概述1. 三层架构与MVC架构区别1.1 三层架构1.2 MVC架构1.3前后端分离开发模式 2. SpringMVC环境搭建2.1 注解启动方式2.2 xml启动方式2.3 SpringMVC PostMan工具使用 3. SpringMVC 请求…

electron出现乱码和使用cmd出现乱码

第一种出现乱码。这种可以通过chcp 65001&#xff0c;设置为utf-8的编码。第二种&#xff0c;是执行exec的时候出现乱码&#xff0c;这个时候需要设置一些编码格式&#xff0c;可以通过iconv-lite进行解决&#xff0c;这个方法是node自带的&#xff0c;所以不需要导入。使用方法…

scrapy爬取汽车、车评数据【上】

这个爬虫我想分三期来写&#xff1a; ✅ 第一期写如何爬取汽车的车型信息&#xff1b; ✅ 第二期写如何爬取汽车的车评&#xff1b; ✅ 第三期写如何对车评嵌入情感分析结果&#xff0c;以及用简单的方法把数据插入mysql中&#xff1b; 技术基于scrapy框架、BERT语言模型、mysq…

【springboot】整合沙箱支付

目录 1. 配置沙箱应用环境2. 配置springboot项目1. 引入依赖2. 配置文件注册下载ngrok 3. 创建支付宝支付服务类4. 支付界面模板5. 控制类实现支付6. 测试 1. 配置沙箱应用环境 使用支付宝账号登录到开放平台控制台。 使用支付宝登录后&#xff0c;看到以下页面&#xff0c;下…

2、.Net 前端框架:OpenAuth.Net - .Net宣传系列文章

OpenAuth.Net 是一个开源的身份验证框架&#xff0c;由开发者 Yubaolee 创建&#xff0c;它旨在简化 Web 应用和服务的安全授权过程。这个框架以其强大的功能和易用性&#xff0c;为开发人员提供了一种高效的方式来处理用户认证和授权问题。 OpenAuth.Net 的关键特性包括&#…

无头双向不循环链表的模拟

总共由四部分组成&#xff0c;一个拥有总体方法名参数 的接口、一个异常类、一个方法类、一个测试类 先看我们写入的接口 public interface ILinkList {// 2、无头双向链表实现//头插法void addFirst(int val);//尾插法void addLast(int val);//任意位置插入,第一个数据节点为…

广联达 Linkworks办公OA Service.asmx接口存在信息泄露漏洞

漏洞描述 广联达科技股份有限公司以建设工程领域专业应用为核心基础支撑&#xff0c;提供一百余款基于“端云大数据”产品/服务&#xff0c;提供产业大数据、产业新金融等增值服务的数字建筑平台服务商。广联达OA存在信息泄露漏洞&#xff0c;由于某些接口没有鉴权&#xff0c…

Unity Input System自动生成配置

参考视频 创建及配置新输入系统 New Input System&#xff5c;Unity2022.2 最新教程《勇士传说》入门到进阶&#xff5c;4K_哔哩哔哩_bilibili ProjectSettings设置 Unity编辑器菜单栏选择Edit->Project Settings->Player->Other Settings,将Api Compatibility Level…

Ascend C 算子运行资源管理简介

Ascend C 算子运行资源管理简介 在 Ascend C 平台上开发深度学习应用时&#xff0c;运行资源的管理是一个核心知识点。通过合理管理算子执行中的计算资源&#xff0c;能够有效提升模型的执行效率和硬件利用率。本文将简要介绍 Ascend C 算子运行时的资源管理。 1. AscendCL 初…

draw.io创建自定义形状

Create custom shapes in draw.io using the text editor Reference draw怎么创建和编辑复杂的自定义形状 https://blog.csdn.net/u012028275/article/details/113828875 Create custom shapes in draw.io using the text editor

AMD发布首个AI小语言模型:6900亿token、推测解码提速3.88倍

AMD发布了自己的首个小语言模型(SLM)&#xff0c;名为“AMD-135M”。相比于越来越庞大的大语言模型(LLM)&#xff0c;它体积小巧&#xff0c;更加灵活&#xff0c;更有针对性&#xff0c;非常适合私密性、专业性很强的企业部署。 AMD-135小模型隶属于Llama家族&#xff0c;有两…

5分钟学会SPI

SPI 定义&#xff1a;SPI 是一种机制&#xff0c;允许用户在不修改现有代码的情况下扩展和替换特定服务的实现。它定义了一组接口&#xff08;Service Interfaces&#xff09;和一组实现&#xff08;Service Providers&#xff09;&#xff0c;使得应用程序可以动态加载和使用…

netty之Netty与SpringBoot整合

前言 在实际的开发中&#xff0c;我们需要对netty服务进行更多的操作&#xff0c;包括&#xff1b;获取它的状态信息、启动/停止、对客户端用户强制下线等等&#xff0c;为此我们需要把netty服务加入到web系统中。 MyChannelInitializer public class MyChannelInitializer ex…

[C++]使用C++部署yolov11目标检测的tensorrt模型支持图片视频推理windows测试通过

官方框架&#xff1a; https://github.com/ultralytics/ultralytics yolov8官方最近推出yolov11框架&#xff0c;标志着目标检测又多了一个检测利器&#xff0c;于是尝试在windows下部署yolov11的tensorrt模型&#xff0c;并最终成功。 重要说明&#xff1a;安装环境视为最基…

边缘自适应粒子滤波(Edge-Adaptive Particle Filter)的MATLAB函数示例,以及相应的讲解

目录 讲解 初始化 预测步骤 观测模拟 权重更新 重采样 状态估计 总结 下面是一个简单的边缘自适应粒子滤波&#xff08;&#xff09;的函数示例&#xff0c;以及相应的讲解。 程序源代码&#xff1a; function X_est edgeAdaptiveParticleFilter(numParticles, numS…

awd基础学习

一、常用防御手段 1、改ssh密码 passwd [user] 2、改数据库密码 进入数据库 mysql -uroot -proot 改密码 update mysql.user set passwordpassword(新密码) where userroot; 查看用户信息密码 select host,user,password from mysql.user; 改配置文件 &#xff08;否则会宕机…

笔记整理—linux进程部分(6)进程间通信、alarm和pause

两个进程间通信可能是任何两个进程间的通信&#xff08;IPC&#xff09;。同一个进程是在同一块地址空间中的&#xff0c;在不同的函数与文件以变量进程传递&#xff0c;也可通过形参传递。2个不同进程处于不同的地址空间&#xff0c;要互相通信有难度&#xff08;内存隔离的原…

2024-09-27 buildroot C和语言将 中文的GBK编码转换为 UTF-8 的代码, printf 显示出来,使用 iconv 库去实现。

一、GBK 的英文全称是 "Guobiao Kuozhan"&#xff0c;意为 "National Standard Extended"。它是对 GB2312 编码的扩展&#xff0c;用于表示更多汉字和符号 GBK&#xff08;国标扩展汉字编码&#xff09;是一种用于简体中文和繁体中文字符的编码方式&#x…

计算机毕业设计Python+Spark知识图谱酒店推荐系统 酒店价格预测系统 酒店可视化 酒店爬虫 酒店大数据 neo4j知识图谱 深度学习 机器学习

《PythonSpark知识图谱酒店推荐系统》开题报告 一、研究背景与意义 随着互联网技术的飞速发展和人们生活水平的提高&#xff0c;旅游和酒店行业迎来了前所未有的发展机遇。然而&#xff0c;面对海量的酒店信息和多样化的用户需求&#xff0c;如何快速、准确地为用户推荐符合其…