Ethan's Blog https://blog.htlac.com/ zh-CN 技术改变生活 Tue, 31 Dec 2024 07:20:00 +0000 Tue, 31 Dec 2024 07:20:00 +0000 Prometheus+snmp_exporter+Grafana监控网络设备 https://blog.htlac.com/archives/665.html https://blog.htlac.com/archives/665.html Tue, 31 Dec 2024 07:20:00 +0000 Ethan 之前用Zabbix来监控,grafana来绘图,但是发现zabbix经常会出现绘图中断的情况,没有找到解决方案,所以想换个监控程序,首先想到的是nagios,但是nagios和grafana集成度可能不算太高,需要使用其他数据库。于是搜索发现Prometheus也能监控,之前用Prometheus主要是监控服务器,没想到配合snmp_exporter也挺好用,于是开始琢磨这套监控。

prometheus主要是一个数据采集器,需要监控的设备清单需要配置在Prometheus上,通过snmp_exporter来获取相关信息,并转化为Prometheus能够理解的内容,然后在通过Grafana进行绘图展示。

安装grafana及prometheus

建议从官网下载最新安装,否则部分新支持的特性可能无法使用,也可直接通过apt源安装

apt isntall grafana prometheus net-snmp snmp -y

snmp用于测试snmp是否配置成功

安装snmp_exporter

github地址https://github.com/prometheus/snmp_exporter

一定一定要使用最新版本的程序,否则新特性无法使用,如果你在网上看到一个别人生成的mib文件无法使用,那么很可能就是你的snmp_exporter版本太旧导致。

下载完了解压放到相应目录,并添加自启动,我将配置文件放到了和prometheus一个目录,方便维护,并使用默认的snmp.yml文件进行启动。基本够用了,我只需要监控系统运行时长、接口状态,大部分厂商基本都把基础的snmp遵循共有标准设计的。

[Unit]
Description=Prometheus exporter for SNMP-enabled devices
Documentation=https://github.com/prometheus/snmp_exporter
After=network.target

[Service]
Restart=on-failure
User=prometheus
EnvironmentFile=/etc/default/snmp-exporter
ExecStart=/usr/bin/snmp-exporter --config.file=/etc/prometheus/snmp.yml
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target

配置Prometheus及snmp_exporter

# Sample config for Prometheus.

global:
  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).
  
  # Attach these labels to any time series or alerts when communicating with
  # external systems (federation, remote storage, Alertmanager).
  external_labels:
      monitor: 'example'

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets: ['localhost:9093']

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  - job_name: 'FW'
    static_configs:
      - targets:
        - 172.31.1.253   # SNMP device.
        - 172.31.1.254
    metrics_path: /snmp
    params:
      auth: [public_v2]
      module: [if_mib]
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: 127.0.0.1:9116  # The SNMP exporter's real hostname:port.

  - job_name: 'SW'
    scrape_interval: 15s
      #scrape_timeout: 5s
    file_sd_configs:
      - files:
        - "./device/sw.yml"
        refresh_interval: 5s
    metrics_path: /snmp
    params:
      auth: [public_v2]
      module: [if_mib]
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - source_labels: [auth]          # 使用auth 替换param的auth
        target_label: __param_auth
      - source_labels: [module]        # 使用module 替换param的module
        target_label: __param_module
      - target_label: __address__
        replacement: 127.0.0.1:9116  # The SNMP exporter's real hostname:port.

我没深入研究过这个配置文件,只简单记录,最简单的配置是要监控的设备,job部分为任务名称,比如我要监控防火墙,这里就是FW,主机写到targets部分,格式如上,scrape_interval(抓取频率)和evaluation_interval(规则评估频率)的时间根据需要进行修改,不要太频繁就行。 scrape_timeout是全局抓取超时时间,这个可以不设置,设置也不建议太短,至少15s起步,如果太短,你配置的主机太多且snmp主机太弱无法及时获取到相应设备的相应,那么会导致主机不在线抓取失败。

另一个配置主机方式是直接通过外部文件获取你要监控的设备列表,我个人理解这个适用于设备很多,需要单独维护一个清单的情况,不同主机需要监控不同模块的情况,且不同主机需要不同认证方式的情况?(我暂时没遇到,也许支持?)。主要配置就是job名称及如下部分,sw.yml单独贴出。

file_sd_configs:
      - files:
        - "./device/sw.yml"

sw.yml配置文件内容:

- labels:
    mib: if_mib
  targets:
    - 172.17.1.1
    - 172.17.1.40
    - 172.17.1.41
    - 172.17.1.42
    - 172.17.1.43

snmp.yml开头加入如下格式的认证信息

# WARNING: This file was auto-generated using snmp_exporter generator, manual changes will be lost.
auths:
  public_v1:
    community: public
    security_level: noAuthNoPriv
    auth_protocol: MD5
    priv_protocol: DES
    version: 1
  public_v2:
    community: test
    security_level: noAuthNoPriv
    auth_protocol: MD5
    priv_protocol: DES
    version: 2
  public_v3:
    community: Huawei94laji
    security_level: noAuthNoPriv
    auth_protocol: MD5
    priv_protocol: DES
    version: 2
modules:
  apcups:

public_vx随便写,主要是community要包含你在设备上面配置的内容,认证协议那些都要根据自己的配置进行修改。

自定义snmp.yml文件

如果你要监控的设备模块为非公有标准,比如设备的HA状态,路由条目等这些一般都为厂商私有MIB,那么你需要自己生成MIB文件,主要通过snmp_exporter里面的generator生成文件,需要找厂商拿到MIB文件,最好获取到对应的说明文档。

需要自己编译,安装对应组件,具体看官方文档把https://github.com/prometheus/snmp_exporter/tree/main/generator

apt-get install unzip build-essential libsnmp-dev golang
git clone https://github.com/prometheus/snmp_exporter.git
cd snmp_exporter/generator
make generator mibs

配置Grafana绘图

官方库已经有人共享出一些模板了,例如ID(10523)、ID(11169),导入模板的时候填数字ID进去就可以了,其实挺好用,但是不满足我的需求,我需要自定义。使用上面模板的时候也要根据自己的job名称等信息进行修改,才能正常绘图。

添加数据源

Grafana首页-连接-数据源,点添加数据源,选择Prometheus,填入相关信息即可。

创建变量

首先是创建一个仪表盘,然后添加可视化,可以先点保存也可以不保存,点击设置按钮进入配置页面。

我定义了如图三个变量

image-20241231142147061.png

  • Device主要是获取指定任务下的设备列表
  • Interface主要获取设备下的接口
  • Interface也是获取接口,但是获取方式不一样

详细说说各参数配置:

Device:

  • Select variable type: Query
  • Name: Device
  • Show on dashboard: Nothing
  • Data source: prometheus
  • Query Type:Label Values
  • Label: instance
  • Metric:不选
  • Label filters: job=FW
  • Sort: Natural(asc)
  • Refresh: On dashboard load

    FW是我的job名称,下面有个正则匹配,不需要填,如果会正则也可以填,Sort根据自己需求选择

image-20241231143341014.png
Interface:

  • Select variable type: Query
  • Name: Interface
  • Show on dashboard: Nothing
  • Data source: prometheus
  • Query Type:Label Values
  • Label: ifName
  • Metric:不选
  • Label filters: instance=$Device
  • Sort: Natural(asc)
  • Refresh: On dashboard load
  • Selection options: Include All option

    $Device就是上面设置的Device变量

image-20241231143438528.png

Interfaces:

  • Select variable type: Query
  • Name: Interfaces
  • Show on dashboard: Nothing
  • Data source: prometheus
  • Query Type:Query result
  • Query: ifHCInOctets{instance="$Device"}
  • Regex: .*ifName="((?!fortilink|ha|l2t.root|mgmt|modem|naf.root|ssl.root|Callcenter|x1|x2|x7|x8).+?)",.*
  • Sort: Natural(asc)
  • Refresh: On dashboard load
  • Selection options: Include All option

    .*ifName="((?!fortilink|ha|l2t.root|mgmt|modem|naf.root|ssl.root|Callcenter|x1|x2|x7|x8).+?)",.* 是一个正则表达式,这里在获取ifName的同时过滤掉了从fortilink到X8的这些打头的接口名称。如果想要获取指定的网络接口名称可使用如下正则表达式.*ifName="((?:Aggregate|Bridge-Aggregation).+?)",.*比如这个表达式只获取了Aggregate和BridgeAggregation开头的接口名称

image-20241231143821740.png

上面的三个变量根据需求进行调用。

创建绘图及图表

添加运行天数

添加可视化,类型选择Stat

直接点击右边的code,进入代码模式,填入下面内容:

sysUpTime{instance="$Device"}/100/(24*3600)

也可切换到Builder模式查看可视化选择条件。Options中的Legend选择Custom,填入对应名称,比如sysUpTime,强烈建议改,否则可能在调用到这个查询结果的时候在图表上会显示一串超长的返回内容值。Formate根据图像类型选择,一般默认为Time Series。Type一般默认Range。

最右边可以改Title,Value Options中的show选择Calculate,下面选Last,Fields选择Numeric Fields,Unit自己选一个或者自己输入,这里我填入自定义的Days,其他都是细微调整,自己根据想法调整。

image-20241231144913151.png

添加可自动绘制不同接口的流量图

只需要添加一个,其他接口的图他会自动绘制出来,不需要再手动添加,这也是前面设置变量的作用,还是添加可视化,类型选择Time Series

添加A、B两个查询条件,A为入方向流量,B为出方向流量,条件如下:

irate(ifHCInOctets{instance='$Device',ifName='$Interfaces'}[5m]) * 8
irate(ifHCOutOctets{instance='$Device',ifName='$Interfaces'}[5m]) * 8
还是那句话Options中的Legend选择Custom,填入对应名称,强烈建议改。这里分别填入方向流量出方向流量,其他默认

最右边Titile填$Interfaces,下面Repeat options中的Repeat by variable选择Interfaces,Max per row根据你一行想展示几个图选择,2-4个最佳。image-20241231145513179.png

下面的Legend中的Values,选择Max和Last可显示最大值和最新值,Graph styles根据喜好选择,单位选择bits/sec(IEC),这个可能选得不对,但是单位大致对上就行。

image-20241231145541258.png

添加表格类型图

这对我来说可能是最难的一个点了,因为别人的模板用的是老的表格,没有参考意义,需要自己研究。样式如下

image-20241231145934336.png

  1. 创建可视化,选择表格。
  2. 创建查询条件

    irate(ifHCInOctets{instance='$Devices'}[5m]) * 8
    irate(ifHCOutOctets{instance='$Devices'}[5m]) * 8
    ifHighSpeed{instance='$Devices'}/1000
    ifOperStatus{instance='$Devices'}
    ifAdminStatus{instance='$Devices'}
    ifInErrors{instance="$Devices"}
    ifOutErrors{instance="$Devices"}
    ifInDiscards{instance="$Devices"}
    ifOutDiscards{instance="$Devices"}
    这里的难点是如何在一个表中显示所有接口的信息,其实很简单就是不要加ifName='$Interfaces'这个条件就行,这样查询的时候就会查询这台设备所有的接口。以上所有查询条件Options中的Format都需要选择为Table
  3. 创建数据转换条件

    由于查询出的数据有很多接口,且是单独的表格,所以需要将所有数据合并为一个表格。

    • 创建Merge Series/tables条件
    • 创建Organize fileds by name条件
    这里隐藏掉不需要展示的值,并将对应的值重命名(也可不做最终以Options中的Legend值显示),如果前面没改,那么可以建立Override添加Display name属性进行名字修改覆盖。
    • 创建Group by条件

      选择根据接口编号排序,这个选group by,其他选择计算,并选择last。这一步其实我很疑惑,我在做另一个图表的时候发现只做前两步就可以实现效果了,但是做这个图表的时候,只做前两步发现同一个接口会展现很多行数据,所以一定要 做Group by这个条件。可以根据世纪情况看要不要做。

image-20241231151123922.png

右边标题随便起,不需要repeat,单位不要选,单独设置override对值进行单位设置,并对值进行映射,不如接口管理状态查询有1、2两个值分别对应up和down。可以设置值映射,1为up,2为down,在图表中就不显示1和2而是up和down,并可以根据值的阈值设置起颜色。

image-20241231151402526.png

总结

整个图表我最需要的就是接口重复绘图和图表生成,比较难的就是图表生成,没有比较有用的参考资料。可以结合图表生成条件,自己建立更多好看的展示图。即兴记录,如有漏记、错记需自行补充更正,仅为自己备忘使用。

]]>
0 https://blog.htlac.com/archives/665.html#comments https://blog.htlac.com/feed/
wireshark抓包技巧 https://blog.htlac.com/archives/653.html https://blog.htlac.com/archives/653.html Mon, 03 Jun 2024 01:38:51 +0000 Ethan 控制抓包文件大小

如果没有特殊需求,将抓包设置为限制到每个帧80字节(byte),TCP层、网络层和数据链路层信息均可包含。
如果需要抓DNS信息,限制为350-400字节左右较为合适,可抓到完整的dns查询信息

修改时间格式

在View-Time Display Format可修改wireshark中每个包抓取到的时间,可修改为与主机一致的格式,方便查找包

修改序列号显示

Edit->Preferences->Protocols->TCP->Relative sequence numbers勾选上,方便计算序列号加减

]]>
0 https://blog.htlac.com/archives/653.html#comments https://blog.htlac.com/feed/
dux修改文章列表间隙 https://blog.htlac.com/archives/652.html https://blog.htlac.com/archives/652.html Mon, 03 Jun 2024 01:38:00 +0000 Ethan 默认dux主题的文章列表与列表之间是没有间隙的。
想要修改CSS,实现列表间隙。

在主题文件编辑器中找excerpt.php
找到如下一行代码

echo '<article class="excerpt excerpt-'.$ii. $_excerpt_text .'">';

修改为

echo '<article class="excerpt excerpt-'.$ii. $_excerpt_text .'" style="margin-bottom: 20px;">';

再牛逼点加个边框颜色,不细说了

]]>
0 https://blog.htlac.com/archives/652.html#comments https://blog.htlac.com/feed/
一次网关MAC冲突导致的网络中断故障排查 https://blog.htlac.com/archives/647.html https://blog.htlac.com/archives/647.html Tue, 10 Jan 2023 02:22:00 +0000 Ethan Symptom

网络结构为:核心交换机-汇聚交换机-接入交换机,网关地址在核心交换机上,LAN下终端无法访问网络,在检查时发现出现ping网关99.99%不通的情况。通过排查发现从核心设备管理VLAN访问汇聚交换机及接入交换机管理地址正常无丢包,但从网关到LAN终端地址能通但丢包严重达到50%左右。起初已怀疑为网关地址冲突,于是在LAN终端进行检查但未发现MAC地址变化,于是进行其他排查步骤。

Cause

90%概率为网关地址/网关MAC地址冲突,不排除有攻击者伪造网关MAC地址。

Solution

  1. 关闭接入交换机与汇聚交换机的端口,在汇聚接入交换机上单独做一个Access口测试,发现正常,无丢包,说明链路正常,故障点在接入交换机上。
  2. 在LAN终端上开启Ping网关检测,依次开启汇聚连接接入交换机的端口,并观察ping包情况,当故障交换机联通时会立刻出现丢包情况,从而定位到故障交换机。
  3. 依次关闭交换机上所有已连接的端口,发现当关闭某一个端口时,ping丢包情况消失,从而定位到故障端口。
  4. 查看MAC地址表,发现该端口下居然有一个MAC地址与核心交换机上的网关地址一模一样,这就是导致故障的原因。
  5. 处理掉交换机下非法接入设备,故障恢复。

本次故障,其实一开始的怀疑时没有问题的,就是网关冲突,但是只考虑到了IP冲突并没有考虑到MAC地址冲突,因为常见的原因是喜欢瞎搞的傻逼用户乱改IP导致冲突,一般通过查看终端的ARP表或抓包会发现MAC地址的变化,但这个是MAC地址冲突,所以无论在终端上怎么排查都没有发现MAC地址的变化。

如果一开始有考虑到MAC地址冲突,那么最开始直接查看汇聚交换机上的MAC地址表就可以定位到问题,但是生活中哪有那么多如果。上面的排查步骤只是为故障排查提供一个思路,遇到类似问题时可以如此操作,也为自己做个记录备份提醒自己。

]]>
0 https://blog.htlac.com/archives/647.html#comments https://blog.htlac.com/feed/
nginx反代plex https://blog.htlac.com/archives/643.html https://blog.htlac.com/archives/643.html Wed, 14 Dec 2022 13:06:00 +0000 Ethan #client_max_body_size 5000M; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For '$proxy_add_x_forwarded_for'; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Sec-WebSocket-Extensions $http_sec_websocket_extensions; proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key; proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version; proxy_cache off; proxy_redirect off; proxy_buffering off; location / { proxy_pass http://127.0.0.1:32400; proxy_set_header X-Forwarded-For $remote_addr; proxy_ssl_verify off; proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 86400; proxy_connect_timeout 60; } ]]> 0 https://blog.htlac.com/archives/643.html#comments https://blog.htlac.com/feed/ 修改Debian11网卡名称为eth格式 https://blog.htlac.com/archives/642.html https://blog.htlac.com/archives/642.html Fri, 09 Dec 2022 06:51:06 +0000 Ethan Symptom

Debian 11网卡名称不是eth0格式

Cause

不知道,没了解过

Solution

sed -i 's/GRUB_CMDLINE_LINUX=\"\"/GRUB_CMDLINE_LINUX=\"net.ifnames=0\ biosdevname=0\"/g' /etc/default/grub
sed -i 's/ens192/eth0/g' /etc/network/interfaces
update-grub
reboot
]]>
0 https://blog.htlac.com/archives/642.html#comments https://blog.htlac.com/feed/
Debian系Vmware缺少模块问题 https://blog.htlac.com/archives/641.html https://blog.htlac.com/archives/641.html Mon, 03 Oct 2022 02:33:25 +0000 Ethan Symptom

使用官方包安装Vmware打开后提示Before you can run Vmware, several modules must be compiled and loaded into the running kernel.

Cause

内核缺少相应模块

Solution

编译相关内核组件并安装即可

apt update
apt install build-essential linux-headers-$(uname -r)
git clone https://github.com/mkubecek/vmware-host-modules.git
cd vmware-host-modules
git checkout workstation-16.2.3   # 根据自己安装的版本调整
make
make install

再次运行VMware即可正常

]]>
0 https://blog.htlac.com/archives/641.html#comments https://blog.htlac.com/feed/
IPv6部署尝试 https://blog.htlac.com/archives/634.html https://blog.htlac.com/archives/634.html Sun, 18 Sep 2022 04:28:00 +0000 Ethan 硬件环境

出口路由:Openwork
防火墙(路由模式):Fortigate (局域网互联路由)

网络环境

局域网已有IPv4,现新增IPv6环境。
运营商分配前缀(PD):2408:3333:4444:6ab0::/60
运营商分配IPv6出口地址:2408:4444:4423:x::x/64

子网划分

需要知道的是,我们首先拿到一个IPv6前缀后,需要规划子网段,从而使得局域网互联路由下的终端都能拿到IPv6地址,当然字网划分的前提是运营商给你分配了一个小于64位长度的前缀。像这个环境中,我们假设只有两跳路由,那么我们要确保整个网络环境能分配的地址都在2408:3333:4444:6ab0::/60内。
互联网出口地址已经由运营商分配,不需要我们操心,我们需要分配Openwrt与Fortigate互联的地址段、Fortigate下的LAN地址段。因此整个前缀我们可以简单划分为两个字网:
2408:3333:4444:6ab0::/61,用于路由器互联,有点奢侈。
2408:3333:4444:6ab8::/61,用户Fortigate下的终端地址分配。

初尝试

Openwrt LAN的DHCPv6设置如下,为默认不变,其实不开DHCPv6也可以

  • 路由通告服务: 服务器模式
  • DHCPv6服务:服务器模式
  • NDP代理:禁用
  • DHCPv6模式:有状态+无状态

Openwrt LAN口设置分配前缀长度为61,IPv6地址2408:3333:4444:6ab0::1

Fortigate与Openwrt互联端口分配地址为2408:3333:4444:6ab0::2/61

Fortigate LAN口IPv6地址设置为手动2408:3333:4444:6ab8::1/61

Fortigate LAN开启DHCPv6,设置为SLAAC及手动指定DNS地址。

Fortigate配置IPv6静态默认路由,下一跳指向 2408:3333:4444:6ab0::1 ,原则上这里下一跳应该是Openwrt的链路本地地址,可以减少路由表查询。

Fortigate配置安全策略,放行所有IPv6流量。

Fortigate配置NAT策略,来自LAN的所有IPv6流量均不做NAT转换。

Openwrt配置静态IPv6路由,目的地2408:3333:4444:6ab8::/61,下一跳2408:3333:4444:6ab0::2

配置验证

  1. 从Fortigate使用默认配置ping 2408:3333:4444:6ab0::1 正常。
  2. 从Fortigate使用默认配置ping 运营商IPv6 DNS地址正常。
  3. 从Fortigate下的LAN ping 2408:3333:4444:6ab0::1正常。
  4. 从Fortigate下的LAN ping运营商IPv6 DNS地址正常。

疑难问题

  1. Fortigate下的设备无法通过DHCPv6获取IPv6地址,但可手动设置IPv6地址,指定网关后可访问公网IPv6。
    解决办法:除开启SLAAC外,在DHCPv6配置中指定有状态服务器,指定IPv6地址分配范围。
  2. 运营商IPV6前缀在家宽环境下经常会变,导致静态配置IPv6地址无法使用。
    解决办法:待研究IPv6 Prefix delegation可能可以解决。
]]>
0 https://blog.htlac.com/archives/634.html#comments https://blog.htlac.com/feed/
debian11 &amp; nextcloud 23 &amp; mariadb 10.6.5 https://blog.htlac.com/archives/627.html https://blog.htlac.com/archives/627.html Sun, 30 Jan 2022 14:26:00 +0000 Ethan 总的来说坑还是比较多,建议查看官方配置手册一个个修改,数据库最主要的坑还是4047 InnoDB refuses to write tables with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE.

报: 4047 InnoDB refuses to write tables with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE.
解决办法:
编辑//etc/mysql/my.cnf


[client]
default-character-set = utf8mb4

[mysqld]
character_set_server = utf8mb4
collation_server = utf8mb4_general_ci
transaction_isolation = READ-COMMITTED
binlog_format = ROW
innodb_large_prefix=on
innodb_file_format=barracuda
innodb_file_per_table=1
innodb_compression_default = off

[server]
skip_name_resolve = 1
innodb_buffer_pool_size = 128M
innodb_buffer_pool_instances = 1
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 32M
innodb_max_dirty_pages_pct = 90
query_cache_type = 1
query_cache_limit = 2M
query_cache_min_res_unit = 2k
query_cache_size = 64M
tmp_table_size= 64M
max_heap_table_size= 64M
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
innodb_read_only_compressed=OFF

编辑etc/mysql/mariadb.conf.d/50-server.cnf

[mysqld]
innodb_read_only_compressed=OFF

官方手册

]]>
0 https://blog.htlac.com/archives/627.html#comments https://blog.htlac.com/feed/
Ansible食用心得 https://blog.htlac.com/archives/626.html https://blog.htlac.com/archives/626.html Sun, 23 Jan 2022 12:18:00 +0000 Ethan Ansible是啥
Red Hat® Ansible® Automation Platform is a foundation for building and operating automation across an organization. The platform includes all the tools needed to implement enterprise-wide automation.

以上信息来自于Ansible官网,简单的说Ansible是redhat出品的一个用于自动化运维的工具,可以用于管理服务器、网络设备之类的,当然了仅限于Cisco、F5等知名产品,至于某些呵呵支不支持我就不知道了,反正官网毛都没提。

安装Ansible

鉴于安装很简单,一笔带过,RH系直接一条命令。

yum -y install ansible

开始前要了解的几个名词

官网手册只有英文版,貌似有好心人翻译了中文版本但是我不记得地址多少了,而且相对来说版本较低,建议看官方版本手册;看不懂英文的建议使用Google Chrome浏览器,对没错,就是那个全世界最好用没有之一的浏览器进行浏览,可以全文英译中;在此我仅仅只对我自己肤浅的了解做一个总结,方便日后自己翻阅。

inventory(仓库)

inventory包含了你所需要自动化管理的服务器、设备,以IP或者域名标识,可以对其进行分组,其默认文件是/etc/ansible/hosts,该文件属于一个ini配置文件,目前可以使用号称更加符合人类阅读的yml文件,保存目录也是/etc/ansbile/,名字自定义,文件拓展名可以是yml、yaml、json或者是不带拓展名,你也可以在该目录下建立不同的文件夹用以区分不同的组,官方也是这样建议的,不同的组建议使用单独的一个仓库文件存储。

hosts文件内容参考如下

# 定义单台设备
192.168.1.1
abc.cn
#定义一个组,名为group1,包含两台主机
[group1]
192.168.1.2
bbc.cn
#定义一个组,名为group2,并且我对其中IP为10.0.0.62的主机单独定义了ansible连接主机时使用的用户名及端口号
[group2]
192.168.1.3
ccc.cn
10.0.0.62 ansible_user=ubuntu ansible_port=222

yml官方内容示例如下:

all:
  hosts:
    mail.example.com:
  children:
    webservers:
      hosts:
        foo.example.com:
        bar.example.com:
    dbservers:
      hosts:
        one.example.com:
        two.example.com:
        three.example.com:

这种结构层次分明,但是其实我觉得ini方式更加容易理解

all:
  hosts:
  children:
    testgroup1:
      hosts:
        10.0.0.1:
    testgroup2:
      hosts:
        10.0.0.2:
        10.0.0.3:
    testgroup3:
      hosts:
        10.0.0.4:
          ansible_user:ubuntu
          ansible_port:9888

tasks(任务)

没啥好说的,你用ansible执行了一个命令就是做了一个任务

playbook (剧本)

顾名思义,如果说Ansible是一台电脑,那么playbook就是电脑上所运行的程序,你所需要实现的自动化操作,全都是由playbook来控制,playbook详细记录了你所要实现的任务名称,任务操作,要操作的对象等,Ansible必须按照你所编写的脚本表演,一个yaml的剧本里面可以包含多个剧情,一个剧情可以有多个任务。你所编写的playbook需要以yaml格式保存,放在哪里无所谓,只要你知道就行,其大概结构如下

#剧本名称
- name : change server password
#剧本所需要操作的对象,这里是group1
  hosts: group1
  gather_facts: False
#剧本任务
  tasks:
#任务名称
    - name: chgpwd
#具体操作,这里调用了chpass模块对系统用户进行密码修改
      user: name={{ item.name }} password={{ item.chpass | password_hash('sha512') }} update_password=always
      with_items:
          - { name: 'root', chpass: 'sdfsdfsdfds' }


- name : change server1 password
  hosts: group2
  gather_facts: False
  tasks:
    - name: chgpwd
      user: name={{ item.name }} password={{ item.chpass | password_hash('sha512') }} update_password=always
      with_items:
          - { name: 'root', chpass: 'aabcc' }
          - { name: 'ubuntu', chpass: 'aabbdd' }

Modules (模块)

本来这块应该放前面讲,但是又要先知道playbook是啥玩意,所以放到这里来说,模块组成了Ansible的一部分,是Ansible的一个功能,比如其包含的shell模块、ping模块等;linux模块可以看这个,其他模块看这里
例如我要实现所有的主机执行ping命令那么我可以使用如下命令

ansible all -m ping

执行一个命令

ansible all -a "/bin/echo hello"

执行一个shell命令

ansible group1 -m shell -a "yum -y update"

正式部署使用Ansbile

知道Ansible大概的概念和相关调用方法后,我们就可以使用其进行自动化运维操作,这里我以批量修改主机密码为例,对我目前用到的东西进行一个描述。

添加免密码登录主机

Ansible管理节点生成公钥,上传到被管理节点

ssh-keygen -t rsa
ssh-copy-id root@10.0.0.1

这里如果有大量的主机需要添加,我还写了一个shell脚本方便使用

PATH=/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

array_server=(
10.0.0.1 \
10.0.0.2 \
)

array_server1=(
 \
)
passwd="halksdjklsdjv"

#ssh-keygen -t rsa
echo "Start adding server..."

for rhel in `cat /root/1.txt`
do
    ping ${rhel} -c 1 > /dev/null 2>&1
    if [ $? == 0 ];then
    expect <<-EOF
        spawn ssh-copy-id root@${rhel}
        expect {
            "yes/no" { send "yes\n";exp_continue }
            "password" { send "$passwd\n" }
        }
        expect eof
    EOF
    echo "${rhel} add success." >> /root/success.log 2>&1
    else
    echo "${rhel} Can't connect to server, skip." >> /root/failed.log 2>&1
    fi
done

for debian in `cat /root/2.txt`
do
    ping ${debian} -c 1 > /dev/null 2>&1
    if [ $? == 0 ];then
        expect <<-EOF
                spawn ssh-copy-id ubuntu@${Debian}
                expect {
                        "yes/no" { send "yes\n";exp_continue }
                        "password" { send "$passwd\n" }
                }
                expect eof
        EOF
    echo "${debian} add success." >> /root/success.log 2>&1
    else
    echo "${debian} Can't connect to server, skip." >> /root/failed.log 2>&1
    fi
done

上面的脚本针对root账户和非root账户分别将服务器放到1.txt和2.txt就可以使用,以前使用的是数组,后面发现数组太麻烦,就改了改,代码没删没注释,懒得管了

PATH=/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

array_server=(
10.0.0.41 \
)

array_server1=(
 \
)

user=$1
passwd=$2

#ssh-keygen -t rsa
echo "Start adding server..."

for rhel in `cat /root/1.txt`
do
        ping ${rhel} -c 1 > /dev/null 2>&1
        if [ $? == 0 ];then
        expect <<-EOF
                spawn ssh-copy-id $user@${rhel}
                expect {
                        "yes/no" { send "yes\n";exp_continue }
                        "password" { send "$passwd\n" }
                }
                expect eof
        EOF
        echo "${rhel} add success." >> /root/success.log 2>&1
        else
        echo "${rhel} Can't connect to server, skip." >> /root/failed.log 2>&1
        fi
done

上面的代码需配合参数使用,用于自动填充的账户和密码,密码用双引号包含,避免特殊符号无法转义。

生成仓库

将需要自动运维的服务器设备放到yml文件或者hosts的ini文件中,并做好分组(建议),以便ansible引用。

创建playbook

编写需要自动化的脚本,例如修改密码的剧本,当然如果不使用剧本,你用ad-hoc命令也可以。

- name : change testgroup password
  hosts: testhost
  gather_facts: False
  tasks:
    - name: chgpwd
      user: name={{ item.name }} password={{ item.chpass | password_hash('sha512') }} update_password=always
      with_items:
          - { name: 'root', chpass: 'sjskdjflsjf' }

调用playbook完成自动运维

假设inventory配置文件为/etc/Ansible/server.yml使用以下命令调用剧本完成自动化任务:

ansible-playbook -i /etc/Ansible/server.yml  xxx.yml

确认剧本执行结果

执行完成后会有相应反馈,如果成功,则状态为ok,否则为就是失败

]]>
0 https://blog.htlac.com/archives/626.html#comments https://blog.htlac.com/feed/