小工具知识网

当前位置: 首页 > 行业知识 > kubectl使用及源码阅读

行业知识

kubectl使用及源码阅读

2026-10-30 01:33:00 来源:互联网转载

目录

  • 概述
  • 实践
    • 样例
      • yaml 中的必须字段
      • kubectl 代码原理
        • kubectl 命令行设置pprof 抓取火焰图
          • kubectl 中的 cobra
          • 七大分组命令
            • kubectl create
            • createCmd中的builder模式
            • createCmd中的visitor访问者模式
            • 外层VisitorFunc分析
            • ���束

              概述

              k8s 版本 v1.24.16

              kubectl的职责

              • 1.主要的工作是处理用户提交的东西(包括,命令行参数,yaml文件等)
              • 2.将用户提交的这些东西组织成一个数据结构体
              • 3.再将其发送给 api server

                实践

                文章名链接
                linux k8s 源码编译及单集群测试地址
                k8s源码debug地址

                样例

                cat test/fixtures/doc-yaml/user-guide/pod.yaml

                apiVersion: v1kind: Podmetadata:  name: nginx  labels:    app: nginxspec:  containers:  - name: nginx    image: nginx    ports:    - containerPort: 80
                字段名含义
                kindPod
                metadata.name
                spec.containers.name
                spec.containers.imageimage名称:版本

                对象规约(Spec) 与状态 (Status)

                • 几乎每个 Kubernetes 对象包含两个嵌套的对象字段,它们负责管理对象的配置:对象 spec (规约) 和对象 status (状态)
                • 对于具有 spec 的对象,必须在创建对象时设置具体内容,描述你希望对象所具有的特征:期望状态 (Desired State)

                  yaml 中的必须字段

                  • 在想要创建的 Kubernetes 对象对应的 yaml 文件中,需要配置如下的字段:
                    • apiVersion - 创建该对象所使用的 Kubernetes API 的版本
                    • kind - 想要创建的对象的类别
                    • metadata - 帮助唯一标识对象的一些数据,包括一个 name 字符串、UID和可选的 namespace
                      [root@test kubernetes]# ./cluster/kubectl.sh get podsNAME    READY   STATUS    RESTARTS   AGEnginx   1/1     Running   0          89s
                      字段名含义
                      NAMEnginx就是对应yaml中metadata.name
                      READY就绪个数
                      STATUS当前的状态,RUNNING表示运行中
                      RESTARTS重启的次数,代表没有重启过
                      AGE运行的时长

                      kubectl 代码原理

                      • 1.从命令行和 yaml 文件中获取信息
                      • 2.通过 Builder 模式并将其转成一系列的资源
                      • 3.最后用 Visitor 模式来迭代处理这些 Resources

                        源码位置

                        kubectl 命令行设置pprof 抓取火焰图

                        kubectl 中的 cobra
                        • 底层函数 NewKubectlCommand 解析
                        • 在 PersistentPreRunE 设置 prrof 采集相关指令
                        • 在 PersistentPostRunE 设置了 pprof 统计结果落盘
                        • 执行采集 pprof cpu 的 kubelet 命令
                          kubectl.go --> command := cmd.NewDefaultKubectlCommand()cmd.go --> return NewDefaultKubectlCommandWithArgs(KubectlOptions{ -->cmd := NewKubectlCommand(o)
                          # cpu.pprof 文件在当前命令执行目录下kubectl get node --profile=cpu --profile-output=cpu.pprof# ll# 使用 go 工具将 pprof 转换成 svg  火焰图go tool pprof -svg cpu.pprof > kubectl_get_node_cpu.svg# 下载下来,在浏览器打开

                          七大分组命令

                          kubectl.go --> command := cmd.NewDefaultKubectlCommand()cmd.go --> var defaultConfigFlags = genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag().WithDiscoveryBurst(300).WithDiscoveryQPS(50.0) --> f := cmdutil.NewFactory(matchVersionKubeConfigFlags) --> proxyCmd := proxy.NewCmdProxy(f, o.IOStreams)proxyCmd.PreRun = func(cmd *cobra.Command, args []string) {kubeConfigFlags.WrapConfigFn = nil}
                          groups := templates.CommandGroups{{Message: "Basic Commands (Beginner):",Commands: []*cobra.Command{create.NewCmdCreate(f, o.IOStreams),expose.NewCmdExposeService(f, o.IOStreams),run.NewCmdRun(f, o.IOStreams),set.NewCmdSet(f, o.IOStreams),},},{Message: "Basic Commands (Intermediate):",Commands: []*cobra.Command{explain.NewCmdExplain("kubectl", f, o.IOStreams),getCmd,edit.NewCmdEdit(f, o.IOStreams),delete.NewCmdDelete(f, o.IOStreams),},},{Message: "Deploy Commands:",Commands: []*cobra.Command{rollout.NewCmdRollout(f, o.IOStreams),scale.NewCmdScale(f, o.IOStreams),autoscale.NewCmdAutoscale(f, o.IOStreams),},},{Message: "Cluster Management Commands:",Commands: []*cobra.Command{certificates.NewCmdCertificate(f, o.IOStreams),clusterinfo.NewCmdClusterInfo(f, o.IOStreams),top.NewCmdTop(f, o.IOStreams),drain.NewCmdCordon(f, o.IOStreams),drain.NewCmdUncordon(f, o.IOStreams),drain.NewCmdDrain(f, o.IOStreams),taint.NewCmdTaint(f, o.IOStreams),},},{Message: "Troubleshooting and Debugging Commands:",Commands: []*cobra.Command{describe.NewCmdDescribe("kubectl", f, o.IOStreams),logs.NewCmdLogs(f, o.IOStreams),attach.NewCmdAttach(f, o.IOStreams),cmdexec.NewCmdExec(f, o.IOStreams),portforward.NewCmdPortForward(f, o.IOStreams),proxyCmd,cp.NewCmdCp(f, o.IOStreams),auth.NewCmdAuth(f, o.IOStreams),debug.NewCmdDebug(f, o.IOStreams),},},{Message: "Advanced Commands:",Commands: []*cobra.Command{diff.NewCmdDiff(f, o.IOStreams),apply.NewCmdApply("kubectl", f, o.IOStreams),patch.NewCmdPatch(f, o.IOStreams),replace.NewCmdReplace(f, o.IOStreams),wait.NewCmdWait(f, o.IOStreams),kustomize.NewCmdKustomize(o.IOStreams),},},{Message: "Settings Commands:",Commands: []*cobra.Command{label.NewCmdLabel(f, o.IOStreams),annotate.NewCmdAnnotate("kubectl", f, o.IOStreams),completion.NewCmdCompletion(o.IOStreams.Out, ""),},},}

                          kubectl create

                          // 进入口create.NewCmdCreate(f, o.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// 发送请求与 api server 通信cmdutil.CheckErr(o.RunCreate(f, cmd))

                          createCmd中的builder模式

                          createCmd中的builder建造者设计模式

                          // 快速定位代码cmdutil.CheckErr(o.RunCreate(f, cmd)) -->r := f.NewBuilder().Unstructured().Schema(schema).ContinueOnError().NamespaceParam(cmdNamespace).DefaultNamespace().FilenameParam(enforceNamespace, &o.FilenameOptions).LabelSelectorParam(o.Selector).Flatten().Do()

                          createCmd中的visitor访问者模式

                          • 访问都模式(Visitor Pattern) 是一种将数据结构与数据操作分离的设计模式
                          • 指封装一些作用于某种数据结构中的各元素的操作
                          • 可以在不改变数据结构的前提下定义作用于这些元素的新的操作
                          • 属于行为型设计模式

                            使用场景:

                            • 数据结构稳定,作用于数据结构的操作经常变化的场景
                            • 需要数据结构与数据操作分享的场景
                            • 需要对不同数据类型(元素)进行操作,而不使用分支判断具体类型的场景
                              // 快速定位代码cmdutil.CheckErr(o.RunCreate(f, cmd)) --> err = r.Visit(func(info *resource.Info, err error) error {// 注意 Visit 是由 Builder 中 FilenameParam 构建的r := f.NewBuilder()....// 构建 VisitFilenameParam(enforceNamespace, &o.FilenameOptions)....// 创建 VisitDo()// 定位FilenameParam --> b.Path(recursive, matches...) --> visitors, err := ExpandPathsToFileVisitors(b.mapper, p, recursive, FileExtensions, b.schema) -->visitor := &FileVisitor{Path:          path,StreamVisitor: NewStreamVisitor(nil, mapper, path, schema),}

                              FilenameParam --> b.Path(recursive, matches…) 位置

                              // NewStreamVisitor is a helper function that is useful when we want to change the fields of the struct but keep calls the same.func NewStreamVisitor(r io.Reader, mapper *mapper, source string, schema ContentValidator) *StreamVisitor {return &StreamVisitor{Reader: r,mapper: mapper,Source: source,Schema: schema,}}// 解析 yaml 或者 json 配置// Visit implements Visitor over a stream. StreamVisitor is able to distinct multiple resources in one stream.func (v *StreamVisitor) Visit(fn VisitorFunc) error {d := yaml.NewYAMLOrJSONDecoder(v.Reader, 4096)for {ext := runtime.RawExtension{}if err := d.Decode(&ext); err != nil {if err == io.EOF {return nil}return fmt.Errorf("error parsing %s: %v", v.Source, err)}// TODO: This needs to be able to handle object in other encodings and schemas.ext.Raw = bytes.TrimSpace(ext.Raw)if len(ext.Raw) == 0 || bytes.Equal(ext.Raw, []byte("null")) {continue}if err := ValidateSchema(ext.Raw, v.Schema); err != nil {return fmt.Errorf("error validating %q: %v", v.Source, err)}info, err := v.infoForData(ext.Raw, v.Source)if err != nil {if fnErr := fn(info, err); fnErr != nil {return fnErr}continue}if err := fn(info, nil); err != nil {return err}}}
                              // 上面方法中,重点如下代码info, err := v.infoForData(ext.Raw, v.Source)// obj 代表 k8s的对象// gvk 代表 Group/Version/Kind 的缩写obj, gvk, err := m.decoder.Decode(data, nil, nil)

                              外层VisitorFunc分析

                              • 如查出错即返回错误
                              • DryRunStrategy 代表试运行策略
                                • 默认为 None 代表不试运行
                                • client 代表客户端试运行,不发送请求至 server
                                • server 点服务端试运行,发送请求,但是如果会改变状态的话就不做
                                  err = r.Visit(func(info *resource.Info, err error) error { --> if o.DryRunStrategy != cmdutil.DryRunClient {  --> Create(info.Namespace, true, info.Object)(最终创建资源)

                                  结束

                                  kubectl使用及进阶 至此结束。

上一篇:MDAS下载宝典,一键获取软件,操作无忧的秘诀!

下一篇:傲云服务器怎么用?