jxwjq 发表于 2018-1-6 07:40:28

k8s学习(一)

  k8s的架构是用户使用kubectl工具对虚拟机资源进行各种各样的控制和定制。
  而kubectl本身并不包含对其核心资源的访问与控制。而是通过http通信与api-server进行交互实现资源的管理。
  而api-server的核心其实就是etcd数据库,它将各种资源的管理通过对etcd中的数据进行更改实现。这篇文章简要分析一下kubectl对
  api-server发起访问的过程。
  以kubectl create 指令为例,其指令的相关代码在kubernetes/pkg/kubectl/cmd/create.go这个文件中。
  一,参数的构造
  稍加分析不难看出,其创建资源的核心函数是func RunCreate()。
  

          r := builder.  Schema(schema).
  ContinueOnError().
  NamespaceParam(cmdNamespace).DefaultNamespace().
  FilenameParam(enforceNamespace, &options.FilenameOptions).
  SelectorParam(options.Selector).
  Flatten().
  Do()
  

  

  这段代码调用了builder的一串函数,最后生成一个Result类型的变量r。(Result 定义在 kubernetes/pkg/kubectl/resource/result.go)
  这里builder的作用是将之前解析得到的各种参数进行各种分析后填充到builder中,最后再生成一个Result类型的变量r。
  此时r中最关键的数据是visitor,这个visitor中包含了多个资源,也就是说一个visitor包含了一个对象(此处存疑)。
  接着以一个函数func为参数调用r的Visit函数。经过分析我们可以知道这是一个调用链函数,其中继续对参数进行各种分析,处理。
  

r.Visit(func(info *resource.Info, err error) error {  
.....
  
})
  

  大致的调用顺序为
  Result.Visit()
  ContinueOnError.Visit()
  Decorated.Visit()
  FlattenList.Visit()
  EagerVisitorList.Visit()
  FileVisitor.Visit()
  StreamVisitor.Visit()
  在StreamVisitor之前,都是对数据的各种处理,并不会调用func函数,在StreamVisitor.Visit()中一个关键的处理是生成一个临时变量Info。
  

info, err := v.InfoForData(ext.Raw, v.Source)  

  这里的ext.Raw和v.Source都是之前对用户的输入进行解析的结果。
  ext.Raw是byte[]类型,v.Source是String类型,打印出来:
  

ext.Raw={  
"apiVersion":"v1",
  
"kind":"Pod",
  
"metadata":
  {"name":"with-node-affinity-2"},
  
"spec":
  
{"affinity":
  {"nodeAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"preference":{"matchExpressions":[{"key":"another-node-label-key","operator":"In","values":["another-node-label-value"]}]},
  
"weight":1}],
  
"requiredDuringSchedulingIgnoredDuringExecution":{"nodeSelectorTerms":[{"matchExpressions":[{"key":"kubernetes.io/e2e-az-name","operator":"In","values":["e2e-az1","e2e-az2"]}]}]}}},
  
"containers":[{"image":"gcr.io/google_containers/pause:2.0","name":"with-node-affinity"}]}},
  

  

  

  

  
v.Source=/home/wlh/mywork/yaml_file/pod-with-node-affinity.yaml
  

  可以看到其中存储了生成的资源的各种特性,有了这个info之后执行func(info)。
  二,访问api-server
  得到了info这个数据结构后,调用func()函数对api-server发起访问请求。
  

if !dryRun {  if err := createAndRefresh(info); err != nil {
  return cmdutil.AddSourceToErr("creating", info.Source, err)
  }
  }
  

  

  这个dryRun标志位的意思是,只打印出将要创建的资源的各种特性,而不会真正去创建他。
  而createAndRefresh函数中的核心调用是
  

obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object)  

  

  这里创建了一个Helper类型的对象,仔细分析后不难发现Info.Client中定义了访问动作,而info.Mapping中定义了这些动作所要访问的资源。
  此时Helper中已经包含了发起一个对api-server请求的所有资源,接着调用Create函数,它创建一个具体去执行这些请求的Request对象。(定义在kubernetes/vendor/k8s.io/client-go/rest/request.go中)
  Requeste发起对api-server的请求,并且将访问存储在ResutInfo中,与此同时返回一个Runtime.Object对象。
  这样一次完整的访问api-server的流程就完成了。
页: [1]
查看完整版本: k8s学习(一)