这次我们来讲讲网络设备的配置推送 上一节课我们简单讲了如何写一个简单的playbook,示例了如何执行命令行。今天我们按照日常的使用逐步深入,把playbook的书写展开来讲。

我们这次分享将网络设备的配置

本文只是从网络视角进行一个入门教程的编写,所以不会过分深入,但是会把一些知识点带一下,把一些思路和方法带给大家,大家有兴趣的可以去官网看看,或者买本书看看,或者看一下其他人的ansible教学视频文章都可以,ansible发展到如今,内涵丰富,实在是博大精深。

执行show命令 网络设备执行show命令非常简单,两种思路:

使用cli_command模块,前提是拥有对应的network_os(原生或者自己开发)

使用各个厂商定制的相关command模块,比如nxos的nxos_command,ios的ios_command

大家可以看看我的上一篇文章。

执行config命令 5种思路 执行了show,其实我们日常很大一部分工作内容是config变更。变更往往伴随大量的文本配置,如何用ansible将文本配置推送到网络设备,选择非常多,大约有5种思路,我们使用其中4种做演示。

  1. 使用cli_commnad通用模块,结合prompt提示符,输入应答answer,模拟人的交互实现配置。
  2. 使用cli_config通用模块,指定配置文件推送加载操作,这个对os有一定要求,我没有细看,但是估计不会是所有os都支持。
  3. 使用cli_config通用模块,执行相关命令的操作,ansible会自动根据os进行相关save或者commit的命令。
  4. 使用厂商定制的命令行command相关模块,部分支持prompt与answer机制,模拟人进行配置,与1类似。注意部分厂商的并不支持这种方式,比如华为的ce,command负责show,config负责下配置。Juniper的junos、思科的asa也是类似情况。思科的nxos与ios是支持的
  5. 使用厂商定制的config模块,这类只需要关注config内容,只要账号权限足够,会自动进入config模式(config terminal或者是system-view等),退出时自动保存配置。这种情况大部分网络厂商都有提供。 四种配置方式的演示 这次我们以思科的nxos为例,用的还是devnet的实验环境(后续等我把eve弄明白了,看看能不能给大家安排一些国产厂商的例子)

我们用4种方式给大家演示。

我们还是来写一个playbook,在写playbook的时候我们简单讲讲playbook的执行过程。

  1. playbook 是一个剧本,由N多幕play组成
  2. play执行的时候捏合host(网络设备)与task(1-N),让符合条件的host去执行每步的task
  3. task要定义调用的模块和参数。 就这样一个playbook贯彻下来后,ansible实现了网络自动化。精华在于每个task。

hosts文件还是我以前的那个hosts文件。不赘述。

---
- name: 执行思科nxos show命令 # play的名称 选填,建议使用
  hosts: cisco_nxos  # filter网络设备
  gather_facts: no # 收集设备的一些基础信息。比如端口、版本、平台等等,耗费时间,大家都选择不调用
  tasks:
    - name: 演示多个show命令
      nxos_command: 
        commands: 
          - show version
          - show int bri


    - name: nxos_command配置一个端口
      nxos_command: 
        commands: 
          - config
          - interface eth1/6
          - description this is configed by ansible nxos_command module
          - exit
          - exit
          - copy running-config startup-config


    - name: nxos_config配置一个端口
      nxos_config: # lines和commands作为此模块的参数,效果等同
        lines: # 使用参数lines,列表数组,无需进入命令行进入config模式,系统自动进入
          - interface eth1/7
          - description this is configed by ansible nxos_config module


    
    - name: cli_command配置一个端口
      cli_command:
        command: |
          config
          interface eth1/8
          description this is configed by ansible cli_command module
          exit
          exit
          copy running-config startup-config
    
    - name: cli_config配置一个端口
      cli_config:
        config: |
          interface eth1/9
          description this is configed by ansible cli_config module
        commit: true 
		

yaml的字符串保留换行 这个playbook,注意一下字符串换行的一个操作,之前我的yaml没有讲换行的部分,我们想贴入一段文本,保留换行的信息,可以使用| |+ |++


string: |
  I am a coder.
  My blog is didispace.com.

string: |+
  I am a coder.
  My blog is didispace.com.

string: |-
  I am a coder.
  My blog is didispace.com.
	

如上面一共有三种配置都会自动按配置中所写的换行来换行,但是在文末会有一些区别,有的会增加一个空行,有的不会,有的会新增两个空行,具体说明如下:

  • |:文中自动换行 + 文末新增一空行

  • |+:文中自动换行 + 文末新增两空行

  • |-:文中自动换行 + 文末不新增行

更多可以参考https://www.cnblogs.com/didispace/archive/2020/03/19/12524194.html

我们其实使用第一种即可。因为网络配置对空行,我所接触的设备来说并不是敏感的。多一行少一行没问题。大家参考上面的按需去选择

从上面的结果我们看到有点小问题,changed=2 代表有一个发生了变化,nxos_command的那段play没有发生变化是绿色的,实际上端口的描述已经发生了变化,这是由对应的module决定的,一会我们简单讲讲。

我们先查看端口描述


Eth1/6        eth    10G     this is configed by ansible nxos_command module
Eth1/7        eth    10G     this is configed by ansible nxos_config module
Eth1/8        eth    10G     this is configed by ansible cli_command module
Eth1/9        eth    10G     this is configed by ansible cli_config module

我们登陆设备看看start的配置,说明以上的均写入到start-up的配置。


interface Ethernet1/6
  description this is configed by ansible nxos_command module

interface Ethernet1/7
  description this is configed by ansible nxos_config module

interface Ethernet1/8
  description this is configed by ansible cli_command module

interface Ethernet1/9
  description this is configed by ansible cli_config module

几点补充 prompt prompt就是提示符的意思,有时候我们输入命令,会让我们确定,是否覆盖,是否保存,等等。

由于本次配置没有prompt,所以无法演示,大家可以看看官方文档很简单。

我们看一个例子


-  name: run command expecting user confirmation
  cli_command:
    command: show interface summary
    prompt: Press any key to continue
    answer: y
    newline: false

这段的意思是如果提示符是Press any key to continue我们就输入y,不换行。

比如我们删除一些资源时,设备会提示我们是否确定,或者其他情况下是否保存等等,我们必须输入yes或者no才能进行下去。

同时这个newline也非常重要:

  • 有的设备是输入yes后回车,这个时候newline需要时true。

  • 有的设备是输入yes后不需要回车,紧接着又一个提示,比如山石防火墙,这种情况下,我们可能需要newline设置为false。当然山石的ansible我没有找到,只是举个例子

保存提交 用command类型的时候,需要我们显式进入config模式,显式保存。

用对应的config模块时,以及cli_config,大部分都是模块帮助我们自动进入config模式,最后自动保存。

但是不绝对,希望大家在调用的时候去看看官方模块的使用说明。

一切才刚刚开始 我们以上所讲的配置模式,只是贴近我们的cli使用,其实ansible的模块是类似声明式的函数,然后我们传参,很多时候我们无需关注命令行,聚焦网络参数即可。这个在下一次分享我们会讲讲。

config模式并不是命令行那么简单 config模式其实还有很多高级功能,大家可以看看对应的模块文档(两种方法,大家可以翻翻我以前的文档),比如有很多高级功能:

  • 备份
  • 从本地文件传入设备进行配置推送
  • 配置比对diff 其实command也没那么简单,里面很多门道,比如多种情况的prompt匹配。

网络module如何查找 官方文档,或者本地的ansible安装环境中(pip show ansible可以看到路径)或者压缩的安装包,相对路径是\python3.8\site-packages\ansible\modules\network,部分按照平台比如nxos、cloudengine,有些是按功能集合,比如netconf、httpapi、interface等等。

找对应的Python文件即可,每个不以下划线开头的Python文件即是一个module,点开后可以详细看参数和使用。甚至可以看源代码的逻辑。

网络设备的changed,并不是百分百可信 我们刚才看到了有配置生效,通过command类型的是绿色,而通过config的是黄色。同时我两次推送同样的配置,按照幂等性要求,第二次应该是没有发生变化的,但实际网络设备又推送了一遍,又执行了一次save。这个和linux的相关模块是有区别的。

主要原因还是网络的nos太多样复杂,甚至写这些模块的对于幂等性没有顾忌,可能是技术不够,更可能是他不关注。

我们翻开nxos_command的源代,找到相关变更是否对设备产生了变化的影响。

result = {'changed': False, 'warnings': warnings}

这个changed自始至终是false的,不会变化,所以command一直是绿色。

而去找找nxos_config的相关源代码

它判断下发成功了就会把changed置为True,一刀切。

这个可以理解,如果真正做到显示正常,需要去判断配置的两次变化是否一致以及配置最后是否生效等等,这个逻辑过于复杂,我们就简单一刀切就可以,网络设备毕竟不过分关注。

幂等性 网络设备理论上来说我个人认为是大部分满足幂等性的。

首先解释下什么是幂等性,任意多次执行所产生的影响均与一次执行的影响相同。

比如我们配置端口,我们同样的配置执行1-N次,结果是一样的。

ansible的很多模块支持幂等性,有些需要自己写playbook的时候去设计。

网络模块底层实现分以下几种情况:

  • 一种是命令行,与具体命令有关,绝大部分命令行忽略报错基本也是幂等,不支持的可以通过一些方法规避,比如资源存在了就跳过这段。

  • 一种是Netconf实现,Netconf本身就是幂等的

  • 一种是httpapi ,看厂商实现,基本也是幂等。

常见的华为用Netconf,f5 有httpapi,思科大部分是命令行,也有api的.这些网络模块并没有特别去处理幂等这块。

最终的结果就是:

  • 绝大多数情况支持幂等,
  • 一些特殊情况实现幂等划不来,逻辑过于复杂,做一只快乐的鸵鸟吧。
  • 为了实现幂等,自己造轮子,好好学习ansible吧少年 抛转引玉 我们网络变更有一大特点,就是晚上到了窗口一顿刷,这个时候其实我们可以基于ansible的命令行相关模块去封装,用户只需关注命令行,执行相关的交给ansible,然后包装一下,给用户看起来好看一些。网工执着于cli,这个是短时间无法变化的现实。所以基于ansible的cli相关模块,可以做一些自己的探针或者叫堡垒机等等。

我一开始比较排斥ansible,原因之前在杂谈里说过一些,就是我们的环境太差,从流程、制度、厂商支持到个人水平,我觉得能做明白的不多,很多都是一知半解,me too(我一大优点是可以看懂源码,分析出其底层逻辑,ansible的语法我可能是幼儿园水平)。

国内能做下去ansible的,绝大多数还是环境单一(全是ce?),国外相关设备特别多的那种地方,或者做的也是表面的或者片面的一些东西,不好意思,又误伤了友军。。。但相信你我没什么竞争,我只是一个甲方,请不要在意。

但是最近学习ansible,看网络相关模块也是深有感触,这东西博大精深啊,且趋势摆在那,将来网络说不定真可以是受益者。如果环境好了,基于ansible去封装一些通用服务组件,也是可以的。我们在做网络自动化模块的时候,底层应该是海纳百川,我正在考虑把我们自己的分布式探针加上ansible的相关支持,这样运维人员的选择会更多,无论是cli、snmp、netconf、httpapi、ansible,全部都整上,向上封装一层。这个有点NSO或者ODL的意思了。后续我再分享一些网络自动化框架的相关理解和见知。

配置命令特别多怎么办 我们的例子是下发几行配置,过于简单,在实际生产中如何配置更多内容呢?两种思路:

  1. 学好ansible,后面有变量文件相关的,可以把大段配置文件推送到设备
  2. 基于Python的jinja2封装,把playbook写好,配置部分用jinja2语法写,用Python脚本把基于jinja2的playbook模板与读取的txt配置文件结合 时代在召唤 国内的友商们,时代在召唤,ansible的挥舞的小手你们看到了吗?将来的招标条件里面,会不会出现一条必须深度支持ansible呢?你们有自己的ansible模块吗?请华为坐下,在这方面,你们很优秀!你们的ansible模块开源了吗?别捂着了。

快快奋起直追吧,你的性能再好,将来的时代是Infrastructure as Code,没有ansible,或者没有其他相关的可编程模块,你凭什么跟别人打?难道真的靠国家情怀吗?消费者买单吗?买单后不会吐槽你吗?

欢迎友商、想学习的网工、甚至是系统运维工程师,与我一起探讨ansible!

继续欢迎点赞、在读、分享、喜欢、关注、推荐本公众号、专栏!

在NetDevOps的路上,让你我不孤单!

最最后 写在最后,这篇文章拖了好久,工作忙压力大,回家看孩子,这次是周六早上爬起来写,中午趁孩子睡觉赶紧再写点(好在ta下午睡觉时间久),时间紧任务重,出来的东西难免纰漏,欢迎大家指正!这篇文章本来想写更多东西,但是写着写着就聚焦于了配置这个场景,甚至去看源码了,anyway,希望大家喜欢,跟随我的视角一起学ansible!

下期预告,循环、变量等等。中间会穿插一些其他NetDevOps的东西。