IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 模板管理、清单管理和并行方式 -> 正文阅读

[系统运维]模板管理、清单管理和并行方式

模板管理、清单管理和并行方式

1. 使用jinja2模块部署自定义文件

1.1 jinja2简介

1.2构建inja2模板

1.3 部署jinja2模板

1.4 管理模板文件

1.5 控制结构

1.5.1 使用循环

1.5.2 使用条件语

1.5.3 变量过滤器

2. 利用主机模式选择主机

2.1 引用清单文件

2.2 受管主机

2.3 使用组指定主机

2.4 使用通配符匹配多个主机

2.5 列表

3. 管理动态清单

3.1 动态生成清单

3.2 开源社区脚本

3.3 管理多个清单

4. 配置并行

4.1 使用分叉在ansible种配置并行

4.2 管理滚动更新


1. 使用jinja2模块部署自定义文件

1.1 jinja2简介

ansible将jinja2模板系统用于模板文件。ansible还使用jinja2语法来引用playbook中的变量

变量和逻辑表达式置于标记或分隔符之间。例如,jinja2模板将{% EXPR %}用于表达式或逻辑(如循环),而{{ EXPR }}则用于向最终用户输出表达式或变量的结果。后一标记在呈现时将被替换为一个或多个值,对最终用户可见。使用{# COMMENT #}语法括起不应出现在最终文件中的注释。

1.2构建inja2模板

jinja2模板由多个元素组成:数据、变量和表达式。在呈现jinja2模板时,这些变量和表达式被替换为对应的值。模板中使用的变量可以在playbook的vars部分中指定。可以将受管主机的事实用作模板中的变量。

使用ansible system_hostname -i inventory_file -m setup命令来获取与受管主机相关的事实。

1.3 部署jinja2模板

jinja2模板是功能强大的工具,可用于自定义要在受管主机上部署的配置文件,创建了使用于配置文件的jinja2模板后,它可以通过template模板部署到受管主机上,该模块支持将控制节点中的本地文件转移到受管主机

若要使用template模块,请使用下列语法。与src键关联的值指定来源jinja2模板,而与dest键关联的值指定要在目标主机上创建的文件。

template模块还允许指定已部署文件的所有者、组、权限和SELINUX上下文,就像file模块一样。它也可以取用validate选项运行任意命令(如visudo -c),在将文件复制到位之前检查该文件的语法是否正确。

1.4 管理模板文件

为避免系统管理员修改Ansible部署的文件,最好在模板顶部包含注释,以指示不应手动编辑该文件。

[root@yibie playbook]# cat hosts.j2 
{{ ansible_facts['hostname'] }}
{# 注释 #}
{{ ansible_facts['default_ipv4']['address'] }}
[root@yibie playbook]# cat test.yml 
---
- hosts: "*"
  tasks:
    - name: yibie
      template:      //如果使用copy模块你会发现只会把内容copy过去,不会替换里面的事实
        src: /etc/ansible/playbook/hosts.j2
        dest: /etc/hosts
[root@yibie playbook]#  ansible-playbook test.yml 

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

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

TASK [yibie] ******************************************************************************
changed: [192.168.57.30]

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

[root@yibie-apache ~]# cat /etc/hosts
yibie-apache             //看见了主机ip和主机名,如果使用copy模块会看见整个注释和模板
192.168.57.30     

1.5 控制结构

用户可以在模板文件中使用jinja2控制结构,以减少重复输入,为play中的每个主机动态输入条目,或者有条件地将文本插入到文件中。

1.5.1 使用循环

inja2使用for语句来提供循环功能。在下例中,user变量替换为users变量中包含的所有值,一行一个值。

[root@yibie vars]# cat huihui.yml 
info:   
  - hello 1
  - hello 2
  - hello 3
[root@yibie vars]# cd /etc/ansible/playbook/
[root@yibie playbook]# cat test.yml 
---
- hosts: "*"
  vars_files:
    - /etc/ansible/vars/huihui.yml
  tasks:
    - name: yibie
      template:
        src: /etc/ansible/files/test.j2
        dest: /tmp/abc
[root@yibie playbook]# cat /etc/ansible/files/test.j2 
{% for msg in info %}
 {{ msg }}
{%  endfor %}
[root@yibie playbook]#  ansible-playbook test.yml 

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

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

TASK [yibie] ******************************************************************************
changed: [192.168.57.30]

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


[root@yibie-apache ~]# cat /tmp/abc 
 hello 1
 hello 2
 hello 3
//可以在变量的后面加东西
[root@yibie playbook]# cat /etc/ansible/files/test.j2 
{% for msg in info %}
 {{ msg }}
============
{%  endfor %}
[root@yibie playbook]# ansible-playbook test.yml 

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

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

TASK [yibie] ******************************************************************************
changed: [192.168.57.30]

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

[root@yibie-apache ~]# cat /tmp/abc 
 hello 1
============
 hello 2
============
 hello 3
============

以下示例模板使用for语句逐一运行msg变量中的所有值,将msg替换为各个值,但只取hello 2的值

[root@yibie playbook]# cat /etc/ansible/files/test.j2 
{% for msg in info if msg == "hello 2" %}
 {{ msg }}
============
{%  endfor %}
[root@yibie playbook]# ansible-playbook test.yml 


[root@yibie-apache ~]# cat /tmp/abc 
 hello 2
============

值为除了hello 3的其他值

[root@yibie playbook]# cat /etc/ansible/files/test.j2 
{% for msg in info if not msg == "hello 2" %}
 {{ msg }}
============
{%  endfor %}
[root@yibie playbook]# ansible-playbook test.yml 


[root@yibie-apache ~]# cat /tmp/abc 
 hello 1
============
 hello 3
============

?另一种格式

[root@yibie ansible]# cat files/test.j2 
{% for msg in info %}
{%  if msg != "hello 3" %}
 {{ msg }}
{%  endif %}
{%  endfor %}
[root@yibie ansible]# ansible-playbook playbook/test.yml 

[root@yibie-apache ~]# cat /tmp/abc 
 hello 1
 hello 2

指定次数

[root@yibie ansible]# cat files/test.j2 
{% for msg in info %}
{%  if msg != "hello 3" %} //结果里面不会出现3,因为我们把它排除了
count {{ loop.index}} of info is {{ msg }}. //循环第几次对这个info变量循环的值是msg
{%  endif %}
{%  endfor %}
[root@yibie ansible]# ansible-playbook playbook/test.yml 
[root@yibie-apache ~]# cat /tmp/abc 
count 1 of info is hello 1. //出现次数
count 2 of info is hello 2. //第二次对info这个变量循环的是hello2

总结:

  • 不需要用{{}}引用变量的场景:
  • debug模块里面的var参数
  • playbook中用when判断条件时
  • 模块文件定义的时候{% 定义的时候%}

1.5.2 使用条件语

jinja2使用if语句来提供条件控制。如果满足某些条件,这允许用户在已部署的文件中放置一行。

[root@yibie ansible]# cat files/test.j2 
{% if "" %}
abc
{% endif %}
[root@yibie ansible]# ansible-playbook playbook/test.yml 
[root@yibie-apache ~]# cat /tmp/abc //条件不成立,abc不搞过来,没有东西,覆盖,所以为空

[root@apache ~]# 

1.5.3 变量过滤器

jinja2提供了过滤器,更改模板表达式的输出格式(例如,输出到果JSON)。有适用于YAML和JSON等语言的过滤器。to_json过滤器使用JSON格式化表达式输出,to_yaml过滤器则使用YAML格式化表达式输出。

{{ output | to_json }}
{{ output | to_yaml }}
{{ output | to_nice_json }}
{{ output | to_nice_yaml }}
{{ output | from_json }}
{{ output | from_yaml }}

列子:

[root@yibie vars]# cat huihui.yml 
info:
  - name: dong
    age: 20
  - name: hui
    age: 21
[root@yibie ansible]# cat files/test.j2 
{% if " " %} //中间是空格
{{ info }}
{% endif %}
[root@yibie ansible]# ansible-playbook playbook/test.yml 


[root@yibie-apache ~]# cat /tmp/abc 
 
[{'name': 'dong', 'age': 20}, {'name': 'hui', 'age': 21}]
[root@yibie files]# cat test.j2 
{% if " " %}
{{ info | to_nice_json }}
{% endif %}
[root@yibie files]# cd /etc/ansible/
[root@yibie ansible]# ansible-playbook playbook/test.yml 


[root@yibie-apache ~]# cat /tmp/abc 
 
[{'name': 'dong', 'age': 20}, {'name': 'hui', 'age': 21}]
[root@yibie-apache ~]# cat /tmp/abc 
[
    {
        "age": 20,
        "name": "dong"
    },
    {
        "age": 21,
        "name": "hui"
    }
]

2. 利用主机模式选择主机

2.1 引用清单文件

主机模式用于指定要作为play或临时命令的目标的主机。在最简单的形式中,清单中受管主机或主机组的名称就是指定该主机或主机组的主机模式。

在play中,hosts指定要针对其运行play的受管主机。对于临时命令,以命令行参数形式将主机模式提供给ansible命令。

本段中将通篇使用以下示例清单来演示主机模式。

[root@localhost ~]# cat myinventory 
web.example.com
data.example.com

[lab]
labhost1.example.com
labhost2.example.com

[test]
test1.example.com
test2.example.com

[datacenter1]
labhost1.example.com
test1.example.com

[datacenter2]
labhost2.example.com
test2.example.com

[datacenter:children]
datacenter1
datacenter2

[new]
172.16.103.129
172.16.103.130

2.2 受管主机

最基本的主机模式是单一受管主机名称列在清单中。这将指定该主机是清单中ansible命令要执行操作的唯一主机。

通过IP地址引用受管主机存在一个问题,那就是难以记住play或临时命令所针对的主机使用了哪个IP地址。但是,如果没有可解析的主机名,我们可能必须按IP地址指定主机以进行连接。
第一种方式受管的IP:

[root@localhost ~]# vim inventory
---
- hosts: 192.168.57.30

第二种方式主机名:

[root@yibie playbook]# cat hosts.j2 
yibie-apache
192.168.57.30
[root@yibie ansible]# cat playbook/hosts.j2 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
yibie-apache
192.168.57.30
[root@yibie ansible]# ping 192.168.57.30
PING 192.168.57.30 (192.168.57.30) 56(84) bytes of data.
64 bytes from 192.168.57.30: icmp_seq=1 ttl=64 time=0.518 ms
64 bytes from 192.168.57.30: icmp_seq=2 ttl=64 time=2.36 ms
64 bytes from 192.168.57.30: icmp_seq=3 ttl=64 time=1.59 ms

2.3 使用组指定主机

当组名称用作主机模式时,它指定Ansible将对属于该组的成员的主机执行操作。

---
- hosts: lab

记住,有一个名为all的特别组,它匹配清单中的所有受管主机

---
- hosts: all

还有一个名为ungrouped的特别组,它包括清单中不属于任何其他组的所有受管主机:

---
- hosts: ungrouped

2.4 使用通配符匹配多个主机

若要达成与all主机模式相同的目标,另一种方法是使用*通配符,它将匹配任意字符串。如果主机模式只是带引号的星号,则清单中的所有主机都将匹配。

---
- hosts: '*'

也可使用*字符匹配包含特定子字符串的受管主机或组。
例如,以下通配符主机模式匹配以.example.com结尾的所有清单名称:

---
- hosts: '*.example.com'

以下示例使用通配符主机模式来匹配开头为192.168.2.的主机或主机组的名称:

---
- hosts: '192.168.2.*'

以下示例使用通配符主机模式来匹配开头为datacenter的主机或主机组的名称。

---
- hosts: 'datacenter*'

2.5 列表

可以通过逻辑列表来引用清单中的多个条目。主机模式的逗号分隔列表匹配符合任何这些主机模式的所有主机。

如果提供受管主机的逗号分隔列表,则所有这些受管主机都将是目标

---
- hosts: labhost1.example.com,test2.example.com,192.168.2.2

如果提供组的逗号分隔列表,则属于任何这些组的所有主机都将是目标:

---
- hosts: lab,datacenter1

也可以混合使用受管主机、主机组和通配符,如下所示:

---
- hosts: 'lab,data*,192.168.2.2'

注意
也可以用冒号(:)取代逗号。不过,逗号是首选的分隔符,特别是将IPv6地址用作受管主机名称时。

如果列表中的某一项以与符号(&)开头,则主机必须与该项匹配才能匹配主机模式。它的工作方式类似于逻辑AND。

例如,根据我们的示例清单,以下主机模式将匹配lab组中同时也属于datacenter1组的计算机:

---
- hosts: lab,&datacenter1 

我们也可以通过主机模式&lab,datacenter1或datacenter,&lab指定datacenter1组中的计算机只有在同时也属于lab组时才匹配。

通过在主机模式的前面使用感叹号(!)表示从列表中排除匹配某一模式的主机。它的工作方式类似于逻辑NOT。

根据示例清单,以下示例匹配datacenter组中定义的所有主机,但test2.example.com除外:

---
- hosts: datacenter,!test2.example.com

也可以使用模式’!test2.example.com,datacenter’来获得相同的结果。

最后一个示例演示了使用匹配测试清单中的所有主机的主机模式,datacenter1组中的受管主机除外。

---
- hosts: all,!datacenter1

3. 管理动态清单

3.1 动态生成清单

前面我们用到的静态清单编写比较容易,对于管理小型基础架构而言也很方便。不过,如果要操作许多台计算机,或者在计算机更替非常快的环境中工作,可能难以让静态清单文件保持最新状态。
大多数大型IT环境中没有系统来跟踪可用的主机以及它们的组织方式。例如,可能有外部目录服务通过Zabbix等监控系统维护,或者位于FreeIPA或Active Directory服务器上。Cobbler等安装服务器或红帽卫星等管理服务可能跟踪部署的裸机系统。类似地,Amazon Web ServicesEC2或OpenStack部署等云服务,或者基于Vmware或红帽虚拟化的虚拟机基础架构可能是有关那些更替的实例和虚拟机的信息来源。

Ansible支持动态清单脚本,这些脚本在每当Ansible执行时从这些类型的来源检索当前的信息,使清单能够实时得到更新。这些脚本是可以执行的程序,能够从一些外部来源收集信息,并以JSON格式输出清单。

动态清单脚本的使用方式与静态清单文本文件一样。清单的位置可以直接在当前的ansible.cfg文件中指定,或者通过-i选项指定。如果清单文件可以执行,则它将被视为动态清单程序,Ansible会尝试运行它来生成清单。如果文件不可执行,则它将被视为静态清单。

清单位置可以在ansible.cfg配置文件中通过inventory参数进行配置。默认情况下,它被配置为/etc/ansible/hosts。

3.2 开源社区脚本

开源社区向Ansible项目贡献了大量现有的动态清单脚本。它们没有包含在ansible软件包中。这些脚本可从Ansible GigHub网站(https://github.com/ansible/ansible/tree/devel/examples)获取。

3.3 管理多个清单

Ansible支持在同一运行中使用多个清单。如果清单的位置是一个目录(不论是由-i选项设置的、是inventory参数的值,还是以某种其他方式设置的),将组合该目录中包含的所有清单文件(不论是静态还是动态)来确定清单。该目录中的可执行文件将用于检索动态清单,其他文件则被用作静态清单。

清单文件不应依赖于其他清单文件或脚本来解析。例如,如果静态清单文件指定某一个组应当是另一个组的子级,则它也需要具有该组的占位符条目,即使该组的所有成员都来自动态清单。

[cloud-east]

[servers]
test.demo.example.com

[servers:children]
cloud-east

注意
清单文件的解析顺序不是由文档指定的。目前,如果存在多个清单文件,它们会按照字母顺序进行解析。如果一个清单源依赖于另一个清单源的信息,则它们的加载顺序可能会确定清单文件是按预期工作还是引发错误。因此,务必要确保所有文件都自相一致,从而避免意外的错误。

Ansible会忽略清单目录中以特定后缀结尾的文件。这可以通过在Ansible配置文件中的inventory_ignore_extensions指令来控制。有关更多信息,请参阅Ansible官方文档。

使用动态清单:https://docs.ansible.com/ansible/latest/user_guide/intro_dynamic_inventory.html
开发动态清单:https://docs.ansible.com/ansible/latest/dev_guide/developing_inventory.html

4. 配置并行

4.1 使用分叉在ansible种配置并行

当Ansible处理playbook时,会按顺序运行每个play。确定play的主机列表之后,Ansible将按顺序运行每个任务。通常,所有主机必须在任何主机在play中启动下一个任务之前成功完成任务。

理论上,Ansible可以同时连接到play中的所有主机以执行每项任务。这非常适用于小型主机列表。但如果该play以数百台主机为目标,则可能会给控制节点带来沉重负担。

Ansible所进行的最大同时连接数由Ansible配置文件中的forks参数控制。默认情况下设为5,这可通过以下方式之一来验证。

[root@localhost ~]# grep forks /etc/ansible/ansible.cfg 
#forks          = 5
[root@localhost ~]# ansible-config dump|grep -i forks
DEFAULT_FORKS(default) = 5

[root@localhost ~]# ansible-config list|grep -i forks
DEFAULT_FORKS:
  description: Maximum number of forks Ansible will use to execute tasks on target
  - {name: ANSIBLE_FORKS}
  - {key: forks, section: defaults}
  name: Number of task forks

例如,假设Ansible控制节点配置了5个forks的默认值,并且play具有10个受管主机。Ansible将在前5个受管主机上执行play中的第一个任务,然后在其他5个受管主机上对第一个任务执行第二轮。在所有受管主机上执行第一个任务后,Ansible将继续一次在5受管主机的组中的所有受管主机上执行下一个任务。Ansible将依次对每个任务执行此操作,直到play结束。

forks的默认值设置得非常保守。如果你的控制节点正在管理Linux主机,则大多数任务将在受管主机上运行,并且控制节点的负载较少。在这种情况下,通常可以将forks的值设置得更高,可能接近100,然后性能就会提高。

如果playbook在控制节点上运行很多代码,则应明智地提高forks限值。如果使用Ansible管理网络路由器和交换机,则大多数模块在控制节点上运行而不是在网络设备上运行。由于这会增加控制节点上的负载,因此其支持forks数量增加的能力将显著低于仅管理Linux主机的控制节点。

可以从命令行覆盖Ansible配置文件中forks的默认设置。ansible和ansible-playbook命令均提供-f或–forks选项以指定要使用的forks数量。

4.2 管理滚动更新

通常,当Ansible运行play时,它会确保所有受管主机在启动任何主机进行下一个任务之前已完成每个任务。在所有受管主机完成所有任务后,将运行任何通知的处理程序。

但是,在所有主机上运行所有任务可能会导致意外行为。例如,如果play更新负载均衡Web服务器集群,则可能需要在进行更新时让每个Web服务器停止服务。如果所有服务器都在同一个play中更新,则它们可能全部同时停止服务。

避免此问题的一种方法是使用serial关键字,通过play批量运行主机。在下一批次启动之前,每批主机将在整个play中运行。

在下面的示例中,Ansible一次在两个受管主机上执行play,直至所有受管主机都已更新。Ansible首先在前两个受管主机上执行play中的任务。如果这两个主机中的任何一个或两个都通知了处理程序,则Ansible将根据这两个主机的需要运行处理程序。在这两个受管主机上执行完play时,Ansible会在接下来的两个受管主机上重复该过程。Ansible继续以这种方式运行play,直到所有受管主机都已更新。

---
- name: Rolling update
  hosts: webservers
  serial: 2
  tasks:
  - name: latest apache httpd package is installed
    yum:
      name: httpd
      state: latest
    notify: restart apache
    
  handlers:
  - name: restart apache
    service:
      name: httpd

假设上一示例中的webservers组包含5个Web服务器,它们位于负载均衡器后面。将serial参数设置为2后,play一次将运行两台Web服务器。因此,5台Web服务器中的大多数服务器将始终可用。

相反,如果不使用serial关键字,将同时在5台Web服务器上执行play和生成的处理程序。这可能会导致服务中断,因为Web服务将在所有Web服务器上同时重新启动。

重要 :出于某些目的,每批主机算作在主机子集上运行的完整play。这意味着,如果整个批处理失败,play就会失败,这将导致整个playbook运行失败。

在设置了serial: 2的上一个场景中,如果出现问题并且处理的前2个主机的play失败,则playbook将中止,其余3个主机将不会通过play运行。这是一个有用的功能,因为只有一部分服务器会不可用,使服务降级而不是中断。

serial关键字也可以指定为百分比。此百分比应用于play中的主机总数,以确定滚动更新批处理大小。无论百分比为何,每一工序的主机数始终为1或以上。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 17:01:25  更:2021-07-31 17:02:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:37:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码