案例分享 | 美国新能源科技公司Netco从零开始Zabbix的自动化之路

2021-01-29 17:49:14 浏览数 (1)

文章简介

本文分享的是美国新能源科技公司(英文名:Netco Technology)的Zabbix自动化部署和管理方案,用于监控大量各种类型的网络设备。在此也特别感谢伍昕先生对演讲原文的翻译和整理!

伍昕,Zabbix社区讲师,8年运维工作经验,五年Zabbix使用经验,擅长Zabbix与其他运维系统的对接及自动化,多次参与和指导监控平台从无到有的设计与搭建。

01 - 介绍

这篇文章中我们将介绍,我们在实际工作中关于Zabbix自动化安装与维护方案。我们现在使用Zabbix监控了大量各种类型的网络设备,因此我们需要通过自动化来完成这些设备监控的初始化。我很乐意分享我们是怎么做到这些的,以及这样做的原因,希望大家可以从我们的分享中有所收获。

Netco 是一家网络基础设施供应商,这意味着我们为各种类型的客户建立和维护网络。几年前,我们开始为一些大型的零售商建立网络,这些客户需要将分散在各地的数百台设备通过广域网连接起来。他们同时希望接入第三方的网络,比如其他合作公司或者总部。所以他们需要一个集中的广域网来管理网络流量和提供网络服务。

我们公司的网络服务非常受欢迎,所以我们将这部分业务作为Retailstekker(在荷兰语中是“零售插头”的意思)进行独立销售。取Retailstekker这个名字背后的想法是,我们将客户的办公地点以提供插件的方式将各类设备接入我们的网络,然后进行维护和管理。收付款设备、打印设备、销售终端设备等都可以接入。

02 - 技术概述

我们的Retailstekker网络,通过python和上图中的各项技术组件实现。我们使用SaltStack作为我们的自动化工作的内核和管理工具,但是我们将会给出一些更通用的建议以便你们能通过Ansible,Puppet或者其他推送工具来实现。

Retail 网络架构

一个Retailstekker网络可以包含数百个客户网络节点,所有的客户网络节点都有一个路由器设备,通常是Cisco路由器。这些路由器通过连接到我们的数据中心来组成一个广域网络并且有一个核心防火墙来防护和管理所有网络的进出访问。通过这个,我们可以建立到总部或者第三方合作商的通信链接,同时也能向客户提供VPN访问以便他们可以访问所有自己的本地设备。

以上这些可以实现,得益于不同技术的组合:FreeRADIUS用于客户网络节点的接入验证,DHCP和BIND用于提供网络服务。Zabbix用于对整个网络的监控。我们使用Django开发了一个仪表版用于让客户了解他们当前的网络状态。

03 - 平台仪表板

NETCO平台面板

仪表板上显示了当前正常的DSL和光纤上行链路节点数量。同时还显示了使用4G网络和LTE接入的客户网络节点数量,以防这些客户网络节点无法建立DSL或者光纤链接。为了将这些信息可视化,我们将地图上的每一个客户网络节点的状态都做了颜色编码。

网络区域告警面板

如果客户想了解某个客户网络节点的更多信息,可以点击它查看现场设备的延迟状态、已使用的4G流量,还可以运行各种诊断测试。此图显示所选客户网络节点使用蜂窝连接的时间,允许客户监视其付费数据的使用情况。

NETCO告警页面

不久前,我们还将部分监控集成到仪表板中。现在,当客户有供应商需要使用VPN来进行链接时,我们可以提供Zabbix监控,以便他们快速检查这些特殊供应商的状态。这样,我们就可以对连接是否正常有更高级别的展示。

04 - NOC面板

所有的客户在广域网中都是互通的,该网络由Zabbix监控。但是实际上每一个客户都有自己独立的网络和独立的ZabbixServer,这意味着会有多个相关配置。为了关注我们的NOC上的所有的ZabbixServer,我们使用Grafana创建单个仪表板用来展示这些ZabbixServer的性能数据,告警,并实现对ZabbixServers本身的监控。

VPN 节点面板

这个VPN仪表板,我们用它来监控所有正常,关闭,正在维护的VPN节点状态。如您所见,所有Zabbix服务器的所有告警也都显示在这一个屏幕上。

Zabbix servers 统计面板

当然我们依然在使用Zabbix本身来监控这些Zabbix Servers。在这一页,每一列都代表一台Zabbix Server服务器,展示了它们的负载,监控项数量,缓存情况等Zabbix Server的性能状况。这样可以让我们关注我们为客户搭建的各个Zabbix 实例的运行情况。

05 - 安装

上一小节解释了我们为何要使用这么多Zabbix Server的原因和背景。方便大家更好的了解我们为什么需要做自动化。

如果你拥有数十台Zabbix Server,手动维护它们将会是一些麻烦。这也是我们为什么通过自动化来完成Zabbix Server 的安装配置以及优化。

安装页面

在设置中我们写了一个python脚本来请求以下数据:

1.客户名称

2.环境参数(用于区分不同的客户)

3.IP地址等等。

然后将会自动生成后续在环境中需要使用的密码。

一旦数据被输入到脚本并确认已经部署,SaltStack服务将通知一台KVM设备,然后启动对应的Zabbix实例,并完成其他操作。

在Zabbix Server启动后,将会连接SaltStack的Server并建立agent-server关联。SaltStack将会在Zabbix Server上做以下操作:

1.注册Katello(代码管理系统)

2.注册FreeIPA(认证管理系统)

3.开始安装Zabbix组件

当这一切完成后,我们将我们的代码从GitLab上推送到本地磁盘中。

06 - 配置

通过前面的步骤我们有了一个已经安装好了的Zabbix Server,现在我们需要通过自动化的对这些Zabbix 组件进行深入的配置和定制。

我们要做的第一件事是配置FreeIPA作为服务器的身份验证机制。另外将会使用LDAP作为我们的用户管理后端,一遍我们的客户使用常规的账号密码验证。这些操作通过SQL来完成,我们通过SaltStack发起这些操作让客户通过LDAP来访问Zabbix页面。

启用LDAP认证:

代码语言:javascript复制
mysql_query.run:
- database: zabbix
- query: "UPDATE config SET authentication_type=1,
ldap_host='ldap://{{ ldap.host }}', ldap_port={{ ldap.port }},
ldap_base_dn='{{ ldap.basedn }}', ldap_bind_dn='{{ ldap.binddn }}',
ldap_bind_password='{{ ldap.password }}',
ldap_search_attribute='{{ ldap.search }}'"

完成登陆验证配置侯,将会开始配置Zabbix的默认邮箱告警配置,仍然是通过SaltStack的方式往各个Server上推送邮箱的配置文件。

配置Zabbix的默认邮箱告警配置。

代码语言:javascript复制
$ cat /srv/salt/zabbix-server/mediatypes.sls
zabbix_mediatype.present:
- name: 'Email'
- mediatype: 0
- smtp_server: localhost
- smtp_helo: {{ salt['grains.get']('id','localhost') }}
- smtp_email: 'zabbix@example.com'

我们继续配置不同的用户组——管理员和普通用户,管理员用户组有我们的API和技术支持人员使用。普通用户组则提供给我们的客户使用。当然,客户实际上访问的是我们自己的仪表版而不是Zabbix的的仪表板。但是我们仍然需要这个组,用来配置告警媒介的配置。

大家会发现使用LDAP的Zabbix仍然需要在Zabbix页面来创建新的用户,这样会带来一些麻烦。我们通过SaltStack解决了这个问题,通过getent的方式循环读取Zabbix用户和LDAP中的用户进行对比,找出在LDAP新创建的用户,然后在Zabbix自动创建。

代码语言:javascript复制
$ cat /srv/salt/zabbix-server/users.sls
 {%- for username in salt['cmd.run']("getent group 
'grp-zabbix-users'").split(':')[3].split(',') %}
Zabbix user {{ username }}:
zabbix_user.present:
- alias: '{{ username }}'
- passwd: ''
- password_reset: False
- usrgrps:
- Support
- medias:
- mediatypeid: {{ salt['zabbix.mediatype_get'](name='Email') }}
sendto: '{{ username }}@example.com'
active: 0
severity: 63
period: '1-7,00:00-24:00'
{%- endfor %}

完成以上工作后,SaltStack 将会安装Gitlab相关的交互及通知脚本。这意味着后续新的代码都将会自动部署到所有的服务器上去。

代码语言:javascript复制
$ cat /srv/salt/zabbix-server/scripts.sls
external-scripts:
git.latest:
- name: https://gitlab.local/zabbix/external-scripts.git
- target: /opt/zabbix/scripts/external
- force_reset: True
- require:
- pkg: git

这种方式也可以用于同步Zabbix的模板,每一个模板都放到Gitlab的存储库中,当SaltStack在服务器上运行时,Git将会将服务器上的文件拉到本地进行对比,如果发生了变化,一个python脚本将会导入该模板及对应的关联模板(递归关联,确保所有直接间接相关模板都会导入)。

代码语言:javascript复制
$ cat /srv/salt/zabbix-server/templates.sls
templates:
file.directory:
- name: /opt/zabbix/templates/
git.latest:
- name: https://gitlab.local/zabbix/templates.git
- target: /opt/zabbix/templates/
- require:
- pkg: git
cmd.run:
- name: /opt/zabbix/scripts/template-import.py -v -T /opt/zabbix/templates/
- runas: zabbix
- onchanges:
- git: templates

特定的目录结构向我们显示了首先加载哪些模板,从而可以递归地导入不同级别的模板。如果有一个模板使用另一个相互链接的模板,我们将逐个遍历目录,以确保所有模板都按顺序正确导入。

07 - Host 管理

这样我们就有了一个”Zabbix server”(Server非彼Server),里面有我们所有的Zabbix组件并且拥有所有的脚本和模板。下一步就是如何配置这些需要监控的Hosts。

主机群组

首先,在添加主机前必须定义主机群组。我们有两种类型的主机群组将会通过Salt 推送到各个Zabbix组件中。上面截图中的白色主机群组是标准主机群组,在各个地方都会用到,比如 用于同一分公司办公室里面的所有Host,或者Zabbix server所在服务器的自监控模板等。蓝色的群组(预发布,维护,离线)用于我们的维护工作。还有一些物理设备群组,包含了客户所在客户网络节点的所有设备。

Zabbix将会通过SaltStack添加Hosts。在SaltStack中定义好Host后,Zabbix将会自动创建。我们也能通过SaltStack来批量推送宏和模板,并且在SaltStack运行时,被遗漏的host也会自动添加到Zabbix中

代码语言:javascript复制
zabbix.hosts:
- name: google-public-dns-a.google.com
label: Google DNS1
ip: 8.8.8.8
groups:
- 3rd Parties
macros:
- '{$TIMEOUT}': 180
template: "t_availability_ping"

低级别host的管理

先前的方式一般用于分支机构或者第三方服务商。对于数量上百的独立商店,我们有更快速的解决方案,通过一个名为“infrabuilder”的Python脚本解决。这个Python脚本通过调用HTTP API的方式访问我们的CMDB。CMDB中包含了我们Retailstekker网络中所有产品的客户网络节点和配置信息。

这个脚本从CMDB获取客户的客户网络节点信息,并且用这些信息来解决以下问题:

1.常见一个DNS记录

2.创建FreeRADIUS记录

3.创建DHCP

4.获取交换机的配置文件并将其放到TFTP服务器上

5.与Zabbix进行通信

CMDB中的每一个host都会被推送到Zabbix中。如果CMDB中的host被删掉了,比如说因为合同不再续约,这个脚本也会自动将Zabbix中对应的host删除。

Host聚合

最后,还有聚合host类型。SaltStack会为每个设备群组创建一个聚合;所以当给路由器创建一个群组时,将会通过跟踪群组中的路由器来自动创建一个Host的聚合。Zabbix将会开始监控这些Host有多少是连通的,又有多少正在维护。这可以让我们对每一个独立商店的状态有一个更全局的了解。

08 - 维护

当我们拥有了一个各个功能非常完善的Zabbix系统后,进一步降低这个系统的人力投入及故障率将会变得非常重要。这也是通过自动化系统的维护来实现的。

三种类型的维护周期

如图所示,Zabbix中有3个维护周期,每个周期内都继续保持数据收集。将被维护的主机放入到这些维护周期类可以防止因为维护产生的告警。

我们为何要设置3个不同的维护周期呢?当一个host被infrabuilder导入后,脚本将会将其放入到Predeployment维护周期中。这意味着即使对应的交换机未交付,这个新的host也可以立刻被纳入到Zabbix监控。因为这些host在维护周期里面,我们的工程师并不会收到对应的告警。

我们一般会在一般在8小时内将路由器送到各个客户网络节点并进行配置,这个维护周期给了我们这些时间。在路由器启动超过8小时后,对应的host将会自动从Predeployment维护周期中删除。这样我们就可以将新的硬件放到Zabbix中,一旦设备被发现,将会自动纳入Zabbix的监控。

然后是Offline维护。有一个脚本在后台运行,用于检查这些设备能否ping通。在实际工作过程中,我们经常发现很多客户会在不通知我们的情况下因为一些原因重启或者关闭我们的设备,在我们的仪表盘中我们会看到对应的host已经down了一个月,并给我们的工程师造成了数据干扰,因为实际上并没有故障发生。我们会将这些受影响的Host放到Offline维护中去,7天后面板上这些设备的状态将会被设置为unknown。当这个商店冲洗你上线后,对应的host将会从Offline维护中移除。

第三种维护周期是给我们的工程师使用的。当一个工程师在维护一台路由器时,我们将会将这个路由器对应的Host放入到这个周期中。所以在维护完成前,客户将不会收到对应的告警。工程师在维护完成后会将该Host从维护周期中移除。

监控项清理

清理监控项脚本

当一各Host通过SNMP无法访问时,Zabbix任然会尝试获取相关的系统信息。如果有大量这样SNMP无法访问的设备,Zabbix将会花费大量时间用于检查这些监控项是否正常。

这种情况促使我们编写了一个Python脚本用于检查设备是否能ping通。如果设备在特定时间内无法ping通,脚本将会将对应Host上的SNMP,HTTP,AGENT等相关监控项全部金庸。这样将会释放那些尝试连接这些无法ping通的设备的ZabbixPoller进程。当这些设备重新被连接后,这些监控项将会通过同一个脚本重新启用。

依赖关系

想象一个场景:一家商店客户有一个路由器,配置了对应的交换机,以及一些用于在商店中连入WIFI的网络接入点。当路由器挂掉之后,我们希望只收到路由器的告警,而不是因为路由器挂掉引发的关联交换机和访问点的告警。这需要通过定义触发器依赖来解决,一般情况下这些依赖是手动创建的。

在这种情况下我们通过一个脚本完成了这个配置依赖的过程。首先在我们的CMDB中,我们会同步每个客户网络节点的合同编号,因此一个客户网络节点中的所有设备在Zabbix中的资产管理中有一个inventory字段的值都是一样的。通过这个inventory字段来标识所有位于同一个客户网络节点的设备,而无需通过网络自动发现来实现。

告警依赖

基于这个资产编号,我们就知道了这些接入点接入的是哪个交换机,对应的交换机接入的是哪一个路由器。这个脚本将会根据这些设备的关系自动创建对应的触发器依赖。

告警

告警配置面板

当一个区域的大量网络节点有异常时,客户希望能收到告警。并且希望时效性很高的告警,比如通过短信。

上图的仪表板中有一个下拉菜单,可以让客户为告警选择对应的告警阈值。客户选择好后,后台会给客户在对应的Host聚合中创建一个用户宏。客户可以在里面填写他们的邮箱地址和电话号码。在后端,这是通过一个Zabbix的“customer”级别的用户实现的,仅有只读权限。

报表

报表配置页面

关于报表,我们通过一个脚本来抓取监控项,监控项采集值和资产信息来自动生成报表。比如,有一个SNMP监控项,用于拉取设备的序列号作为一个资产信息字段的值。

正在执行的报表脚本

这个脚本同时也会将主机名,序列号清单以及任何可以获取到的监控项信息输出到报表中。这个报表每个月都会发送给我们的财务部门,财务部门可以用这个报表来检查我们的收费情况与实际的服务情况是否一致或者用于其他地方。

0 人点赞