苹果|OpenYurt 之 Yurthub 数据过滤框架解析( 三 )


byte) ([
byte error) { list err := fh.serializer.Decode(b) if err != nil || list == nil { klog.Errorf(\"skip filter failed to decode response in ObjectResponseFilter of discardCloudServiceFilterHandler %v\" err) return b nilserviceList ok := list.(*v1.ServiceList) if ok { var svcNew [
v1.Service for i := range serviceList.Items { nsName := fmt.Sprintf(\"%s/%s\" serviceList.Items[i
.Namespace serviceList.Items[i
.Name) // remove lb service if serviceList.Items[i
.Spec.Type == v1.ServiceTypeLoadBalancer { if serviceList.Items[i
.Annotations[filter.SkipDiscardServiceAnnotation
!= \"true\" { klog.V(2).Infof(\"load balancer service(%s) is discarded in ObjectResponseFilter of discardCloudServiceFilterHandler\" nsName) continue// remove cloud clusterIP service if _ ok := cloudClusterIPService[nsName
; ok { klog.V(2).Infof(\"clusterIP service(%s) is discarded in ObjectResponseFilter of discardCloudServiceFilterHandler\" nsName) continuesvcNew = append(svcNew serviceList.Items[i
)serviceList.Items = svcNew return fh.serializer.Encode(serviceList)return b nil 过滤框架现状 目前的过滤框架比较僵硬 , 将资源过滤硬编码至代码中 , 只能是已注册的资源才能进行相应的过滤为了解决这个问题 , 需要对过滤框架进行相应的改造 。
解决方案
方案一:
使用参数或者环境变量的形式自定义过滤配置 , 但是这种方式有以下弊端:
1、配置复杂需要将所以需要自定义的配置写入到启动参数或者读取环境变量 例如下格式:
--filter_serviceTopology=coredns/endpointslices#listkube-proxy/services#list;watch --filter_endpointsFilter=nginx-ingress-controller/endpoints#list;watch 2、无法热更新 , 每次修改配置都需要重启 Yurthub 生效 。
方案二:
1、使用 configmap 的形式自定义过滤配置降低配置复杂度配置格式(user-agent/resource#listwatch) 多个资源通过逗号隔开 。 如下所示:
filter_endpoints: coredns/endpoints#list;watchtest/endpoints#list;watchfilter_servicetopology: coredns/endpointslices#list;watchfilter_discardcloudservice: \"\"filter_masterservice: \"\" 2、利用 Informer 机制保证配置实时生效
综合以上两点在 OpenYurt 中我们选择了解决方案二 。
开发过程中遇到的问题 在边缘端 Informer watch 的 api 地址是 Yurthub 的代理地址 , 那么 Yurthub 在启动代理端口之前都是无法保证 configmap 的数据是正常的 。 如果在启动完成之后 addons 的请求先于 configmap 数据更新 这个时候会导致数据在没有过滤的情况下就返回给了 addons , 这样会导致很多预期以外的问题 。
为了解决这个问题 我们需要在 apporve 中加入 WaitForCacheSync 保证数据同步完成之后才能返回相应的过滤数据 , 但是在 apporve 中加入 WaitForCacheSync 也直接导致 configmap 进行 watch 的时候也会被阻塞 , 所以需要在 WaitForCacheSync 之前加入一个白名单机制 , 当 Yurthub 使用 listwatch 访问 configmap 的时候我们直接不进行数据过滤 , 相应的代码逻辑如下:
func (a *approver) Approve(comp resource verb string) bool { if a.isWhitelistReq(comp resource verb) { return falseif ok := cache.WaitForCacheSync(a.stopCh a.configMapSynced); !ok { panic(\"wait for configMap cache sync timeout\")a.Lock() defer a.Unlock() for _ requests := range a.nameToRequests { for _ request := range requests { if request.Equal(comp resource verb) { return truereturn false 总结 1、通过上述的扩展能力可以看出 , YurtHub 不仅仅是边缘节点上的带有数据缓存能力的反向代理 。 而是对 Kubernetes 节点应用生命周期管理加了一层新的封装 , 提供边缘计算所需要的核心管控能力 。
2、YurtHub 不仅仅适用于边缘计算场景 , 其实可以作为节点侧的一个常备组件 , 适用于使用 Kubernetes 的任意场景 。 相信这也会驱动 YurtHub 向更高性能 , 更高稳定性发展 。

相关经验推荐