logo
logo

使用 DeepFlow 开启 DNS 可观测性

李倩, 嘉炜 2022-11-15

目前针对 DNS 监控的 Grafana Dashboard 并不多,使用率较高的 Grafana CoreDNS 只适用于 K8s 环境,对于云服务器、物理硬件模式下的 DNS 监控也并不通用;同时,对于应用研发人员想定位 DNS 查询异常或者时延问题时,CoreDNS 的 Dashboard 仅提供 DNS 服务端视角,无法从应用视角出发来分析问题,只能依赖自身代码增加了 DNS 日志。

明确这些问题后,我们基于 DeepFlow 构建了对一个高效可配置无侵入面向应用的 DNS 监控面板,可监控 DNS 服务的网络异常、吞吐、时延,以及访问日志,以快速定位性能瓶颈和排查故障原因。部署了 DeepFlow 之后,deepflow-agent 会自动采集所在节点上的可观测数据,我们基于这些数据构建了一个 Dashboard,内容包括:

  • Overview
  • Delay
  • Error
  • Request
  • Log Analysis

前往我们的在线 Demo 也可快速体验 Dashboard

0x0: Dashboard 介绍

接下来,详细介绍下 Dashboard 的使用

进入 Dashboard 后,可通过变量来控制需要分析的 DNS 服务端,下面详细说下变量的使用方式:

  • ①:DNS 服务端部署在 K8s 环境中,例如 CoreDNS,使用 cluster/dns_service/dns_wildcard 变量
    • cluster:选择 DNS 服务端所部署的 K8s 集群
    • dns_service:选择 DNS 服务端对应的 K8s 服务名
    • dns_wildcard:通过通配符的形式筛选 dns_service
  • ②:DNS 服务端部署在云服务器环境中,使用 dns_chost 变量
    • 特别说明:此时需要将 cluster/dns_service 设置为Disabled
  • ③:使用外部的 DNS 服务端,例如使用运营商提供的114.114.114.114,则在 dns_ip 变量输入对应的 IP 即可
    • 特别说明:此时需要将 cluster/dns_service/dns_chost 设置为Disabled
  • ④:DeepFlow 可在多个位置采集数据,可通过 tap_side 来控制需要查看的数据统计位置,位置点的详细说明,可参考文档

模板变量说明模板变量说明

设置好变量后,接下来就可以利用 Dashboard 来分析 DNS 了,通过 Overview 可快速了解 DNS 请求总量有无异常存在应用的 DNS 访问拓扑DNS 响应时延的整体分布情况,得到大概总览情况后,可以结合 ErrorDelayRequest 模块中的曲线快速分析问题发生的时间点,然后利用 client 分组,可快速得到触发问题发生的客户端服务

OverviewOverview

ErrorError

Delay + RequestDelay + Request

接下来可以利用 Log_Analysis 模块来详细分析发生问题的客户端服务的 DNS 请求,分析之前,需要先设置 client_for_Log_Analysisstatus_for_Log_Analysis 变量

  • ⑤ client_for_Log_Analysis:输入在前面模块得到的客户端服务
  • ⑥ status_for_Log_Analysis:确定需要分析的 DNS 请求的状态
  • ⑦ domain_for_Log_Analysis:输入需要分析的 DNS 请求的域名

模板变量说明模板变量说明

通过 Log_Analysis 模块,可快速得到存在问题的 TOP N ClientRequest DomainRequest TypeResponse Desc 以及客户端服务访问 DNS 的整个时延分布

Log_AnalysisLog_Analysis

接下来,让我们结合实际案例,来体验一下 DNS Dashboard 给我们带来的高效分析能力。

0x1: 案例1 - 无效内部域名解析

现象

我们的集群里的应用规模不大,理论上 DNS 请求不会太多,但我们打开 DNS Dashboard 后,发现有大量 DNS 查询请求,且有访问异常:

Client Request Log ErrorClient Request Log Error

其中有较多 DNS 客户端异常,响应码为 0x3,错误描述是:Non-Existent Domain,意味着应用访问了不存在的域名。(更多的异常定义可见 DeepFlow-数据库字段定义

我们通过异常排序,查看访问无效 Top10 域名,发现大量 DNS 请求后缀包含了 cluster.local,而这是 k8s 自动填充的搜索域:

Client Request Domain TopN ErrorClient Request Domain TopN Error

原因分析

我们结合 k8s 的 DNS 原理来分析问题原因。首先,一个典型的 k8s Pod 中 resolv.conf 文件的内容如下:

1
2
3
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5

这里有三个配置,search 是域名检索的搜索域,nameserver 是集群内的 DNS 服务地址,options 是自定义选项,其中 ndots=5,意味着当一个域名中包含.的数量小于 5 时,会优先解析为内部域名,并按照 search 的顺序依次添加搜索域后缀来检索,如果它依然无法被解析,才会把这个域名当作外部域名来解析。
那为什么 k8s 的 ndots 默认配置是 5 呢?Issue#33554 也做出了解释,简单来说:

  1. 同命名空间下,形如 $service 的域名要被优先解析为内部域名,所以 ndots>=1,并在搜索域 $namespace.svc.$zone 下搜索。
  2. 跨命名空间下,形如 $service.$namespace 的域名要被优先解析为内部域名,所以 ndots>=2,并在搜索域 svc.$zone 下搜索。
  3. 访问非 Service Name 时,形如 $name.$namespace.svc 的域名要被优先解析为内部域名,所以 ndots>=3,并在搜索域 $zone 下搜索。
  4. 对于 StatefulSet 类型的应用,由于需要支持形如 $name-0.service.$namespace.svc 的域名内部解析,所以 ndots>=4。
  5. 对于形如 _$port._$proto.$service.$namespace.svc 的 SRV Record 要被优先解析为内部域名,所以 ndots>=5。

综上,k8s 的 resolv.conf 中 ndots 默认值是 5 。但这符合我们的使用场景吗?我们要访问的域名是一个.小于 5 的外部域名,但它被解析为内部域名,并尝试通过 $url.default.svc.cluster.local / $url.svc.cluster.local / $url.cluster.local 的顺序来解析,最后才去访问 $url 本身,所以产生了大量的异常记录。

修复建议

要解决这个问题,有几个可选的方案:

  1. k8s 文档中 Pod DNS 配置一节,只需要修改 Pod 的 DNS 策略,定义 ndots=2,这样就可以优先将域名解析为外部域名,弊端在于这样反而会使得内部域名的解析变慢。
  2. 把访问的外部域名修改为 FQDN,比如我们要访问的是 vpc.tencentcloudapi.com,修改为 vpc.tencentcloudapi.com.,这样可以直接访问域名,不会依次检索搜索域。
  3. CoreDNS 使用 autopath 插件,减少搜索次数,但这依赖于 API Watch 机制,会使得 CoreDNS 增加内存消耗。
  4. 使用 Node LocalDNS,增加 DNS 解析性能,减少 CoreDNS 压力,但同样的,它需要使用内存来做 DNS 缓存查询,增加了内存消耗。

经过权衡,方案(2)对集群的侵入性和修改难度是最低的,效果也比较理想,所以我们采用方案(2)达成了目标。

0x2: 案例2 - 对已失效服务的依赖

现象

同样通过 DNS Request Log 分析,我们发现还有大量的 Non-Existent Domain 异常,且它不是访问外部域名:

Client Request Domain TopNClient Request Domain TopN

原因分析

集群里没有 zipkin 的 Service,按照上述的 k8s 的 DNS 原理分析,在访问域名的时候同样会尝试按搜索域顺序依次访问,造成了不小的 CoreDNS 压力,这说明应用的配置有错误,尝试访问无效的服务,导致冗余的开销

修复建议

检查代码或配置中是否还在访问失效的服务,去掉配置后恢复正常。

0x3: 后续规划

我们目前在制作一批 Dashboard,包括:Nginx、MySQL/PostgreSQL、HTTP、Dubbo/gRPC、Kafka/MQTT、TCP/UDP/IP 等,希望能带来社区高度自动化高精度的可观测性体验,期待有社区的小伙伴能加入一起。

0x4: 什么是 DeepFlow

DeepFlow 是云杉网络开发的一款可观测性产品,旨在为复杂的云基础设施及云原生应用提供深度可观测性。DeepFlow 基于 eBPF 实现了应用性能指标、分布式追踪、持续性能剖析等观测信号的零侵扰Zero Code)采集,并结合智能标签SmartEncoding)技术实现了所有观测信号的全栈Full Stack)关联和高效存取。使用 DeepFlow,可以让云原生应用自动具有深度可观测性,从而消除开发者不断插桩的沉重负担,并为 DevOps/SRE 团队提供从代码到基础设施的监控及诊断能力。

GitHub 地址:https://github.com/deepflowio/deepflow

访问 DeepFlow Demo,体验高度自动化的可观测性新时代。