How Openyurt runs the business pod in edge scenarios
1.背景介绍
OpenYurt是业界首个非侵入的边缘计算云原生开源项目,通过边缘自治,云边协同,边缘单元化,边缘流量闭环等能力为用户提供云边一体化的使用体验。不少用户在使用OpenYurt的时候,经常需要把存量的使用InClusterConfig访问kube-apiserver的Pod通过OpenYurt迁移到边缘环境中。如下图所示:
在OpenYurt集群中,提供了使用InClusterConfig的业务Pod零修改就可以运行在边缘环境的能力。
2.面临挑战
使用InClusterConfig的业务Pod在边缘环境中运行,需要解决如下问题:
-
问题一:Pod通过InClusterConfig地址访问kube-apiserver,节点上默认网络规则(iptables/ipvs)将会把请求转发到kube-apiserver的PodIP,同时云端与边缘位于不同网络平面,边缘是无法访问到云端的PodIP。所以边缘业务Pod无法通过InClusterConfig访问到kube-apiserver。
-
问题二:在解决问题一后,如果云边网络断开时业务Pod容器出现重启等状况,边缘Pod将无法从kube-apiserver获取到业务配置,这会影响到业务Pod的重启运行。
3.解决方案
从上述问题可以看出,我们需要无感知的调整边缘pod的访问地址,同时需要在边缘环境中缓存业务配置,保证云边断网时也可以利用边缘缓存业务配置,保证云边断网时也可以利用边缘缓存来获取业务Pod的配置信息。具体解决方案如下;
3.1边缘Pod访问的云端endpoint优化
-
Pod通过InClusterConfig访问kube-apiserver,源码如下:
func InClusterConfig() (*Config, error) { const ( tokenFile = "/var/run/secrets/kubernetes.io/serviceaccount/token" rootCAFile = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" // 通过Kuberentes service对应的环境变量来获取访问地址 host, port := os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT") if len(host) == 0 || len(port) == 0 { return nil, ErrNotInCluster } // skip some code... return &Config{ Host: "https://" + net.JoinHostPort(host, port), TLSClientConfig: tlsClientConfig, BearerToken: string(token), BearerTokenFile: tokenFile, }, nil }
-
因此想无感知调整边缘Pod访问的云端endpoint,只需要无侵入修改Pod的KUBERNETES_SERVICE_HOST和KUBERNETE_SERVICE_PORT两个环境变量或者修改kubernetes service地址。解决方案如下:
-
解决方案一:增加一个admission controller在边缘Pod创建时把kube-apiserver的公网地址自动注入到Pod的环境变量KUBERNETES_SERVICE_HOST和KUBERNETE_SERVICE_PORT
-
解决方案二:边缘数据过滤框架中增加一个fillter yurthub的边缘数据过滤框架类似于admission controller ,专门用于边缘场景下在边缘应用无感知的状态下,无侵入的修改或者过滤云端返回的数据。目前支持的过滤器有:Masterservice,servicetopology,discardcloudservice等
-
解决方案对比:
解决方案一
-