您好,登錄后才能下訂單哦!
本篇內容主要講解“kubernetes與CNI Plugin的集成方法是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“kubernetes與CNI Plugin的集成方法是什么”吧!
cni項目提供了golang寫的一個library,定義了集成cni插件的應用需調用的cni plugin接口,它就是libcni。其對應的Interface定義如下:
libcni/api.go:51 type CNI interface { AddNetworkList(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error) DelNetworkList(net *NetworkConfigList, rt *RuntimeConf) error AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) DelNetwork(net *NetworkConfig, rt *RuntimeConf) error }
kubelet Run方法方法中會最終調用syncLoopIteration函數,由它通過各種channel對pod進行sync。
pkg/kubelet/kubelet.go:1794 // syncLoopIteration reads from various channels and dispatches pods to the // given handler. // // Arguments: // 1. configCh: a channel to read config events from // 2. handler: the SyncHandler to dispatch pods to // 3. syncCh: a channel to read periodic sync events from // 4. houseKeepingCh: a channel to read housekeeping events from // 5. plegCh: a channel to read PLEG updates from // // Events are also read from the kubelet liveness manager's update channel. // // The workflow is to read from one of the channels, handle that event, and // update the timestamp in the sync loop monitor. // // Here is an appropriate place to note that despite the syntactical // similarity to the switch statement, the case statements in a select are // evaluated in a pseudorandom order if there are multiple channels ready to // read from when the select is evaluated. In other words, case statements // are evaluated in random order, and you can not assume that the case // statements evaluate in order if multiple channels have events. // // With that in mind, in truly no particular order, the different channels // are handled as follows: // // * configCh: dispatch the pods for the config change to the appropriate // handler callback for the event type // * plegCh: update the runtime cache; sync pod // * syncCh: sync all pods waiting for sync // * houseKeepingCh: trigger cleanup of pods // * liveness manager: sync pods that have failed or in which one or more // containers have failed liveness checks func (kl *Kubelet) syncLoopIteration(configCh <-chan kubetypes.PodUpdate, handler SyncHandler, syncCh <-chan time.Time, housekeepingCh <-chan time.Time, plegCh <-chan *pleg.PodLifecycleEvent) bool { kl.syncLoopMonitor.Store(kl.clock.Now()) select { case u, open := <-configCh: // Update from a config source; dispatch it to the right handler // callback. if !open { glog.Errorf("Update channel is closed. Exiting the sync loop.") return false } switch u.Op { case kubetypes.ADD: glog.V(2).Infof("SyncLoop (ADD, %q): %q", u.Source, format.Pods(u.Pods)) // After restarting, kubelet will get all existing pods through // ADD as if they are new pods. These pods will then go through the // admission process and *may* be rejected. This can be resolved // once we have checkpointing. handler.HandlePodAdditions(u.Pods) case kubetypes.UPDATE: glog.V(2).Infof("SyncLoop (UPDATE, %q): %q", u.Source, format.PodsWithDeletiontimestamps(u.Pods)) handler.HandlePodUpdates(u.Pods) case kubetypes.REMOVE: glog.V(2).Infof("SyncLoop (REMOVE, %q): %q", u.Source, format.Pods(u.Pods)) handler.HandlePodRemoves(u.Pods) case kubetypes.RECONCILE: glog.V(4).Infof("SyncLoop (RECONCILE, %q): %q", u.Source, format.Pods(u.Pods)) handler.HandlePodReconcile(u.Pods) case kubetypes.DELETE: glog.V(2).Infof("SyncLoop (DELETE, %q): %q", u.Source, format.Pods(u.Pods)) // DELETE is treated as a UPDATE because of graceful deletion. handler.HandlePodUpdates(u.Pods) case kubetypes.SET: // TODO: Do we want to support this? glog.Errorf("Kubelet does not support snapshot update") } // Mark the source ready after receiving at least one update from the // source. Once all the sources are marked ready, various cleanup // routines will start reclaiming resources. It is important that this // takes place only after kubelet calls the update handler to process // the update to ensure the internal pod cache is up-to-date. kl.sourcesReady.AddSource(u.Source) case e := <-plegCh: if isSyncPodWorthy(e) { // PLEG event for a pod; sync it. if pod, ok := kl.podManager.GetPodByUID(e.ID); ok { glog.V(2).Infof("SyncLoop (PLEG): %q, event: %#v", format.Pod(pod), e) handler.HandlePodSyncs([]*v1.Pod{pod}) } else { // If the pod no longer exists, ignore the event. glog.V(4).Infof("SyncLoop (PLEG): ignore irrelevant event: %#v", e) } } if e.Type == pleg.ContainerDied { if containerID, ok := e.Data.(string); ok { kl.cleanUpContainersInPod(e.ID, containerID) } } case <-syncCh: // Sync pods waiting for sync podsToSync := kl.getPodsToSync() if len(podsToSync) == 0 { break } glog.V(4).Infof("SyncLoop (SYNC): %d pods; %s", len(podsToSync), format.Pods(podsToSync)) kl.HandlePodSyncs(podsToSync) case update := <-kl.livenessManager.Updates(): if update.Result == proberesults.Failure { // The liveness manager detected a failure; sync the pod. // We should not use the pod from livenessManager, because it is never updated after // initialization. pod, ok := kl.podManager.GetPodByUID(update.PodUID) if !ok { // If the pod no longer exists, ignore the update. glog.V(4).Infof("SyncLoop (container unhealthy): ignore irrelevant update: %#v", update) break } glog.V(1).Infof("SyncLoop (container unhealthy): %q", format.Pod(pod)) handler.HandlePodSyncs([]*v1.Pod{pod}) } case <-housekeepingCh: if !kl.sourcesReady.AllReady() { // If the sources aren't ready or volume manager has not yet synced the states, // skip housekeeping, as we may accidentally delete pods from unready sources. glog.V(4).Infof("SyncLoop (housekeeping, skipped): sources aren't ready yet.") } else { glog.V(4).Infof("SyncLoop (housekeeping)") if err := handler.HandlePodCleanups(); err != nil { glog.Errorf("Failed cleaning pods: %v", err) } } } kl.syncLoopMonitor.Store(kl.clock.Now()) return true }
說明:
HandlePodSyncs, HandlePodUpdates, HandlePodAdditions最終都是invoke dispatchWork來分發pods到podWorker進行異步的pod sync。
HandlePodRemoves調用一下接口,將pod從cache中刪除,kill pod中進程,并 stop Pod的Probe Workers,最終通過捕獲Pod的PLEG Event,通過cleanUpContainersInPod來清理Pod。 pkg/kubelet/kubelet.go:1994 kl.podManager.DeletePod(pod); kl.deletePod(pod); kl.probeManager.RemovePod(pod);
HandlePodReconcile中,如果Pod是通過Eviction導致的Failed,則調用kl.containerDeletor.deleteContainersInPod來清除Pod內的容器。
Kubelet.dispatchWork最終會invoke podWokers.managePodLoop,podWorkers會嗲用NewMainKubelet時給PodWorkers注冊的syncPodFn= (kl *Kubelet) syncPod(o syncPodOptions)。
Kubelet.syncPod會根據runtime類型進行區分,我們只看runtime為docker的情況,會invoke DockerManager.SyncPod。
DockerManager.SyncPod會dm.network.SetUpPod,然后根據network plugin類型進行區分,我們只看cni plugin,會對應invoke cniNetworkPlugin.SetUpPod進行網絡設置。
cniNetworkPlugin.SetUpPod invoke cniNetwork.addToNetwork,由后者最終調用CNIConfig.AddNetwork,這就是libcni中對應的AddNetwork Interface。
CNIConfig.AddNetwork通過封裝好的execPlugin由系統去調用cni plugin bin,到此就完成了pod內的網絡設置。
都是通過invoke podContainerDeleter.deleteContainerInPod來清理容器。
對于docker,deleteContainerInPod會調用DockerManager.delteContainer。
在deleteContainer時,通過invoke containerGC.netContainerCleanup進行容器的網絡環境清理。
然后由PluginManger.TearDownPod去調用cniNetworkPlugin.TearDownPod,再執行cniNetwork.deleteFromNetwork。
cniNetwork.deleteFromNetwork會調用CNIConfig.DelNetwork,這就是libcni中對應的DelNetwork Interface。
CNIConfig.AddNetwork通過封裝好的execPlugin由系統去調用cni plugin bin,到此就完成了pod內的網絡清理。
到此,相信大家對“kubernetes與CNI Plugin的集成方法是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。