首页 > 编程语言 >k8s源码分析4-create命令执行流程

k8s源码分析4-create命令执行流程

时间:2022-11-21 14:22:58浏览次数:42  
标签:cmdutil return err create cmd 源码 k8s AddCommand ioStreams

本节重点总结 :

  1. newCmdCreate 调用cobra的Run函数
  2. 调用RunCreate构建resourceBuilder对象
  3. 调用visit方法创建资源
  4. 底层使用resetclient 和k8s-api通信

架构图

kubectl_create.png

create的流程 NewCmdCreate

  • 代码入口 D:\go_path\src\github.com\kubernetes\kubernetes\staging\src\k8s.io\kubectl\pkg\cmd\create\create.go

创建Create选项对象

o := NewCreateOptions(ioStreams)

初始化cmd

	cmd := &cobra.Command{
		Use:                   "create -f FILENAME",
		DisableFlagsInUseLine: true,
		Short:                 i18n.T("Create a resource from a file or from stdin"),
		Long:                  createLong,
		Example:               createExample,
		Run: func(cmd *cobra.Command, args []string) {
			if cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames, o.FilenameOptions.Kustomize) {
				ioStreams.ErrOut.Write([]byte("Error: must specify one of -f and -k\n\n"))
				defaultRunFunc := cmdutil.DefaultSubCommandRun(ioStreams.ErrOut)
				defaultRunFunc(cmd, args)
				return
			}
			cmdutil.CheckErr(o.Complete(f, cmd))
			cmdutil.CheckErr(o.ValidateArgs(cmd, args))
			cmdutil.CheckErr(o.RunCreate(f, cmd))
		},
	}

设置选项

  • 具体绑定到o的各个字段上
	// bind flag structs
	o.RecordFlags.AddFlags(cmd)

	usage := "to use to create the resource"
	cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
	cmdutil.AddValidateFlags(cmd)
	cmd.Flags().BoolVar(&o.EditBeforeCreate, "edit", o.EditBeforeCreate, "Edit the API resource before creating")
	cmd.Flags().Bool("windows-line-endings", runtime.GOOS == "windows",
		"Only relevant if --edit=true. Defaults to the line ending native to your platform.")
	cmdutil.AddApplyAnnotationFlags(cmd)
	cmdutil.AddDryRunFlag(cmd)
	cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
	cmd.Flags().StringVar(&o.Raw, "raw", o.Raw, "Raw URI to POST to the server.  Uses the transport specified by the kubeconfig file.")
	cmdutil.AddFieldManagerFlagVar(cmd, &o.fieldManager, "kubectl-create")

	o.PrintFlags.AddFlags(cmd)

绑定创建子命令

	// create subcommands
	cmd.AddCommand(NewCmdCreateNamespace(f, ioStreams))
	cmd.AddCommand(NewCmdCreateQuota(f, ioStreams))
	cmd.AddCommand(NewCmdCreateSecret(f, ioStreams))
	cmd.AddCommand(NewCmdCreateConfigMap(f, ioStreams))
	cmd.AddCommand(NewCmdCreateServiceAccount(f, ioStreams))
	cmd.AddCommand(NewCmdCreateService(f, ioStreams))
	cmd.AddCommand(NewCmdCreateDeployment(f, ioStreams))
	cmd.AddCommand(NewCmdCreateClusterRole(f, ioStreams))
	cmd.AddCommand(NewCmdCreateClusterRoleBinding(f, ioStreams))
	cmd.AddCommand(NewCmdCreateRole(f, ioStreams))
	cmd.AddCommand(NewCmdCreateRoleBinding(f, ioStreams))
	cmd.AddCommand(NewCmdCreatePodDisruptionBudget(f, ioStreams))
	cmd.AddCommand(NewCmdCreatePriorityClass(f, ioStreams))
	cmd.AddCommand(NewCmdCreateJob(f, ioStreams))
	cmd.AddCommand(NewCmdCreateCronJob(f, ioStreams))
	cmd.AddCommand(NewCmdCreateIngress(f, ioStreams))

核心的cmd.Run函数

校验文件参数

			if cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames, o.FilenameOptions.Kustomize) {
				ioStreams.ErrOut.Write([]byte("Error: must specify one of -f and -k\n\n"))
				defaultRunFunc := cmdutil.DefaultSubCommandRun(ioStreams.ErrOut)
				defaultRunFunc(cmd, args)
				return
			}

完善并填充所需字段

cmdutil.CheckErr(o.Complete(f, cmd))

校验参数

cmdutil.CheckErr(o.ValidateArgs(cmd, args))

核心的RunCreate

  • 位置 D:\go_path\src\github.com\kubernetes\kubernetes\staging\src\k8s.io\kubectl\pkg\cmd\create\create.go
cmdutil.CheckErr(o.RunCreate(f, cmd))

如果配置了apiserver的raw-uri就直接发送请求

	if len(o.Raw) > 0 {
		restClient, err := f.RESTClient()
		if err != nil {
			return err
		}
		return rawhttp.RawPost(restClient, o.IOStreams, o.Raw, o.FilenameOptions.Filenames[0])
	}

如果配置了创建前 edit就执行 RunEditOnCreate

	if o.EditBeforeCreate {
		return RunEditOnCreate(f, o.PrintFlags, o.RecordFlags, o.IOStreams, cmd, &o.FilenameOptions, o.fieldManager)
	}

根据配置中的validate决定是否开启validate

  • --validate=true: 使用一种模式校验一下配置,模式是true的
  • 意思是避免yaml中配置错了
	schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"))
	if err != nil {
		return err
	}

根据命令行获取namespace

	cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace()
	if err != nil {
		return err
	}

构建builder对象


	r := f.NewBuilder().
		Unstructured().
		Schema(schema).
		ContinueOnError().
		NamespaceParam(cmdNamespace).DefaultNamespace().
		FilenameParam(enforceNamespace, &o.FilenameOptions).
		LabelSelectorParam(o.Selector).
		Flatten().
		Do()
	err = r.Err()
	if err != nil {
		return err
	}

FilenameParam读取配置文件

  • 除了支持简单的本地文件,也支持标准输入和http/https协议访问的文件,保存为Visitor
  • 代码位置 D:\go_path\src\github.com\kubernetes\kubernetes\staging\src\k8s.io\cli-runtime\pkg\resource\builder.go
func (b *Builder) FilenameParam(enforceNamespace bool, filenameOptions *FilenameOptions) *Builder {
	if errs := filenameOptions.validate(); len(errs) > 0 {
		b.errs = append(b.errs, errs...)
		return b
	}
	recursive := filenameOptions.Recursive
	paths := filenameOptions.Filenames
	for _, s := range paths {
		switch {
		case s == "-":
			b.Stdin()
		case strings.Index(s, "http://") == 0 || strings.Index(s, "https://") == 0:
			url, err := url.Parse(s)
			if err != nil {
				b.errs = append(b.errs, fmt.Errorf("the URL passed to filename %q is not valid: %v", s, err))
				continue
			}
			b.URL(defaultHttpGetAttempts, url)
		default:
			if !recursive {
				b.singleItemImplied = true
			}
			b.Path(recursive, s)
		}
	}
	if filenameOptions.Kustomize != "" {
		b.paths = append(
			b.paths,
			&KustomizeVisitor{
				mapper:  b.mapper,
				dirPath: filenameOptions.Kustomize,
				schema:  b.schema,
				fSys:    filesys.MakeFsOnDisk(),
			})
	}

	if enforceNamespace {
		b.RequireNamespace()
	}

	return b
}

调用visit函数创建资源

	err = r.Visit(func(info *resource.Info, err error) error {
		if err != nil {
			return err
		}
		if err := util.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info.Object, scheme.DefaultJSONEncoder()); err != nil {
			return cmdutil.AddSourceToErr("creating", info.Source, err)
		}

		if err := o.Recorder.Record(info.Object); err != nil {
			klog.V(4).Infof("error recording current command: %v", err)
		}

		if o.DryRunStrategy != cmdutil.DryRunClient {
			if o.DryRunStrategy == cmdutil.DryRunServer {
				if err := o.DryRunVerifier.HasSupport(info.Mapping.GroupVersionKind); err != nil {
					return cmdutil.AddSourceToErr("creating", info.Source, err)
				}
			}
			obj, err := resource.
				NewHelper(info.Client, info.Mapping).
				DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
				WithFieldManager(o.fieldManager).
				Create(info.Namespace, true, info.Object)
			if err != nil {
				return cmdutil.AddSourceToErr("creating", info.Source, err)
			}
			info.Refresh(obj, true)
		}

  • Create函数追踪底层调用 createResource创建资源
  • 位置 D:\go_path\src\github.com\kubernetes\kubernetes\staging\src\k8s.io\cli-runtime\pkg\resource\helper.go
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()
}
  • 底层使用 restfulclient .post
  • D:\go_path\src\github.com\kubernetes\kubernetes\staging\src\k8s.io\cli-runtime\pkg\resource\interfaces.go
type RESTClient interface {
	Get() *rest.Request
	Post() *rest.Request
	Patch(types.PatchType) *rest.Request
	Delete() *rest.Request
	Put() *rest.Request
}

本节重点总结 :

  1. newCmdCreate 调用cobra的Run函数
  2. 调用RunCreate构建resourceBuilder对象
  3. 调用visit方法创建资源
  4. 底层使用resetclient 和k8s-api通信

标签:cmdutil,return,err,create,cmd,源码,k8s,AddCommand,ioStreams
From: https://www.cnblogs.com/Dev0ps/p/16911280.html

相关文章

  • k8s二进制部署
    企业级K8S集群二进制环境部署 集群架构集群系统环境   一、集群环境配置1.1、关闭所有节点swap分区swapoff-a&&sysctl-wvm.swappiness=0sed-......
  • 直播带货源码,CSS 3之图文混排效果
    直播带货源码,CSS3之图文混排效果1.设置图片与文字间距用padding属性能设计图片和文字之间的距离,即文字与图片之间在一定间距;padding属性主要用来在一个声明中设置......
  • 源码补码与反码
    title:源码补码与反码comments:truedate:2022-11-2113:24:55tags:javacategory:计算机底层存储数据时使用的是二进制数字,但是计算机在存储一个数字时并不是直......
  • K8S kube-scheduler-master CreateContainerError 问题解决及思路
    错误信息1:kubectlgetpods  发现pod状态一直在runing-error-CrashLoopBackOff-循环解决方法:1,查看日志。kubectllogspodsweb-674477549d-zx8gmkubectldescri......
  • Kubernetes(K8S) 配置静态资源服务
    Kubernetes(K8S)配置静态资源服务---apiVersion:v1kind:ConfigMapmetadata:name:img-confignamespace:vipsoftdata:img.conf:|server{ch......
  • K8S的pod展示镜像信息
    K8S的pod展示镜像信息 https://kubernetes.io/zh/docs/tasks/access-application-cluster/list-all-running-container-images/kubectlgetpods-ojsonpath='{r......
  • Spring-boot-源码-BeanMetadataElement
    org.springframework.beans.BeanMetadataElement接口BeanMetadataElement/**Interfacetobeimplementedbybeanmetadataelementsthatcarryaconfiguration......
  • docker与k8s
    虚拟技术是系统颗粒度的,容器技术是进程颗粒度的容器技术:容器技术的好处节省资源:比如你起一台虚拟机,可能只用到30%的资源,现在要在起一个application的时候,需要再起一台......
  • new Object 和 Object.create的区别
    一起来学习一下newObject和Object.create,先贴一个代码来看一下输出结果。letobj1=Object.create({x:1});//obj1={}letobj2=newObject({x:1});//obj2={......
  • 没必要阅读 Vue 源码吧?
    Vue的渐进式设计使得它非常容易上手,在最简单的情况下,我们只需要引入Vue的JS文件,然后newVue()即可使用声明式渲染。Vue的文档编写也比较优秀,方便使用者一步一步深入......