這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
kubectl
實際啟動並執行函數(k8s.io/kubernetes/pkg/kubectl/app/kubectl.go
):
func Run() error { cmd := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr) return cmd.Execute()}
NewKubectlCommand
的代碼(k8s.io/kubernetes/pkg/kubectl/cmd/cmd.go
):
// NewKubectlCommand creates the `kubectl` command and its nested children.func NewKubectlCommand(f *cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command { // Parent command to which all subcommands are added. cmds := &cobra.Command{ Use: "kubectl", Short: "kubectl controls the Kubernetes cluster manager", Long: `kubectl controls the Kubernetes cluster manager.Find more information at https://github.com/kubernetes/kubernetes.`, Run: runHelp, BashCompletionFunction: bash_completion_func, } f.BindFlags(cmds.PersistentFlags()) // From this point and forward we get warnings on flags that contain "_" separators cmds.SetGlobalNormalizationFunc(util.WarnWordSepNormalizeFunc) cmds.AddCommand(NewCmdGet(f, out)) cmds.AddCommand(NewCmdDescribe(f, out)) cmds.AddCommand(NewCmdCreate(f, out)) ...... return &cmds}
所以cmd := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr)
得到的cmd
是一個指向cobra.Command
的指標。
cmdutil.NewFactory
代碼(k8s.io/kubernetes/pkg/kubectl/cmd/util/factory.go
):
// NewFactory creates a factory with the default Kubernetes resources defined// if optionalClientConfig is nil, then flags will be bound to a new clientcmd.ClientConfig.// if optionalClientConfig is not nil, then this factory will make use of it.func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { mapper := kubectl.ShortcutExpander{RESTMapper: api.RESTMapper} flags := pflag.NewFlagSet("", pflag.ContinueOnError) flags.SetNormalizeFunc(util.WarnWordSepNormalizeFunc) // Warn for "_" flags generators := map[string]kubectl.Generator{ "run/v1": kubectl.BasicReplicationController{}, "run-pod/v1": kubectl.BasicPod{}, "service/v1": kubectl.ServiceGeneratorV1{}, "service/v2": kubectl.ServiceGeneratorV2{}, "horizontalpodautoscaler/v1beta1": kubectl.HorizontalPodAutoscalerV1Beta1{}, "deployment/v1beta1": kubectl.DeploymentV1Beta1{}, "job/v1beta1": kubectl.JobV1Beta1{}, } clientConfig := optionalClientConfig if optionalClientConfig == nil { clientConfig = DefaultClientConfig(flags) } clients := NewClientCache(clientConfig) return &Factory{ ...... }
因為cmdutil.NewFactory(nil)
參數為nil
,所以調用的是DefaultClientConfig
函數。
clientcmd.ClientConfig
定義在k8s.io/kubernetes/pkg/client/unversioned/clientcmd/client_config.go
檔案:
// ClientConfig is used to make it easy to get an api server clienttype ClientConfig interface { // RawConfig returns the merged result of all overrides RawConfig() (clientcmdapi.Config, error) // ClientConfig returns a complete client config ClientConfig() (*client.Config, error) // Namespace returns the namespace resulting from the merged // result of all overrides and a boolean indicating if it was // overridden Namespace() (string, bool, error)}
DefaultClientConfig
代碼(k8s.io/kubernetes/pkg/kubectl/cmd/util/factory.go
):
func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig { loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() flags.StringVar(&loadingRules.ExplicitPath, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests.") overrides := &clientcmd.ConfigOverrides{} flagNames := clientcmd.RecommendedConfigOverrideFlags("") // short flagnames are disabled by default. These are here for compatibility with existing scripts flagNames.ClusterOverrideFlags.APIServer.ShortName = "s" clientcmd.BindOverrideFlags(overrides, flags, flagNames) clientConfig := clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, os.Stdin) return clientConfig}
最後返回一個DeferredLoadingClientConfig
結構體(定義在k8s.io/kubernetes/pkg/client/unversioned/clientcmd/merged_client_builder.go
):
// DeferredLoadingClientConfig is a ClientConfig interface that is backed by a set of loading rules// It is used in cases where the loading rules may change after you've instantiated them and you want to be sure that// the most recent rules are used. This is useful in cases where you bind flags to loading rule parameters before// the parse happens and you want your calling code to be ignorant of how the values are being mutated to avoid// passing extraneous information down a call stacktype DeferredLoadingClientConfig struct { loadingRules *ClientConfigLoadingRules overrides *ConfigOverrides fallbackReader io.Reader}