网络自动化之Ansible模块的构建-1

Posted zhangzhilian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络自动化之Ansible模块的构建-1相关的知识,希望对你有一定的参考价值。

重点介绍了如何安装Ansible,并描述了Ansible的主要构建模块,以及如何利用它们构建高级的Ansible playbook。


Ansible是一个非常受欢迎的自动化框架,它被用于自动化 IT运营较长时间。它简化了不同基础设施节点的管理,并将业务逻辑转换为定义良好的过程,以便实现该业务逻辑。Ansible是用Python编写的,它主要依靠SSH与基础设施节点通信,在节点上执行指令。它从Ansible 1.9开始支持网络设备,通过Ansible 2.9,它目前对网络设备的支持得到了广泛的发展。它可以使用SSH与网络设备交互,或通过API, 如果网络供应商在他们的设备上支持API。它还具有多种优点,包括以下几点:

  • 简单的学习曲线:编写Ansible Playbook需要 YAML和Jinja2模板知识,它们很容易学习,而且它的描述性语言很容易理解。
  • 无代理:它不需要在远程管理设备上安装代理来控制该设备。
  • 可扩展:Ansible配备了多个模块,可以在托管节点上执行各种任务。它还支持编写自定义模块和插件来扩展Ansible的核心功能。
  • 幂等性:Ansible不会改变设备的状态,除非它需要改变设置的设置以达到所需的状态。一旦它在这个理想的状态,运行Ansible Playbooks对设备不会改变它的配置。

在这一章中,我们将介绍Ansible的主要组件,并概述Ansible支持的不同功能和选项。以下是将涉及的主要内容:

  • 安装Ansible
  • 构建Ansible Invertory
  • 使用Ansible的变量
  • 构建Ansible Playbook
  • 使用Ansible的条件语句
  • 使用Ansible的循环语句
  • 使用Ansible Vault保护机密
  • 使用Jinja2与Ansible
  • 使用Ansible的过滤器
  • 使用Ansible标记
  • 定制Ansible的设置
  • 使用Ansible角色

本文的目的是对不同的Ansible组件有一个基本的了解,将在后面使用这些组件,与网络设备进行交互。因此,本文中的所有例子都不是针对网络设备的管理。相反,我们将专注于理解Ansible中的不同组件,以便在后面中有效地使用它们。


1.1 技术要求

下面是安装Ansible和运行我们所有的Ansible playbook的要求:

  • 使用下列Linux虚拟机(VM)发行版之一:
  • Ubuntu 18.04 or higher
  • CentOS 7.0 or higher
  • 虚拟机连接Internet

设置Linux机器超出了本教程的范围。然而,设置任何操作系统版本的Linux VM最简单的方法是使用Vagrant创建和设置Ansible VM。


1.2 安装Ansible

我们安装Ansible的机器(这被称为Ansible控制机器)应该运行在任何Linux发行版上。在本节中,我们将概述如何安装 在Ubuntu Linux或CentOS机器上使用Ansible。

1.2.1 准备工作

为了安装Ansible,我们需要一个使用Ubuntu 18.04+或CentoS 7+操作系统的Linux虚拟机。 另外,这台机器需要有网络连接才能安装Ansible。

1.2.2 如何安装ansible

Ansible是用Python编写的,它的所有模块都需要Python来安装在Ansible控制机器上。我们的第一个任务是确保Python安装在Ansible控制机器上,如下面的步骤所述。

  1. 大多数Linux发行版默认安装了Python。但是,如果没有安装Python,下面是在Linux上安装它的步骤:
  • 在Ubuntu操作系统中,执行如下命令:

# Install python3
$sudo apt-get install python3
# validate python is installed
$python3 --version
Python 3.6.9

  • 在CentOS操作系统下,执行如下命令:

# Install python
$sudo yum install pytho3
# validate python is installed
$python3 --version
Python 3.6.8

  1. 在我们确认Python已经安装之后,我们就可以开始安装Ansible了
  • 在Ubuntu操作系统中,执行如下命令:

# 我们需要使用ansible repository来安装最新版本的ansible
$ sudo apt-add-repository ppa:ansible/ansible
# 更新repo cach使用新的repo
$ sudo apt-get update
# 安装Ansible
$ sudo apt-get install ansible

  • 在CentOS操作系统中执行如下命令:

# 我们需要使用最新的epel库来获取最新的ansible
$ sudo yum install epel-release
#安装ansible
$ sudo yum install ansible


1.2.3 如何使用ansible

安装Ansible最简单的方法是使用Linux发行版特有的包管理器。我们只需要确保我们已经启用了安装最新版本Ansible所需的存储库。在Ubuntu和CentOS中,我们需要启用额外的存储库来提供最新版本的Ansible。在CentOS中,我们需要安装并启用Enterprise Linux Repository (EPEL repo),它提供了额外的软件包,并有最新的CentOS Ansible软件包。


使用这种方法,我们将安装Ansible和运行Ansible模块所需的所有必要的系统包。在Ubuntu和CentOS中,此方法也将安装Python 2并使用Python 2运行Ansible。通过运行下面的命令,我们可以验证Ansible已经安装,并且使用了哪个版本:

$ ansible --version
ansible 2.9
config file = /etc/ansible/ansible.cfg
configured module search path =
[u/home/vagrant/.ansible/plugins/modules,
u/usr/share/ansible/plugins/modules]
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Aug 7 2019, 00:51:29) [GCC 4.8.520150623 (Red Hat 4.8.5-39)]

此外,我们可以检查Ansible是否按预期工作,尝试使用ping模块连接到本地机器,如图所示:

$ ansible -m ping localhost
localhost | SUCCESS =>
"changed": false,
"ping": "pong"

使用这种方法,我们可以看到它有以下几个问题:

  • 它使用Python 2作为执行环境,但我们想使用Python 3。
  • 它更新安装在系统上的Python包,这可能不是我们想要的。
  • 它没有为我们提供选择使用哪个版本的Ansible所需的粒度。使用此方法,我们将始终安装最新版本ansible,这可能不是我们需要的。


1.2.4 在Python 3环境中安装Ansible

为了在Python 3环境中安装Ansible,并对部署的版本有更多的控制,我们将使用pip Python程序来安装Ansible,如下所示:

  • 如果Python 3不存在,请安装Python 3,如下所示:

# Ubuntu
$ sudo apt-get install python3
# CentOS
sudo yum install python3

  • 安装 python3-pip包

# Ubuntu
$ sudo apt-get install python3-pip
# CentOS
$ sudo yum install python3-pip

  • 安装 Ansible

# Ubuntu and CentOS
# This will install ansible for the current user ONLY
$ pip3 install ansible==2.9 --user
# We Can install ansible on the System Level
$ sudo pip3 install ansible==2.9

  • 我们可以验证Ansible已经成功安装,如图所示

$$ ansible --version
ansible 2.9
config file = None
configured module search path =
[/home/vagrant/.ansible/plugins/modules,
/usr/share/ansible/plugins/modules]
ansible python module location =
/home/vagrant/.local/lib/python3.6/site-packages/ansible
executable location = /home/vagrant/.local/bin/ansible
python version = 3.6.8 (default, Aug 7 2019, 17:28:10) [GCC 4.8.5
20150623 (Red Hat 4.8.5-39)]

使用这种方法安装Ansible可以确保我们使用Python 3作为我们的执行环境,并允许我们控制安装哪个版本的Ansible,如示例所示。

我们将使用这个方法作为我们的Ansible安装方法,后续的所有章节都将基于这个安装过程。

提示:在第13章,Ansible的高级技术和最佳实践中,我们将概述另一种使用Python虚拟环境安装Ansible的方法。

1.2.5 另请参阅

关于Ansible安装的更多信息,请参考以下URL内容:

​https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html​


1.3 构建Ansible Inventory

在安装Ansible之后,我们需要定义Ansible的Inventory,这是一个文本文件,定义了Ansible将管理的节点。在这个节中,我们将概述如何创建和组织Ansible的Inventory文件。

1.3.1 准备工作

我们需要创建一个文件夹,其中包含我们将在本章中概述的所有代码。 我们创建了一个名为ch1_ansible的文件夹,如下所示:

mkdir ch1_ansible
$ cd ch1_ansible

1.3.2 创建Inventory文件

执行以下步骤创建Inventory文件:

  1. 创建一个名为hosts的文件:

touch hosts

  1. 使用任何文本编辑器,打开文件并添加以下内容:

$ cat hosts
[cisco]
csr1 ansible_host=172.10.1.2
csr2 ansible_host=172.10.1.3
[juniper]
mx1 ansible_host=172.20.1.2
mx2 ansible_host=172.20.1.3
[core]
mx1
mx2
[edge]
csr[1:2]
[network:children]
core
edge

提示:Ansible Inventory文件可以有任何名称。但是,作为最佳实践,我们将使用名称hosts来描述Inventory中的设备。


1.3.3 定义Ansible管理主机

Ansible Inventory文件定义了将由Ansible管理的主机(在前面的例子中,这是csr1-2和mx1-2),以及如何根据不同的标准将这些设备分组到自定义的组中。组用[ ]定义。这个分组帮助我们定义变量,简化设备之间的隔离,以及Ansible如何与它们交互。我们如何根据我们的用例对设备进行分组,所以我们可以根据供应商(cisco和juniper)或功能(core和edge)对它们进行分组。


我们还可以使用子元素为组构建层次结构,这在Inventory文件中进行了概述。下图显示了主机是如何分组的,以及组层次结构是如何构建的:

网络自动化之Ansible模块的构建-1_ansible


1.4 使用Ansible的变量

Ansible使用Ansible变量存储它管理的节点的信息。 Ansible变量可以在多个位置声明。然而,在观察Ansible的最佳实践时,我们将概述Ansible为清单文件中声明的节点寻找变量的两个主要部分。


为了遵循这个配方,Ansible库存文件必须按照前面的配方进行定义


在Inventory文件中,我们定义了主机,并将主机分组。现在我们定义了两个目录,用于Ansible搜索组变量和主机变量:

  1. 创建两个文件夹group_vars和host_vars:

$ cd ch1_ansible
$ mkdir group_vars host_vars

  1. 在group_vars文件夹中创建ios.yml和juos.yml文件

$ touch group_vars/cisco.yml group_vars/juniper.yml

  1. 在 host_vars文件夹中创建mx1.yml和csr1.yml文件

$ touch host_vars/csr1.yml host_vars/mx1.yml

  1. 在所有文件中填充变量,如下所示:

$echo hostname: core-mx1 >> host_vars/mx1.yml
$echo hostname: core-mx2 >> host_vars/mx2.yml
$echo hostname: edge-csr1 >> host_vars/csr1.yml
$echo hostname: edge-csr2 >> host_vars/csr2.yml
$echo os: ios >> group_vars/cisco.yml
$echo os: junos >> group_vars/juniper.yml


我们创建了如下结构的目录和文件来托管我们的变量,如下图所示:

网络自动化之Ansible模块的构建-1_centos_02

目录group_vars中的所有文件都包含我们在Inventory中定义的组的组变量,它们应用于这个组中的所有主机。至于目录host_vars中的文件,它们包含每个主机的变量。使用这个结构,我们可以将来自多个主机的变量分组到一个特定的组文件中,而特定于主机的变量将放在一个特定于该主机的单独文件中。

除了host_vars和group_vars, Ansible还支持使用其他技术定义变量,包括以下技术:

  • 在playbook中使用vars关键字指定多个变量
  • 使用vars_files在一个文件中定义变量,并让Ansible在运行剧本时从这个文件中读取这些变量
  • 使用-e选项在命令行指定变量


除了我们可以指定的用户定义变量之外,Ansible还有一些默认变量,它会为它的Inventory动态构建。下表捕捉了一些最常用的变量:

inventory_hostname

Inventory中定义的主机名称(例如:csr1 and mx1)

play_hosts

playbook中所有hosts的名单

group_names

一个特定主机所属的所有组的列表(例如,对于csr1,这将是[edge,cisco,network])


1.5 构建Ansible playbook

Ansible playbook是Ansible的基本元素,它声明了我们想要在托管主机上执行什么操作(在inventory中指定)。Ansible playbook是一个yaml格式的文件,它定义了将在我们管理的设备上执行的任务列表。在本节中,我们将概述如何编写Ansible playbook以及如何定义该playbook的目标主机。

1.5.1 准备工作

为了遵循此配置方法,必须定义Ansible Inventory文件,以及根据先前配置方法创建的所有特定于组和主机的变量文件。

1.5.2 编写和使用playbook

  1. 创建一个名为playbook的新文件。然后在ch1_ansible文件夹中加入以下代码行:

$ cat playbook.yml
---
- name: Initial Playbook
hosts: all
gather_facts: no
tasks:
- name: Display Hostname
debug:
msg: "Router name is hostname "
- name: Display OS
debug:
msg: " hostname is running os "

  1. 如下所示运行playbook:

$ ansible-playbook -i hosts playbook.yml

1.5.3 playbook是如何工作的

Ansible playbook是由一系列play组成的,每个play都针对特定的一组主机(在inventory文件中定义)。每个play都可以有一个或多个任务在该play的主机上执行。每个任务运行一个特定的Ansible模块,该模块有一些参数。下面的截图概述了该剧本的总体结构

网络自动化之Ansible模块的构建-1_python_03


在前面的playbook中,我们在括号中引用我们在前面配置方法中定义的变量。Ansible从group_vars或host_vars读取这些变量,我们在本playbook中使用的模块是调试模块,它将作为一个自定义消息显示在终端输出的msg参数中指定。playbook运行如下所示:

网络自动化之Ansible模块的构建-1_centos_04

我们在Ansible -playbook命令中使用-i选项来指向Ansible Inventory文件,我们将把它用作构建Inventory的源文件。

在本playbook中,我使用了all关键字来指定inventory中的所有主机。这是一个众所周知的组名,Ansible会为inventory中的所有主机动态构造这个组名。


1.6 使用Ansible的条件语句

Ansible的核心功能之一是有条件的任务执行。这使我们能够根据指定的条件/测试来控制在给定主机上运行哪些任务。在本节中,我们将概述如何配置条件任务执行。

1.6.1 准备工作

为了遵循这个配置方法,Ansible Inventory文件必须按照前面的配置方法进行配置。此外,我们所有主机的Ansible变量应该按照前面的配置方法定义。

1.6.2 编写和使用Ansible条件语句模板

  1. 在ch1_ansible文件夹中,创建一个名为ansible_cond.yml的新playbook。
  2. 在新playbook中放置如下内容,如下所示:

---
- name: Using conditionals
hosts: all
gather_facts: no
tasks:
- name: Run for Edge nodes Onlay
debug:
msg: "Router name is hostname"
when: "edge in group_names"

- name: Run for Only Mx1 node
debug:
msg: "hostname is running os"
when:
- inventory_hostname == mx1

  1. 如下所示运行playbook

$ ansible-playbook -i hosts ansible_cond.yml


1.6.3 Ansible条件语句是如何工作的

Ansible使用when语句为任务提供有条件的执行。当语句在任务级应用,如果when语句中的条件求值为true,则为给定的主机执行任务。如果为false,则跳过此主机的任务。运行上述playbook的结果如下所示:

网络自动化之Ansible模块的构建-1_python_05

when语句可以接受第一个任务中看到的单个条件,也可以接受第二个任务中看到的一系列条件。如果when是一个条件列表,那么为了执行任务,所有条件都必须为真。

在第一个任务中,when语句被括在""中,因为该语句以字符串开头。但是,在第二个语句中,我们使用普通的when语句,不带"",因为when语句以变量名开头。


1.6.4 另请参阅

更多关于Ansible条件的信息,请查看下面的URL:

​https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html​


1.7 使用Ansible循环语句

在某些情况下,我们需要在Ansible playbook中运行一个任务来循环一些数据。 Ansible的循环允许我们对一个变量(字典或列表)进行多次循环,以实现这种行为。在本节中,我们将概述如何使用Ansible的循环语句。

1.7.1 准备工作

为了遵循这个配置方法,Ansible Inventory文件必须提供并配置,如前面的配方所述。

1.7.2 编写和使用Ansible循环语句模板

  1. 在ch1_ansible文件夹中,创建一个名为ansible_loops.yml的新playbook。
  2. 在group_vars/cisco.yml文件内包含以下内容:

snmp_servers:
- 10.1.1.1
- 10.2.1.1

  1. 在group_vars/juniper.yml文件内包含以下内容:

users:
admin: admin123
oper: oper123

  1. 在ansible_loops.yml文件,包含以下内容

---
- name: Ansible Loop over a list
hosts: cisco
gather_facts: no
tasks:
- name: Loop over SNMP Servers
debug:
msg: "Router hostname with snmp server item "
loop: " snmp_servers"

- name: Ansible loop over a Dictionary
hosts: juniper
gather_facts: no
tasks:
- name: Loop over Username and Passwords
debug:
msg: "Router hostname with user item.key password item.value "
with_dict: " users "

  1. 运行playbook如下所示:

$ ansible-playbook ansible_loops.yml -i hosts


1.7.3 Ansible循环语句是如何工作的

Ansible支持循环使用两个主要的可迭代数据结构:列表和字典。当我们需要遍历列表(snmp_servers是一个列表数据结构)时,我们使用loops关键字;当我们遍历字典时,我们使用with_dicts (users是一个字典数据结构,其中用户名是键,密码是值)。在这两种情况下,我们都使用item关键字来指定当前迭代中的值。在with_dicts的情况下,我们使用item.key来获取key值, 使用item.value来获取value值。

前面playbook运行的输出如下所示:

网络自动化之Ansible模块的构建-1_ubuntu_06


1.7.5 另请参阅

关于不同的Ansible循环结构的更多信息,请参考以下URL内容:

​https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html​



1.8 使用Ansible Vault保护机密

当我们处理需要在Ansible playbook中引用的敏感材料时,例如密码,我们不应该以纯文本的形式保存这些数据。Ansible Vault提供了一种加密数据的方法,因此在剧本运行时可以安全地解密和访问。在本节中,我们将概述如何使用Ansible Vault,以确保Ansible中的敏感信息安全。


1.8.1 如何使用Ansible Vault

  1. 创建一个名为decrypt_passwd的新文件,如下所示:

$ echo strong_password > decrypt_passwd

  1. 使用ansible-vault会创建一个名为secrets的新文件,如下所示:

$ ansible-vault create --vault-id=decrypt_passwd secrets

  1. 将以下变量添加到这个新的secrets文件中

ospf_password: ospf_P@ssw0rD
bgp_password: BGP_p@ssw0rd

  1. 创建一个名为ansible_vault.yml的新playbook,如图所示:

---
- name: Using Ansible Vault
hosts: all
gather_facts: no
vars_files:
- secrets
tasks:
- name: Output OSPF password
debug:
msg: "Router hostname ospf Password ospf_password "
when: inventory_hostname == csr1

- name: Outpass BGP password
debug:
msg: "Router hostname BGP Password bgp_password "
when: inventory_hostname == mx2

  1. 运行playbook如下所示:

$ ansible-playbook --vault-id=decrypt_passwd ansible_vault.yml -i hosts


1.8.2 Ansible Vault是如何工作的

我们使用ansible-vault命令创建一个新文件,该文件使用--vault-id指定的密钥进行加密。我们将这个密钥/密码放在另一个文件中(在我们的示例中称为decrypt_passwd),并将该文件作为参数传递给vault-id。 在这个文件中,我们可以放置任意多的变量。最后,我们使用vars_files将这个文件作为变量文件包含在剧本中。下面是这个秘密文件的内容,以防我们不解密读取它:

网络自动化之Ansible模块的构建-1_ubuntu_07

前面playbook运行的输出如下所示:

网络自动化之Ansible模块的构建-1_python_08


为了让Ansible解密这个文件,我们必须通过--vault-id选项提供解密密码(在这个例子中存储在decrypt_passwd文件中)。当我们运行ansible-playbook时,我们必须提供这个解密密码,否则ansible-playbook会失败,如下所示:

#运行Ansible playbook不带--vault-id参数
$ansible-playbook ansible_vault.yml -i hosts
ERROR! Attempting to decrypt but no vault secrets found


如果我们不想在文本文件中指定加密/解密密码,我们可以使用--ask-vault-pass和ansible-playbook命令,以便在运行playbook时输入密码,如下所示:

#运行Ansible playbook带--ask-vault-pass参数
$ansible-playbook ansible_vault.yml -i hosts --ask-vault-pass
Vault password:


1.9 使用Jinja2与Ansible

Jinja2是一个强大的Python模板引擎,由Ansible支持。它还用于生成任何基于文本的文件,如html、CSV或YAML。我们可以利用Jinja2和Ansible变量来为网络设备生成自定义配置文件。在本节中,我们将概述如何在Ansible中使用Jinja2模板。

1.9.1 准备工作

为了遵循这个配置方法,Ansible Inventory文件必须按照前面的配置方法进行配置。

1.9.2 编写Asnible变量和Jinja2模板

  1. 在group_vars目录中创建一个名为network.yml的新文件

$ cat group_vars/network.yml
---
ntp_servers:
- 172.20.1.1
- 172.20.2.1

  1. 创建一个新的templates目录,并创建一个新的os_basic.j2文件,内容如下:

$ cat templates/ios_basic.j2
!
hostname hostname
% for server in ntp_servers %
ntp server
% endfor %
!

  1. 创建一个新的junos_basic.j2文件,包含以下内容:

$ cat templates/junos_basic.j2
set system host-name hostname
% for server in ntp_servers %
set system ntp server server
% endfor %

  1. 创建一个名为ansible_jinja2.yml的新playbook,内容如下:

---
- name: Generate Cisco config from Jinja2
hosts: localhost
gather_facts: no
tasks:
- name: Create Configs Directory
file: path=configs state=directory

- name: Generates Cisco config from Jinja2
hosts: cisco
gather_facts: no
tasks:
- name: Generate Cisco Basic Config
template:
src: "templates/ios_basic.j2"
dest: "configs/inventory_hostname.cfg"
delegate_to: localhost

- name: Generate Juniper config from Jinja2
hosts: juniper
gather_facts: no
tasks:
- name: Generate Juniper Basic Config
template:
src: "templates/junos_basic.j2"
dest: "configs/ inventory_hostname.cfg"
delegate_to: localhost

运行Ansible playbook,如下所示:

$ ansible-playbook -i hosts ansible_jinja2.yml

前面playbook运行的输出如下所示:

网络自动化之Ansible模块的构建-1_ansible_09


1.9.3 Ansible变量与Jinja2模板是如何工作的

我们创造了这个network.yml文件,以便将应用于该组下所有设备的所有变量分组。之后,我们创建了两个Jinja2文件,一个用于Cisco IOS设备,另一个用于Juniper设备。在每个jina2模板中,我们使用引用Ansible变量。我们还使用了for循环构造,% for server in ntp_servers %,这是jina2模板引擎支持的,以便循环通过ntp_servers变量(它是一个列表)来访问列表中的每一项。

Ansible提供了一个template模块有两个参数:

  • src:它引用jina2模板文件。
  • dest:指定将生成的输出文件。

在我们的例子中,我们使用inventory_hostname变量,以使清单中每个路由器的输出配置文件都是唯一的。

默认情况下,template模块在远程管理节点上创建输出文件。 但是,这在我们的例子中是不可能的,因为被管理的设备是网络节点。 因此,我们使用delegate_to: localhost选项来在Ansible控制机器上本地运行这个任务。

在playbook中的第一个play创建config目录来存储网络设备的配置文件。第二个play在Cisco设备上运行template模块,第三个平台在Juniper设备上运行template模块。

以下是Cisco设备其中一个配置文件:

[root@netdevops ch1_ansible]# cat configs/csr1.cfg
hostname edge-csr1
!
ntp 172.20.1.1
ntp 172.20.2.1
!

这是Juniper设备的配置文件:

[root@netdevops ch1_ansible]# cat configs/mx2.cfg
set system host-name core-mx2
set system ntp server 172.20.1.1
set system ntp server 172.20.2.1

1.9.4 另请参阅

关于Ansible template模块的更多信息,请参考以下URL内容:

​https://docs.ansible.com/ansible/latest/collections/ansible/builtin/template_module.htm​


1.10 使用Ansible过滤器

Ansible的过滤器主要来源于Jinja2过滤器,所有的Ansible过滤器都是用来转换和操作数据(Ansible的变量)。除了Jinja2过滤器,Ansible还实现了自己的过滤器来增强Jinja2过滤器,同时也允许用户定义自己的自定义过滤器。在本节中,我们将概述如何配置和使用Ansible过滤器来操作我们的输入数据。


1.10.1 编写和使用Ansible过滤器

  1. 安装python3-pip和Python的netaddr库,因为我们将使用 Ansible IP过滤器,它需要Python的netaddr库。

#在ubuntu系统上
$ sudo apt-get install python3-pip
#在CentOS系统上
$ sudo yum install python3-pip
$ pip3 install netaddr

  1. 创建一个新的Ansible剧本,名字为ansible_filters.yml,如图所示:

---
- name: Ansible Filters
hosts: csr1
vars:
interfaces:
- port: FastEthernet0/0, prefix: 10.1.1.0/24
- port: FastEthernet0/1, prefix: 10.1.2.0/24
tasks:
- name: Generate Interface Config
blockinfile:
block: |
hostname hostname | upper
% for intf in interfaces %
!
interface intf.port
ip address intf.prefix | ipv4(1) | inv4(address) intf.prefix | ipv4(netmask)
!
% endfor %
dest: "configs/csr1_interfaces.cfg"
create: yes
delegrate_to: localhost


1.10.2 Ansible过滤器是如何工作的

首先,我们使用blockinfile模块创建一个新的配置文件 Ansible控制机器。这个模块非常类似于template模块。但是,我们可以在模块的block选项中直接编写Jinja2表达式。我们使用playbook中的vars参数定义一个名为interfaces的新变量。这个变量是一个列表数据结构,其中列表中的每一项都是一个字典数据结构。这个嵌套的数据结构指定了每个接口使用的IP前缀。

在Jinja2表达式中,我们可以看到我们使用了许多过滤器,如下所示:

  • hostname | upper: upper是一个jina2过滤器,它将输入字符串中的所有字母转换成大写。通过这种方式,我们将主机名变量的值传递给这个过滤器,输出将是该值的大写版本。
  • intf.prefix| ipv4(1) | ipv4(address):这里,我们使用 Ansible IP地址过滤器两次。ipv4(1)接受一个输入的IP地址前缀,输出该前缀中的第一个IP地址。然后我们使用另一个IP地址过滤器,ipv4(address),为了只得到IP地址前缀的IP地址部分。 因此在本例中,我们使用10.1.1.0/24,并输出10.1.1.1作为第一个接口。
  • intf.prefix | ipv4(netmask) : 这里,我们使用Ansible IP地址过滤器来获取IP地址前缀的netmask,所以在我们的例子中,我们得到/24子网,并将其转换为255.255.255.0。

运行这个playbook之后,csr1路由器的输出文件显示如下:

$ cat configs/csr1_interfaces.cfg
# BEGIN ANSIBLE MANAGED BLOCK
hostname EDGE-CSR1
!
interface FastEthernet0/0
ip address 10.1.1.1 255.255.255.0
!
!
interface FastEthernet1/0
ip address 10.1.2.1 255.255.255.0
!
# END ANSIBLE MANAGED BLOCK


1.11 使用Ansible标记

Ansible Tags是一个强大的工具,它允许我们在一个大的Ansible playbook中标记特定的任务,并为我们提供了基于我们指定的标签选择在给定playbook中运行哪些任务的灵活性。在本节中,我们将概述如何配置和使用Ansible Tags。

1.11.1 配置和使用Ansible标记

  1. 创建一个新的Ansible playbook,名为ansible_tags.yml,如下所示:

---
- name: Using Ansible Tags
hosts: cisco
gather_facts: no
tasks:
- name: Print OSPF
debug:
msg: "Router hostname will Run OSPF"
tags: [ospf, routing]

- name: Print BGP
debug:
msg: "Router hostname will Run BGP"
tags:
- bgp
- routing

- name: Print NTP
debug:
msg: "Router hostname will run NTP"
tags: ntp

  1. 运行playbook,如下所示:

$ ansible-playbook ansible_tags.yml -i hosts --tags routing

  1. 再次运行playbook,这次使用标签,如下所示:

$ ansible-playbook ansible_tags.yml -i hosts --tags bgp
$ ansible-playbook ansible_tags.yml -i hosts --tags ospf
$ ansible-playbook ansible_tags.yml -i hosts --tags routing
$ ansible-playbook ansible_tags.yml -i hosts --tags ntp


1.11.2 Ansible标记是如何工作的

我们可以使用tags去标识给定tag的任务和play,以便使用它来控制执行哪些tasks或plays。这在开发playbook时给予了我们更多的控制,以允许我们运行相同的playbook。但是,在每次运行时,我们都可以控制要部署的内容。在本节的示例playbook中,我们已经将任务标记为OSPF、BGP或NTP,并将routing标记应用于OSPF和BGP任务。这允许我们有选择地在我们的剧本中运行任务,如下所示:

  • 没有指定标签,这将运行剧本中的所有任务而不改变行为,如下面的截图所示:

网络自动化之Ansible模块的构建-1_centos_10

  • 使用osp或bgpf标签,我们将只运行任何带有该标签的任务,如下所示:

网络自动化之Ansible模块的构建-1_centos_11