Kubernetes 与 OpenYurt 无缝转换(命令式)
作者:adamzhoul,OpenYurt 成员
打开 openYurt 的 README.md,在简单介绍之后就是 Getting started:
yurtctl convert --provider [minikube|kubeadm|kind] // To convert an existing Kubernetes cluster to an OpenYurt cluster yurtctl revert // To uninstall and revert back to the original cluster settings
简单一行命令就可体验 OpenYurt 了,感觉非常方便。
稍等!为什么是 convert/revert 而不是 install/uninstall ?
这个命令对集群做了什么?
看来,在执行它之前有必要搞清楚它到底做了什么。
yurtctl convert 到底做了些什么?
核心流程
跟随 openYurt 源代码(详情请见文末相关链接),梳理了 convert 的核心流程:
可见 1、2 并没有什么特别,只是常规的服务部署。
3,则是对原有 k8s 系统组件的操作,需要特别注意。
4,节点转换看着也并不复杂,却对边缘至关重要。****
disable nodelifecycle controller 做了什么
工作内容:
1. 查询控制面节点
2. 创建 job,通过 nodeName: {{.nodeName}}
确保 job 的 pod 调度到对应 node 上执行(通过 nsenter 的方式执行,修改宿主机上文件)。
3. sed -i 's/--controllers=/--controllers=-nodelifecycle,/g' /etc/kubernetes/manifests/kube-controller-manager.yaml
查看 kube-controller-manager.yaml
... containers: - command: - kube-controller-manager - --allocate-node-cidrs=true ... - --controllers=-nodelifecycle,*,bootstrapsigner,tokencleaner ...
可见,上面的一系列操作最终就是修改了 kube-controller-manager 的启动命令。
查看 kube-controller-manager 启动参数说明:
--controllers 代表需要开启的controller列表\
可见,sed 命令就是去掉了 nodelifecycle 这个 controller。
那,nodelifecycle controller 是做什么的?
简单来说:
1. 不断监听,kubelet 上报上来的 node 信息
2. 如果某个 node 状态异常,或者说长时间没有上报等
2.1 驱逐这个 node 节点或者其他 ---> 导致上面的 pod 被重新调度
可见,对于处于弱网环境的边缘节点,很容易就命中异常状态,导致 node 被驱逐,pod 被重新调度。
所以这里把它去掉了。使用 yurt-controller-manager 来代替它。
即使节点心跳丢失,处于自治模式的节点中的 pod 也不会从 APIServer 中驱逐。
注:这里自治模式的节点,指的就是边缘节点。我们通常会通过加 annotation 的方式把节点标记为自治节点。
节点转换是怎么实现的,云端节点和边缘节点有什么差异?
同样,是通过跑 job 的方式,在目标宿主机上下文中执行相关操作。
不过,相比于暴力使用 nsenter,这里用了更加优雅的方式。通过将宿主机根路径 volume 挂载到容器里的方式。
kubelet 的修改
在文件/var/lib/kubelet/kubeadm-flags.env 中为 KUBELET_KUBEADM_ARGS 添加配置:
--kubeconfig=/var/lib/openyurt/kubelet.conf --bootstrap-kubeconfig=
作用:
1. 参数:--kubeconfig , 给kubelet指定了访问apiServer的配置文件。
2. 当--kubeconfig 文件存在,--bootstrap-kubeconfig为空时, kubelet 启动就不需要通过 bootstrap-token 置换文件证书等过程,直接读取 kubeconfig 文件访问 apiServer。 *
*
3. 由于 KUBELET_KUBEADM_ARGS 是 kubelet 启动参数的最后一部分,所以可以起到覆盖前面参数的作用。
其中 /var/lib/openyurt/kubelet.conf
内容如下,直接将流量指定到 yurthub:
apiVersion: v1 clusters: - cluster: server: http://127.0.0.1:10261 name: default-cluster contexts: - context: cluster: default-cluster namespace: default user: default-auth name: default-context current-context: default-context kind: Config preferences: {}
yurthub 的启动细节
yurthub 容器启动参数如下:
command: - yurthub - --v=2 - --server-addr=__kubernetes_service_addr__ - --node-name=$(NODE_NAME) - --join-token=__join_token__ - --working-mode=__working_mode__
通过参数我们可看出:
1. server-addr 指定了云端 apiServer 地址。注意这里的地址一定是公网可访问地址,否则异构网络下会有问题。
2. join-token 就是加入节点的 token,可使用kubeadm token create
来创建。k8s 提供机制,通过 token 置换出正常访问的 kubeconf 文件。
3. working-mode:cloud/edge。这就是边缘节点和云端节点的差异。
我们都知道 yurthub 可以用来做缓存,是解决边缘自治的重要环节。那么云端为什么也需要部署?为什么还要区分 edge 或者 cloud 工作模式?简单查看 yurthub 源代码 cmd/yurthub/app/start.go:
if cfg.WorkingMode == util.WorkingModeEdge { cacheMgr, err = cachemanager.NewCacheManager(cfg.StorageWrapper, cfg.SerializerManager, cfg.RESTMapperManager, cfg.SharedFactory) ... } else { klog.Infof("%d. disable cache manager for node %s because it is a cloud node", trace, cfg.NodeName) } if cfg.WorkingMode == util.WorkingModeEdge { ... gcMgr, err := gc.NewGCManager(cfg, restConfigMgr, stopCh) } else { klog.Infof("%d. disable gc manager for node %s because it is a cloud node", trace, cfg.NodeName) }
可见,云端 yurthub,少做了 cache、GC 的工作。
查看 issue(详情请见文末相关链接)可了解:云端也可以利用 yurthub 提供的 data-filtering 能力来控制 service 的流量。
当然,云端也不需要做 cache 等工作。
命令行参数
在执行过程中,有几个参数比较重要:
--cloud-nodes 用于标识哪些是云端节点,多个节点用逗号分隔:node1,node2
--deploy-yurttunnel 标记是否要部署 yurttunnel
--kubeadm-conf-path 标记节点机器上 kubeadm 配置文件路径。默认:/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
更多参数,可使用 yurtctl convert --help 来查看。
总结
简单来说,convert 核心做了几个事情:
1. disable K8s 的 nodelifecontroller,用自己的 yurtcontrollermanager 来替换它的职责。
2. 安装自己的各类组件,deployment、damenonset 等模式部署。(这类资源部署无需任何担心,因为搞不坏集群,也不太会出现问题。)
3. 边缘节点:启动 yurthub 静态 pod;将 kubelet 流量转发到 yurthub。
可见,convert 的事情还是比较可控的。执行 yurtctl convert 也不用太担心。当然,最后的担心也应该由 yurtctl revert 来彻底消除!
yurtctl revert 又干了些什么?
核心流程
整个 revert 的过程就是 convert 的反向操作,还比较好理解。
需要注意的是。如果 convert 失败,比如 job 执行超时或者失败。job 是不会被删除的。
即使 yurtctl revert 也不会删除。目的是为了保留现场方便定位问题。
如果需要重新执行 yurtctl convert, 需要手动删除 job。
kubectl get job -n kube-system -A |grep convert kubectl delete job -n kube-system < job-name>
总结
yurtctl convert/revert 命令是最快捷体验 OpenYurt 功能的方法之一。
在了解了这两个命令的实现原理,也就对 OpenYurt 的技术方案了解大半了。
执行命令也不担心了,so easy!
相关链接
1)源代码:
2)issue:
https://github.com/openyurtio/openyurt/issues/450
点击【此处】阅读网站原文。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java中大集合求交集的方法比较
背景 项目中使用到List求交集,很容易想到collecion.retainAll()方法,但是在数据量比较大时,这个方法效率并不高。本文研究了几种常用的方法,以供大家参考。 方法 【首先】梳理下思路,List去重一般有几种方法。 『外层遍历+内层遍历』查找: 复杂度O(NM) ,一般使用contains()检查是否包含 『外层遍历+内层Hash』查找: 复杂度O(N),一般将内层List转化为HashSet实现 『外层遍历+内层bitMap』查找: 复杂度O(N),一般将内层List转化为字节映射实现 【其次】这里其实忽略了一个点,就是 『单层遍历』中,检查 元素不包含 时,需要将这个元素移除(即remove方法)。remove时,也会导致性能问题。 这里面我们使用Java8中java.util.AbstractCollection#retainAll方法来验证下我们的思路。 // Java8 中 方法:java.util.AbstractCollection#retainAll public boolean retainAll(Collection<?> c)...
- 下一篇
揭开Vue异步组件的神秘面纱
简介 在大型应用里,有些组件可能一开始并不显示,只有在特定条件下才会渲染,那么这种情况下该组件的资源其实不需要一开始就加载,完全可以在需要的时候再去请求,这也可以减少页面首次加载的资源体积,要在Vue中使用异步组件也很简单: // AsyncComponent.vue <template> <div>我是异步组件的内容</div> </template> <script> export default { name: 'AsyncComponent' } </script> // App.vue <template> <div id="app"> <AsyncComponent v-if="show"></AsyncComponent> <button @click="load">加载</button> </div> </template> <script> export default { name: 'A...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- 设置Eclipse缩进为4个空格,增强代码规范