欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Kubernetes Visitor設(shè)計(jì)模式及發(fā)送pod創(chuàng)建請求解析

 更新時(shí)間:2022年11月25日 11:16:00   作者:LuckyLove  
這篇文章主要為大家介紹了Kubernetes Visitor設(shè)計(jì)模式及發(fā)送pod創(chuàng)建請求解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

確立目標(biāo)

  • 理解kubectl的核心實(shí)現(xiàn)之一:Visitor Design Pattern 訪問者模式
  • 理解發(fā)送pod創(chuàng)建請求的細(xì)節(jié)

visitor design pattern

在設(shè)計(jì)模式中,訪問者模式的定義為:

允許一個(gè)或者多個(gè)操作應(yīng)用到對象上,解耦操作和對象本身

那么,對一個(gè)程序來說,具體的表現(xiàn)就是:

  • 表面:某個(gè)對象執(zhí)行了一個(gè)方法
  • 內(nèi)部:對象內(nèi)部調(diào)用了多個(gè)方法,最后統(tǒng)一返回結(jié)果

舉個(gè)例子,

  • 表面:調(diào)用一個(gè)查詢訂單的接口
  • 內(nèi)部:先從緩存中查詢,沒查到再去熱點(diǎn)數(shù)據(jù)庫查詢,還沒查到則去歸檔數(shù)據(jù)庫里查詢

Visitor

我們來看看kubeadm中的訪問者模式的定義:

// Visitor 即為訪問者這個(gè)對象
type Visitor interface {
	Visit(VisitorFunc) error
}
// VisitorFunc對應(yīng)這個(gè)對象的方法,也就是定義中的“操作”
type VisitorFunc func(*Info, error) error

基本的數(shù)據(jù)結(jié)構(gòu)很簡單,但從當(dāng)前的數(shù)據(jù)結(jié)構(gòu)來看,有兩個(gè)問題:

  • 單個(gè)操作 可以直接調(diào)用Visit方法,那多個(gè)操作如何實(shí)現(xiàn)呢?
  • 在應(yīng)用多個(gè)操作時(shí),如果出現(xiàn)了error,該退出還是繼續(xù)應(yīng)用下一個(gè)操作呢?

Chained

以下內(nèi)容在staging/src/k8s.io/cli-runtime/pkg/resource

VisitorList和EagerVisitorList是將多個(gè)對象聚合為一個(gè)對象

DecoratedVisitor和ContinueOnErrorVisitor是將多個(gè)方法聚合為一個(gè)方法

FlattenListVisitor和FilteredVisitor是將對象抽象為多個(gè)底層對象,逐個(gè)調(diào)用方法

VisitorList

封裝多個(gè)Visitor為一個(gè),出現(xiàn)錯(cuò)誤就立刻中止并返回

// VisitorList定義為[]Visitor,又實(shí)現(xiàn)了Visit方法,也就是將多個(gè)[]Visitor封裝為一個(gè)Visitor
type VisitorList []Visitor
// 發(fā)生error就立刻返回,不繼續(xù)遍歷
func (l VisitorList) Visit(fn VisitorFunc) error {
	for i := range l {
		if err := l[i].Visit(fn); err != nil {
			return err
		}
	}
	return nil
}

EagerVisitorList

封裝多個(gè)Visitor為一個(gè),出現(xiàn)錯(cuò)誤暫存下來,全部遍歷完再聚合所有的錯(cuò)誤并返回

// EagerVisitorList 也是將多個(gè)[]Visitor封裝為一個(gè)Visitor
type EagerVisitorList []Visitor
// 返回的錯(cuò)誤暫存到[]error中,統(tǒng)一聚合
func (l EagerVisitorList) Visit(fn VisitorFunc) error {
	errs := []error(nil)
	for i := range l {
		if err := l[i].Visit(func(info *Info, err error) error {
			if err != nil {
				errs = append(errs, err)
				return nil
			}
			if err := fn(info, nil); err != nil {
				errs = append(errs, err)
			}
			return nil
		}); err != nil {
			errs = append(errs, err)
		}
	}
	return utilerrors.NewAggregate(errs)
}

DecoratedVisitor

這里借鑒了裝飾器的設(shè)計(jì)模式,將一個(gè)Visitor調(diào)用多個(gè)VisitorFunc方法,封裝為調(diào)用一個(gè)VisitorFunc

// 裝飾器Visitor
type DecoratedVisitor struct {
	visitor    Visitor
	decorators []VisitorFunc
}
// visitor遍歷調(diào)用decorators中所有函數(shù),有失敗立即返回
func (v DecoratedVisitor) Visit(fn VisitorFunc) error {
	return v.visitor.Visit(func(info *Info, err error) error {
		if err != nil {
			return err
		}
		for i := range v.decorators {
			if err := v.decorators[i](info, nil); err != nil {
				return err
			}
		}
		return fn(info, nil)
	})
}

ContinueOnErrorVisitor

// 報(bào)錯(cuò)依舊繼續(xù)
type ContinueOnErrorVisitor struct {
	Visitor
}
// 報(bào)錯(cuò)不立即返回,聚合所有錯(cuò)誤后返回
func (v ContinueOnErrorVisitor) Visit(fn VisitorFunc) error {
	errs := []error{}
	err := v.Visitor.Visit(func(info *Info, err error) error {
		if err != nil {
			errs = append(errs, err)
			return nil
		}
		if err := fn(info, nil); err != nil {
			errs = append(errs, err)
		}
		return nil
	})
	if err != nil {
		errs = append(errs, err)
	}
	if len(errs) == 1 {
		return errs[0]
	}
	return utilerrors.NewAggregate(errs)
}

FlattenListVisitor

將runtime.ObjectTyper解析成多個(gè)runtime.Object,再轉(zhuǎn)換為多個(gè)Info,逐個(gè)調(diào)用VisitorFunc

type FlattenListVisitor struct {
	visitor Visitor
	typer   runtime.ObjectTyper
	mapper  *mapper
}

FilteredVisitor

對Info資源的檢驗(yàn)

// 過濾的Info
type FilteredVisitor struct {
	visitor Visitor
	filters []FilterFunc
}
func (v FilteredVisitor) Visit(fn VisitorFunc) error {
	return v.visitor.Visit(func(info *Info, err error) error {
		if err != nil {
			return err
		}
		for _, filter := range v.filters {
      // 檢驗(yàn)Info是否滿足條件,出錯(cuò)則退出
			ok, err := filter(info, nil)
			if err != nil {
				return err
			}
			if !ok {
				return nil
			}
		}
		return fn(info, nil)
	})
}

Implements

StreamVisitor

最基礎(chǔ)的Visitor

type StreamVisitor struct {
  // 讀取信息的來源,實(shí)現(xiàn)了Read這個(gè)接口,這個(gè)"流式"的概念,包括了常見的HTTP、文件、標(biāo)準(zhǔn)輸入等各類輸入
	io.Reader
	*mapper
	Source string
	Schema ContentValidator
}

FileVisitor

文件的訪問,包括標(biāo)準(zhǔn)輸入,底層調(diào)用StreamVisitor來訪問

type FileVisitor struct {
  // 表示文件路徑或者STDIN
	Path string
	*StreamVisitor
}

URLVisitor

HTTP用GET方法獲取數(shù)據(jù),底層也是復(fù)用StreamVisitor

type URLVisitor struct {
	URL *url.URL
	*StreamVisitor
  // 提供錯(cuò)誤重試次數(shù)
	HttpAttemptCount int
}

KustomizeVisitor

自定義的Visitor,針對自定義的文件系統(tǒng),Customize 定制,是將C轉(zhuǎn)成了K

type KustomizeVisitor struct {
	Path string
	*StreamVisitor
}

發(fā)送創(chuàng)建Pod請求的實(shí)現(xiàn)細(xì)節(jié)

kubectl是怎么向kube-apiserver發(fā)送請求的呢?

send request

// 在RunCreate函數(shù)中,關(guān)鍵的發(fā)送函數(shù)
obj, err := resource.
				NewHelper(info.Client, info.Mapping).
				DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
				WithFieldManager(o.fieldManager).
				Create(info.Namespace, true, info.Object)
// 進(jìn)入create函數(shù),查看到
m.createResource(m.RESTClient, m.Resource, namespace, obj, options)
// 對應(yīng)的實(shí)現(xiàn)為
func (m *Helper) createResource(c RESTClient, resource, namespace string, obj runtime.Object, options *metav1.CreateOptions) (runtime.Object, error) {
	return c.Post().
		NamespaceIfScoped(namespace, m.NamespaceScoped).
		Resource(resource).
		VersionedParams(options, metav1.ParameterCodec).
		Body(obj).
		Do(context.TODO()).
		Get()
}
/*
到這里,我們發(fā)現(xiàn)了2個(gè)關(guān)鍵性的定義:
1. RESTClient 與kube-apiserver交互的RESTful風(fēng)格的客戶端 這個(gè)RESTClient是來自于Builder時(shí)的傳入,生成的Result,底層是一個(gè)NewClientWithOptions生成的
2. runtime.Object 資源對象的抽象,包括Pod/Deployment/Service等各類資源
3. 我們是傳入的文件,是FileVisitor來執(zhí)行的,底層Builder.mapper調(diào)用Decode來生成obj(Unstructured())
*/

RESTful Client

我們先來看看,與kube-apiserver交互的Client是怎么創(chuàng)建的

// 從傳入?yún)?shù)來看,數(shù)據(jù)來源于Info這個(gè)結(jié)構(gòu)
r.Visit(func(info *resource.Info, err error) error{})
// 而info來源于前面的Builder,前面部分都是將Builder參數(shù)化,核心的生成為Do函數(shù)
r := f.NewBuilder().
		Unstructured().
		Schema(schema).
		ContinueOnError().
		NamespaceParam(cmdNamespace).DefaultNamespace().
		FilenameParam(enforceNamespace, &o.FilenameOptions).
		LabelSelectorParam(o.Selector).
		Flatten().
		Do()
// 大致看一下這些函數(shù),我們可以在Unstructured()中看到getClient函數(shù),其實(shí)這就是我們要找的函數(shù)
func (b *Builder) getClient(gv schema.GroupVersion) (RESTClient, error) 
// 從返回值來看,client包括默認(rèn)的REST client和配置選項(xiàng)
NewClientWithOptions(client, b.requestTransforms...)
// 這個(gè)Client會(huì)在kubernetes項(xiàng)目中大量出現(xiàn),它是與kube-apiserver交互的核心組件,以后再深入。

Object

Object這個(gè)對象是怎么獲取到的呢?因?yàn)槲覀兊臄?shù)據(jù)源是來自文件的,那么我們最直觀的想法就是FileVisitor

func (v *FileVisitor) Visit(fn VisitorFunc) error {
	// 省略讀取這塊的代碼,底層調(diào)用的是StreamVisitor的邏輯
	return v.StreamVisitor.Visit(fn)
}
func (v *StreamVisitor) Visit(fn VisitorFunc) error {
	d := yaml.NewYAMLOrJSONDecoder(v.Reader, 4096)
	for {
		// 這里就是返回info的地方
		info, err := v.infoForData(ext.Raw, v.Source)
  }
}
// 再往下一層看,來到mapper層,也就是kubernetes的資源對象映射關(guān)系
func (m *mapper) infoForData(data []byte, source string) (*Info, error){
  // 這里就是我們返回Object的地方,其中GVK是Group/Version/Kind的縮寫,后續(xù)我們會(huì)涉及
  obj, gvk, err := m.decoder.Decode(data, nil, nil)
}

這時(shí),我們想回頭去看,這個(gè)mapper是在什么時(shí)候被定義的?

// 在Builder初始化中,我們就找到了
func (b *Builder) Unstructured() *Builder {
	b.mapper = &mapper{
		localFn:      b.isLocal,
		restMapperFn: b.restMapperFn,
		clientFn:     b.getClient,
    // 我們查找資源用到的是這個(gè)decoder
		decoder:      &metadataValidatingDecoder{unstructured.UnstructuredJSONScheme},
	}
	return b
}
// 逐層往下找,對應(yīng)的Decode方法的實(shí)現(xiàn),就是對應(yīng)的數(shù)據(jù)解析成data:
func (s unstructuredJSONScheme) decode(data []byte) (runtime.Object, error) {
	// 細(xì)節(jié)暫時(shí)忽略
}

Post

了解了REST ClientObject的大致產(chǎn)生邏輯后,我們再回過頭來看發(fā)送的方法

// RESTful接口風(fēng)格中,POST請求對應(yīng)的就是CREATE方法
c.Post().
		NamespaceIfScoped(namespace, m.NamespaceScoped).
		Resource(resource).
		VersionedParams(options, metav1.ParameterCodec).
		Body(obj).
		Do(context.TODO()). 
		Get() 
// Do方法,發(fā)送請求
err := r.request(ctx, func(req *http.Request, resp *http.Response) {
		result = r.transformResponse(resp, req)
	})
// Get方法,獲取請求的返回結(jié)果,用來打印狀態(tài)
switch t := out.(type) {
	case *metav1.Status:
		if t.Status != metav1.StatusSuccess {
			return nil, errors.FromObject(t)
		}
	}

站在前人的肩膀上,向前輩致敬,Respect!

Summary

通過Visitor的設(shè)計(jì)模式,從傳入的參數(shù)中解析出內(nèi)容,然后在Factory進(jìn)行NewBuilder的時(shí)候進(jìn)行配置實(shí)現(xiàn)RESTClient,mapper,obj的生成,Do()拿到Result,組裝好POST請求發(fā)送到ApiServer。

到這里我們對kubectl的功能有了初步的了解,以下是關(guān)鍵內(nèi)容所在:

命令行采用了cobra庫,主要支持7個(gè)大類的命令;

掌握Visitor設(shè)計(jì)模式,這個(gè)是kubectl實(shí)現(xiàn)各類資源對象的解析和校驗(yàn)的核心;

初步了解RESTClientObject這兩個(gè)對象,它們是貫穿kubernetes的核心概念;

調(diào)用邏輯

  • cobra匹配子命令
  • 用Visitor模式構(gòu)建Builder
  • 用RESTClient將Object發(fā)送到kube-apiserver

以上就是Kubernetes Visitor設(shè)計(jì)模式及發(fā)送pod創(chuàng)建請求解析的詳細(xì)內(nèi)容,更多關(guān)于Kubernetes Visitor發(fā)送pod請求的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Kubernetes(K8S)入門基礎(chǔ)內(nèi)容介紹

    Kubernetes(K8S)入門基礎(chǔ)內(nèi)容介紹

    這篇文章介紹了Kubernetes(K8S)的入門基礎(chǔ)內(nèi)容,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-03-03
  • KubeSphere接入外部Elasticsearch實(shí)戰(zhàn)示例

    KubeSphere接入外部Elasticsearch實(shí)戰(zhàn)示例

    這篇文章主要為大家介紹了KubeSphere接入外部Elasticsearch實(shí)戰(zhàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Kubernetes關(guān)鍵組件與結(jié)構(gòu)組成介紹

    Kubernetes關(guān)鍵組件與結(jié)構(gòu)組成介紹

    這篇文章介紹了Kubernetes的關(guān)鍵組件與結(jié)構(gòu)組成,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-03-03
  • Kubernetes scheduler啟動(dòng)監(jiān)控資源變化解析

    Kubernetes scheduler啟動(dòng)監(jiān)控資源變化解析

    這篇文章主要為大家介紹了Kubernetes scheduler啟動(dòng)監(jiān)控資源變化解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Kubernetes中Deployment的升級與回滾

    Kubernetes中Deployment的升級與回滾

    這篇文章介紹了Kubernetes中Deployment的升級與回滾?,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • 部署k8s集群的超詳細(xì)實(shí)踐步驟

    部署k8s集群的超詳細(xì)實(shí)踐步驟

    k8s是一個(gè)可移植的、可擴(kuò)展的開源平臺(tái),用于管理容器化的工作負(fù)載和服務(wù),可以促進(jìn)聲明式配置和自動(dòng)化,下面這篇文章主要給大家介紹了關(guān)于部署k8s集群的實(shí)踐步驟,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • Kubernetes(K8S)容器集群管理環(huán)境完整部署詳細(xì)教程-中篇

    Kubernetes(K8S)容器集群管理環(huán)境完整部署詳細(xì)教程-中篇

    本系列文章主要介紹了Kubernetes(K8S)容器集群管理環(huán)境完整部署的詳細(xì)教程,分為上中下三篇文章,此為中篇,需要的朋友可以參考下
    2022-01-01
  • K8S集群范圍使用imagePullSecret示例詳解

    K8S集群范圍使用imagePullSecret示例詳解

    在這篇文章中,我將向你展示如何在?Kubernetes?中使用?imagePullSecrets示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • kubernetes數(shù)據(jù)持久化StorageClass動(dòng)態(tài)供給實(shí)現(xiàn)詳解

    kubernetes數(shù)據(jù)持久化StorageClass動(dòng)態(tài)供給實(shí)現(xiàn)詳解

    這篇文章主要為大家介紹了kubernetes數(shù)據(jù)持久化StorageClass動(dòng)態(tài)供給實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Kubernetes Visitor設(shè)計(jì)模式及發(fā)送pod創(chuàng)建請求解析

    Kubernetes Visitor設(shè)計(jì)模式及發(fā)送pod創(chuàng)建請求解析

    這篇文章主要為大家介紹了Kubernetes Visitor設(shè)計(jì)模式及發(fā)送pod創(chuàng)建請求解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11

最新評論