一文读懂 SuperEdge 分布式健康检查 (边端)

本文深入探讨了SuperEdge如何通过分布式健康检查机制应对边缘计算中的网络不稳定性,保证服务稳定。作者杜杨浩介绍了edge-health-daemon组件的工作原理,包括同步节点列表、执行检查、通信和投票四个部分,以及如何通过云端的edge-health-admission webhook调整节点状态,防止误判导致的服务中断。
摘要由CSDN通过智能技术生成

作者:杜杨浩,腾讯云高级工程师,热衷于开源、容器和Kubernetes。目前主要从事镜像仓库、Kubernetes集群高可用&备份还原,以及边缘计算相关研发工作。

前言

SuperEdge 是基于原生 Kubernetes 的边缘容器管理系统。该系统把云原生能力扩展到边缘侧,很好的实现了云端对边缘端的管理和控制,极大简化了应用从云端部署到边缘端的过程。同时SuperEdge设计了分布式健康检查机制规避了云边网络不稳定造成的大量pod迁移和重建,保证了服务的稳定。

边缘计算场景下,边缘节点与云端的网络环境十分复杂,连接并不可靠,在原生 Kubernetes 集群中,会造成 apiserver 和节点连接的中断,节点状态的异常,最终导致pod的驱逐和 endpoint 的缺失,造成服务的中断和波动,具体来说原生 Kubernetes 处理如下:

  • 失联的节点被置为 ConditionUnknown 状态,并被添加 NoSchedule 和 NoExecute 的 taints
  • 失联的节点上的 pod 被驱逐,并在其他节点上进行重建
  • 失联的节点上的 pod 从 Service 的 Endpoint 列表中移除

因此,边缘计算场景仅仅依赖边端和 apiserver 的连接情况是不足以判断节点是否异常的,会因为网络的不可靠造成误判,影响正常服务。而相较于云端和边缘端的连接,显然边端节点之间的连接更为稳定,具有更高的参考价值,因此 superedge 提出了边缘分布式健康检查机制。该机制中节点状态判定除了要考虑 apiserver 的因素外,还引入了节点的评估因素,进而对节点进行更为全面的状态判断。通过这个功能,能够避免由于云边网络不可靠造成的大量的pod迁移和重建,保证服务的稳定

具体来说,主要通过如下三个层面增强节点状态判断的准确性:

  • 每个节点定期探测其他节点健康状态
  • 集群内所有节点定期投票决定各节点的状态
  • 云端和边端节点共同决定节点状态

而分布式健康检查最终的判断处理如下:

edge-health-daemon 源码分析

在深入源码之前先介绍一下分布式健康检查的实现原理,其架构图如下所示:

Kubernetes 每个 node 在 kube-node-lease namespace 下会对应一个 Lease object,kubelet 每隔 node-status-update-frequency 时间(默认10s)会更新对应node的 Lease object

node-controller 会每隔 node-monitor-period 时间(默认5s)检查 Lease object 是否更新,如果超过 node-monitor-grace-period 时间(默认40s)没有发生过更新,则认为这个 node 不健康,会更新 NodeStatus(ConditionUnknown)

而当节点心跳超时(ConditionUnknown)之后,node controller 会给该 node 添加如下 taints:

spec:
  ...
  taints:
  - effect: NoSchedule
    key: node.kubernetes.io/unreachable
    timeAdded: "2020-07-02T03:50:47Z"
  - effect: NoExecute
    key: node.kubernetes.io/unreachable
    timeAdded: "2020-07-02T03:50:53Z"

同时,endpoint controller 会从 endpoint backend 中踢掉该母机上的所有 pod

对于打上 NoSchedule taint 的母机,Scheduler 不会调度新的负载在该 node 上了;而对于打上 NoExecute(node.kubernetes.io/unreachable) taint 的母机,node controller 会在节点心跳超时之后一段时间(默认5mins)驱逐该节点上的 pod

分布式健康检查边端的 edge-health-daemon 组件会对同区域边缘节点执行分布式健康检查,并向 apiserver 发送健康状态投票结果(给 node 打 annotation)

此外,为了实现在云边断连且分布式健康检查状态正常的情况下:

  • 失联的节点上的 pod 不会从 Service 的 Endpoint 列表中移除
  • 失联的节点上的 pod 不会被驱逐

还需要在云端运行 edge-health-admission(Kubernetes mutating admission webhook),不断根据 node edge-health annotation 调整 kube-controller-manager 设置的 node taint(去掉NoExecute taint)以及 endpoints (将失联节点上的 pods 从 endpoint subsets notReadyAddresses 移到 addresses中),从而实现云端和边端共同决定节点状态

本章将主要介绍 edge-health-daemon 原理,如下为 edge-health-daemon 的相关数据结构:

type EdgeHealthMetadata struct {
    *NodeMetadata
    *CheckMetadata
}
type NodeMetadata struct {
    NodeList []v1.Node
    sync.RWMutex
}
type CheckMetadata struct {
    CheckInfo            map[string]map[string]CheckDetail // Checker ip:{Checked ip:Check detail}
    CheckPluginScoreInfo map[string]map[string]float64     // Checked ip:{Plugin name:Check score}
    sync.RWMutex
}
type CheckDetail struct {
    Normal bool
    Time   time.Time
}
type CommunInfo struct {
    SourceIP    string                 // ClientIP,Checker ip
    CheckDetail map[string]CheckDetail // Checked ip:Check detail
    Hmac        string
}

含义如下:

  • NodeMetadata:为了实现分区域分布式健康检查机制而维护的边缘节点 cache,其中包含该区域内的所有边缘节点列表 NodeList
  • CheckMetadata:存放健康检查的结果,具体来说包括两个数据结构:
    • CheckPluginScoreInfo:为Checked ip:{Plugin name:Check score}组织形式。第一级 key 表示:被检查的ip;第二级 key 表示:检查插件的名称;value 表示:检查分数
    • CheckInfo:为Checker ip:{Checked ip:Check detail}组织形式。第一级key表示:执行检查的ip;第二级key表示:被检查的ip;value表示检查结果 CheckDetail
  • CheckDetail:代表健康检查的结果
    • Normal:Normal 为 true 表示检查结果正常;false 表示异常
    • Time:表示得出该结果时的时间,用于结果有效性的判断(超过一段时间没有更新的结果将无效)
  • CommunInfo:边缘节点向其它节点发送健康检查结果时使用的数据,其中包括:
    • SourceIP:表示执行检查的ip
    • CheckDetail:为Checked ip:Check detail组织形式,包含被检查的ip以及检查结果
    • Hmac:SourceIP 以及 CheckDetail 进行 hmac 得到,用于边缘节点通信过程中判断传输数据的有效性(是否被篡改)

edge-health-daemon 主体逻辑包括四部分功能:

  • SyncNodeList:根据边缘节点所在的 zone 刷新 node cache,同时更新 CheckMetadata相关数据
  • ExecuteCheck:对每个边缘节点执行若干种类的健康检查插件(ping,kubelet等),并将各插件检查分数汇总,根据用户设置的基准线得出节点是否健康的结果
  • Commun:将本节点对其它各节点健康检查的结果发送给其它节点
  • Vote:对所有节点健康检查的结果分类,如果某个节点被大多数(>1/2)节点判定为正常,则对该节点添加superedgehealth/node-health:true annotation,表明该节点分布式健康检查结果为正常;否则,对该节点添加superedgehealth/node-health:false annotation,表明该节点分布式健康检查结果为异常

下面依次对上述功能进行源码分析:

1、SyncNodeList

SyncNodeList 每隔 HealthCheckPeriod 秒(health-check-period 选项)执行一次,会按照如下情况分类刷新 node cache:

  • 如果 kube-system namespace 下不存在名为 edge-health-zone-config的configmap,则没有开启多地域探测,因此会获取所有边缘节点列表并刷新 node cache
  • 否则,如果 edge-health-zone-config 的 configmap 数据部分 TaintZoneAdmission 为 false,则没有开启多地域探测,因此会获取所有边缘节点列表并刷新 node cache
  • 如果 TaintZoneAdmission 为 true,且 node 有"superedgehealth/topology-zone"标签(标示区域),则获取"superedgehealth/topology-zone" label value 相同的节点列表并刷新 node cache
  • 如果 node 没有"superedgehealth/topology-zone" label,则只会将边缘节点本身添加到分布式健康检查节点列表中并刷新 node cache(only itself)
func (ehd *EdgeHealthDaemon) SyncNodeList() {
    // Only sync nodes when self-located found
    var host *v1.Node
    if host = ehd.metadata.GetNodeByName(ehd.cfg.Node.HostName); host == nil {
        klog.Errorf("Self-hostname %s not found", ehd.cfg.Node.HostName)
        return
    }
    // Filter cloud nodes and retain edge ones
    masterRequirement, err := labels.NewRequirement(common.MasterLabel, selection.DoesNotExist, []string{})
    if err != nil {
        klog.Errorf("New masterRequirement failed %+v", err)
        return
    }
    masterSelector := la
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值