ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] ### **启动参数** 当我们执行`virtual-kubelet --help`命令时,会有如下输出: ``` $ virtual-kubelet --help ... Flags: --cluster-domain string kubernetes cluster-domain (default is 'cluster.local') (default "cluster.local") --disable-taint disable the virtual-kubelet node taint --full-resync-period duration how often to perform a full resync of pods between kubernetes and the provider (default 1m0s) ... ``` flags即表示virtual kubelet的启动参数,那么我们怎么知道有哪些启动参数呢? 在[flag.go](https://github.com/virtual-kubelet/virtual-kubelet/blob/v1.7.0/cmd/virtual-kubelet/internal/commands/root/flag.go)文件中如下函数,可以知道有哪些启动参数: ``` func installFlags(flags *pflag.FlagSet, c *Opts) { // 第二列的"kubeconfig"表示flag的名字,第一列的内容为该参数的默认值,即virtual-kubelet --help命令输出中,有些flag会输出默认值 flags.StringVar(&c.KubeConfigPath, "kubeconfig", c.KubeConfigPath, "kube config file to use for connecting to the Kubernetes API server") flags.StringVar(&c.KubeNamespace, "namespace", c.KubeNamespace, "kubernetes namespace (default is 'all')") // MarkDeprecated表示virtual-kubelet --help命令的输出中,该flag会提示deprecated flags.MarkDeprecated("namespace", "Nodes must watch for pods in all namespaces. This option is now ignored.") //nolint:errcheck // MarkHidden表示,virtual-kubelet --help时,该flag不会显示 flags.MarkHidden("namespace") //nolint:errcheck ... ``` 我们看到,这些flag大多有默认值,而这些默认值,是如何设置的呢?从上面的installFlag函数中我们知道,它是取自于Opts结构体中的值,我们来看一下[Opts](https://github.com/virtual-kubelet/virtual-kubelet/cmd/virtual-kubelet/internal/commands/root/opts.go)结构体的定义: ``` type Opts struct { KubeConfigPath string // vk连接apiserver时所需要的kubeconfig文件 KubeNamespace string // vk需要监听的命名空间,默认ALL KubeClusterDomain string ListenPort int32 // 监听端口,默认10250 NodeName string // vk向apiserver注册时,node的名字 OperatingSystem string // vk所在的操作系统 Provider string // Provider的名字,如ctyun-vk ProviderConfigPath string // Provider的配置文件路径,配置文件中可能会包含ctyun-eci的url等信息,该参数可为空,通过其他方式配置ECI的url信息 TaintKey string TaintEffect string DisableTaint bool MetricsAddr string PodSyncWorkers int InformerResyncPeriod time.Duration EnableNodeLease bool TraceExporters []string TraceSampleRate string TraceConfig TracingExporterOptions StartupTimeout time.Duration StreamIdleTimeout time.Duration StreamCreationTimeout time.Duration Version string } ``` 在main函数中的如下代码,会首先给Opts结构体设置默认值: ``` optsErr := root.SetDefaultOpts(&opts) ``` 在NewCommand()函数中,会调用installFlags()来设置flags ``` func NewCommand(ctx context.Context, name string, s *provider2.Store, c Opts) *cobra.Command { ... installFlags(cmd.Flags(), &c) return cmd } ``` 接下来,我们再来看一下,假设我们在启动virtual-kubelet时,指定了flag,它是如何覆盖默认值的。 在main函数中,最后会执行Command的Execute()函数,我们追踪这个函数,会发现它调用了ExcuteC()函数,我们再跟踪ExecuteC()函数,会发现如下的内容: ``` func (c *Command) ExecuteC() (cmd *Command, err error) { ... if c.args == nil && filepath.Base(os.Args[0]) != "cobra.test" { args = os.Args[1:] } ``` 上面就是从virtual-kubelet的第一个输入开始,把它存入到args变量中,后面再进行解析。解析的代码后面再分析。 ### **Virtual Kubelet的功能** virtual kubelet的主要功能有: - 向apiserver注册节点,并定期上报节点状态 - 监听调度到该节点的Pod,并维护它们的生命周期 - 提供http服务,供apiserver调用exec与logs接口 在virtual-kubelet中,它对应的数据结构为[node/nodeutil/controller.go#Node](https://github.com/virtual-kubelet/virtual-kubelet/blob/v1.7.0/node/nodeutil/controller.go) ``` type Node struct { nc *node.NodeController // 向apiserver注册节点,并定期上报节点状态 pc *node.PodController // 维护Pod的生命周期 readyCb func(context.Context) error ready chan struct{} done chan struct{} err error podInformerFactory informers.SharedInformerFactory // 从apiserver同步Pod到本地缓存 scmInformerFactory informers.SharedInformerFactory // 从apiserver同步cm、secret等来本地缓存 client kubernetes.Interface // 用于连接apiserver listenAddr string // 监听地址 h http.Handler // http请求处理 tlsConfig *tls.Config // tls证书配置 workers int // PodController的 eb record.EventBroadcaster // 向apiserver写事件? } ``` 当一个Node对象被创建后,执行它Run()函数,即可以把它跑起来。 ``` func (n *Node) Run(ctx context.Context) (retErr error) { ... // 运行eventbroadcaster if n.eb != nil { n.eb.StartLogging(log.G(ctx).Infof) n.eb.StartRecordingToSink(&corev1client.EventSinkImpl{Interface: n.client.CoreV1().Events(v1.NamespaceAll)}) defer n.eb.Shutdown() log.G(ctx).Debug("Started event broadcaster") } // 运行http服务 cancelHTTP, err := n.runHTTP(ctx) ... // 运行SharedInforFactory,用来从Pod、Secret、ConfigMap go n.podInformerFactory.Start(ctx.Done()) go n.scmInformerFactory.Start(ctx.Done()) // 运行PodController go n.pc.Run(ctx, n.workers) //nolint:errcheck ... // 运行NodeController go n.nc.Run(ctx) //nolint:errcheck ... } ``` 根据 ##### **NodeController的内容** NodeController的结构体如下: ``` type NodeController struct { p NodeProvider // 需要实现的一个Interface serverNodeLock sync.Mutex serverNode *corev1.Node // apiserver中node的json结构体 nodes v1.NodeInterface // 连接apiserver的client,通过它的接口来更新apiserver中的node结构体 leaseController *leaseController pingInterval time.Duration statusInterval time.Duration chStatusUpdate chan *corev1.Node nodeStatusUpdateErrorHandler ErrorHandler chReady chan struct{} chDone chan struct{} errMu sync.Mutex err error nodePingController *nodePingController pingTimeout *time.Duration group wait.Group } ``` Run函数如下: ``` ``` ##### **PodController的内容** ``` type PodController struct { provider PodLifecycleHandler // 需要实现的接口 podsInformer corev1informers.PodInformer podsLister corev1listers.PodLister recorder record.EventRecorder client corev1client.PodsGetter resourceManager *manager.ResourceManager syncPodsFromKubernetes *queue.Queue deletePodsFromKubernetes *queue.Queue syncPodStatusFromProvider *queue.Queue knownPods sync.Map podEventFilterFunc PodEventFilterFunc ready chan struct{} done chan struct{} mu sync.Mutex err error } ``` ##### **HTTPS监听** https://blog.csdn.net/qq_16539951/article/details/126502399