Kubernetes 與 OpenYurt 無縫轉(zhuǎn)換(命令式)
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 ?
這個命令對集群做了什么?
看來,在執(zhí)行它之前有必要搞清楚它到底做了什么。
01
yurtctl convert 到底做了些什么?
Cloud Native
1核心流程
跟隨 openYurt 源代碼(詳情請見文末相關(guān)鏈接),梳理了 convert 的核心流程:
1. 檢查
1.1 檢查所有 node 節(jié)點狀態(tài)為 ready
2. 組件部署
2.1 給 node節(jié)點打上相應(yīng)的 label。
2.2 使用 deployment 部署 yurt-controller-manager。
2.3 使用 deployment 部署 yurt-tunnel-server。
2.4 使用 daemonset 部署 yurt-tunnel-agent,部署在邊緣節(jié)點上。
2.5 使用 deployment 部署 yurt-app-manager。
3. k8s 組件修改
3.1 修改 kube-controller-manager.yaml,用來disable nodelifecycle controller
4. 節(jié)點轉(zhuǎn)換
4.1 寫入 yurthub.yaml 到 /etc/kubernetes/manifests,啟動靜態(tài) pod
4.2 修改 kubelet 配置,使得 kubelet 訪問 yurthub 而不是直連 apiServer
3,則是對原有 k8s 系統(tǒng)組件的操作,需要特別注意。
4,節(jié)點轉(zhuǎn)換看著也并不復(fù)雜,卻對邊緣至關(guān)重要。
2
disable nodelifecycle controller 做了什么
工作內(nèi)容:
1. 查詢控制面節(jié)點2. 創(chuàng)建 job,通過` nodeName: {{.nodeName}}` 確保 job 的 pod 調(diào)度到對應(yīng) node 上執(zhí)行(通過 nsenter 的方式執(zhí)行,修改宿主機上文件)。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 啟動參數(shù)說明:
--controllers 代表需要開啟的controller列表可見,sed 命令就是去掉了 nodelifecycle 這個 controller。
那,nodelifecycle controller 是做什么的?
簡單來說:
1. 不斷監(jiān)聽,kubelet 上報上來的 node 信息
2. 如果某個 node 狀態(tài)異常,或者說長時間沒有上報等
2.1 驅(qū)逐這個 node 節(jié)點或者其他 ---> 導(dǎo)致上面的 pod 被重新調(diào)度
可見,對于處于弱網(wǎng)環(huán)境的邊緣節(jié)點,很容易就命中異常狀態(tài),導(dǎo)致 node 被驅(qū)逐,pod 被重新調(diào)度。
所以這里把它去掉了。使用 yurt-controller-manager 來代替它。
即使節(jié)點心跳丟失,處于自治模式的節(jié)點中的 pod 也不會從 APIServer 中驅(qū)逐。
注:這里自治模式的節(jié)點,指的就是邊緣節(jié)點。我們通常會通過加 annotation 的方式把節(jié)點標記為自治節(jié)點。
3
節(jié)點轉(zhuǎn)換是怎么實現(xiàn)的,云端節(jié)點和邊緣節(jié)點有什么差異?
同樣,是通過跑 job 的方式,在目標宿主機上下文中執(zhí)行相關(guān)操作。
不過,相比于暴力使用 nsenter,這里用了更加優(yōu)雅的方式。通過將宿主機根路徑 volume 掛載到容器里的方式。
kubelet 的修改
在文件/var/lib/kubelet/kubeadm-flags.env 中為 KUBELET_KUBEADM_ARGS 添加配置:
--kubeconfig=/var/lib/openyurt/kubelet.conf --bootstrap-kubeconfig=
作用:
1. 參數(shù):--kubeconfig , 給kubelet指定了訪問apiServer的配置文件。2. 當--kubeconfig 文件存在,--bootstrap-kubeconfig為空時, kubelet 啟動就不需要通過 bootstrap-token 置換文件證書等過程,直接讀取 kubeconfig 文件訪問 apiServer。3. 由于 KUBELET_KUBEADM_ARGS 是 kubelet 啟動參數(shù)的最后一部分,所以可以起到覆蓋前面參數(shù)的作用。
其中 /var/lib/openyurt/kubelet.conf 內(nèi)容如下,直接將流量指定到 yurthub:
apiVersion: v1clusters:- cluster:server: http://127.0.0.1:10261name: default-clustercontexts:- context:cluster: default-clusternamespace: defaultuser: default-authname: default-contextcurrent-context: default-contextkind: Configpreferences: {}
yurthub 的啟動細節(jié)
yurthub 容器啟動參數(shù)如下:
command:- yurthub- --v=2- --server-addr=__kubernetes_service_addr__- --node-name=$(NODE_NAME)- --join-token=__join_token__- --working-mode=__working_mode__
通過參數(shù)我們可看出:
1. server-addr 指定了云端 apiServer 地址。注意這里的地址一定是公網(wǎng)可訪問地址,否則異構(gòu)網(wǎng)絡(luò)下會有問題。
2. join-token 就是加入節(jié)點的 token,可使用`kubeadm token create`來創(chuàng)建。k8s 提供機制,通過 token 置換出正常訪問的 kubeconf 文件。
3. working-mode:cloud/edge。這就是邊緣節(jié)點和云端節(jié)點的差異。
簡單查看 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(詳情請見文末相關(guān)鏈接)可了解:云端也可以利用 yurthub 提供的 data-filtering 能力來控制 service 的流量
當然,云端也不需要做 cache 等工作。
4 命令行參數(shù)
--cloud-nodes 用于標識哪些是云端節(jié)點,多個節(jié)點用逗號分隔:node1,node2
--deploy-yurttunnel 標記是否要部署 yurttunnel
--kubeadm-conf-path 標記節(jié)點機器上 kubeadm 配置文件路徑。默認:/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
更多參數(shù),可使用 yurtctl convert --help 來查看。
總結(jié)
簡單來說,convert 核心做了幾個事情:
可見,convert 的事情還是比較可控的。執(zhí)行 yurtctl convert 也不用太擔心。
當然,最后的擔心也應(yīng)該由 yurtctl revert 來徹底消除!
02
yurtctl revert 又干了些什么?
Cloud Native
1核心流程
1. 檢查
1.1 確保所有 node 都已經(jīng) ready
2. 刪除自身部署組件
2.1 刪除 yurt-controller-manager deployment 以及相關(guān)資源
2.2 刪除 yurt-tunnel-agent 以及相關(guān)資源
2.2 刪除 yurt-tunnel-server 以及相關(guān)資源
2.3 刪除 yurt-app-manager 以及相關(guān)資源
3. K8s 組件修改
3.1 開啟 nodelifecontroller, 這個很好理解,就是把修改的命令通過 sed 命令改回來。
4. 云端、邊緣節(jié)點轉(zhuǎn)換為原生節(jié)點
4.1 修改 kubelet 配置,直連 apiServer
4.2 刪除 yurthub 相關(guān)配置、目錄
需要注意的是。如果 convert 失敗,比如 job 執(zhí)行超時或者失敗。job 是不會被刪除的。
即使 yurtctl revert 也不會刪除。目的是為了保留現(xiàn)場方便定位問題。
如果需要重新執(zhí)行 yurtctl convert, 需要手動刪除 job。
kubectl get job -n kube-system -A |grep convertkubectl delete job -n kube-system < job-name>
總結(jié)
yurtctl convert/revert 命令是最快捷體驗 OpenYurt 功能的方法之一。
在了解了這兩個命令的實現(xiàn)原理,也就對 OpenYurt 的技術(shù)方案了解大半了。
執(zhí)行命令也不擔心了,so easy!
03
相關(guān)鏈接
Cloud Native
1)源代碼:https://github.com/openyurtio/openyurt/blob/5063752a9f6645270e3177e39a46df8c23145af2/pkg/yurtctl/cmd/convert/convert.go#L300