主体程序路径:
kubernetes/cmd/kubelet
实验环境:
- 服务器:
- 系统:
Centos 7.9
- go:
v1.17.5
- 本地:
- 系统:
Windows 10
- 开发环境:
VS Code
+SSH-Remote
- kubernetes:
v1.23.1
说明:为了阅读方便,快速抓住核心,本文中的示例代码在源代码的基础上可能存在略微调整、伪代码化等等操作。如果阅读时存在排版疑问,请以文档原始编辑器(
typora v0.11.17 beta for windows
)为准
1. 简介
主要源码结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30kubelet/
├── app
│ ├── auth.go
│ ├── init_others.go
│ ├── init_windows.go
│ ├── init_windows_test.go
│ ├── options
│ │ ├── container_runtime.go
│ │ ├── globalflags.go
│ │ ├── globalflags_linux.go
│ │ ├── globalflags_other.go
│ │ ├── globalflags_providerless.go
│ │ ├── globalflags_providers.go
│ │ ├── options.go
│ │ ├── options_test.go
│ │ ├── osflags_others.go
│ │ └── osflags_windows.go
│ ├── OWNERS
│ ├── plugins.go
│ ├── plugins_providerless.go
│ ├── plugins_providers.go
│ ├── server_bootstrap_test.go
│ ├── server.go
│ ├── server_linux.go
│ ├── server_others.go
│ ├── server_test.go
│ ├── server_unsupported.go
│ └── server_windows.go
├── kubelet.go
└── OWNERS内部组件架构
2. 程序入口:
1 | func main() { |
3. kubelet命令行创建
即实例化 var command *cobra.command
1 | func NewKubeletCommand() *cobra.Command { |
默认初始化cleanFlagSet结构
1
cleanFlagSet := pflag.NewFlagSet(componentKubelet, pflag.ContinueOnError)
type: pflag.FlagSet
作用:类似pflag结构的定义,用于生成命令行应用
拓展:
pflag的三种使用方式
import “github.com/spf13/pflag”
方式一:
1
2
3
4
5
6
7
8
9
10
11
12flagSet := pflag.NewFlagSet("main", pflag.ExitOnError)
version := flagSet.BoolP("version", "v", false, "print version string") // 参数定义
flagSet.Parse(os.Args[1:]) // 解析:命令应用启动参数
// 读取:使用参数
// 方法一:
fmt.Println(*version)
// 方法二:
value, _ := flagSet.GetBool("version")
fmt.Println(value)方式二:
1
2
3
4flagSet := pflag.NewFlagSet("main", pflag.ExitOnError)
flagSet.Parse(os.Args[1:]) // 解析:命令应用启动参数
value, _ := flagSet.GetBool("version") // 读取:使用参数
fmt.Println(value)方式三:
1
2
3
4version := pflag.BoolP("version","v", false, "print version string") // 参数定义
pflag.Parse() // 解析
fmt.println(version) // 读取附加:
若使用package为golang内置的
flag
而不是pflag
(增强版),可使用如下:1
2
3
4
5
6
7
8
9
10
11
12flagSet := flag.NewFlagSet("main", flag.ExitOnError)
version := flagSet.Bool("version", false, "print version string") // 参数定义
flagSet.Parse(os.Args[1:]) // 解析:命令应用启动参数
// 读取:使用参数
// 方法一:
value := flagSet.Lookup("version").Value.(flag.Getter).Get().(bool)
fmt.Println(value)
// 方法二
fmt.Println(*version)
启动参照: ./go_exec –version=true
默认初始化kubeletFlags结构
1
2// 默认值初始化KubeletFlags结构,包括docker,证书路径,插件目录,CIDR等等
kubeletFlags := options.NewKubeletFlags()- type:
option.KubeletFlags
- 作用:从
kubelet
命令启动时追加的参数(Flags)后期存储到该结构 - 集群各node节点之间不共享的配置集
- type:
默认初始化
kubeletConfig
结构1
kubeletConfig, err := options.NewKubeletConfiguration()
type:
config.kubeletConfiguration
作用:从配置文件
--config=$PATH/kubelet.config
获取的参数后期存储到该结构集群各node节点之间共享的配置集
kubelet.config
文件内容示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
x509:
clientCAFile: /opt/kubernetes/ssl/ca.pem
webhook:
enabled: true
cacheTTL: 2m0s
anonymous:
enabled: false
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: 5m0s
cacheUnauthorizedTTL: 30s
address: $NODE_IP
port: 10250
readOnlyPort: 10255
cgroupDriver: systemd
hairpinMode: promiscuous-bridge
serializeImagePulls: false
clusterDomain: cluster.local.
clusterDNS:
- 10.0.0.2
cmd初始化
DisableFlagParsing: true
即禁用cobra包的flags自动解析。flags会被直接解析为参数
args
的一部分(注意子命令
不是flags
),其中包括--help
等。以下通过简单示例说明此参数影响:
DisableFlagParsing: false
1
2
3
4
5
6apt-get install package -f
解析结果
command: `apt-get install`
flags: ["-f"]
args: ["package"]DisableFlagParsing: true
1
2
3
4
5
6apt-get install package -f
解析结果
command: `apt-get install`
flags: []
args: ["-f","package"]将此参数值设置为
true
,使得kubelet
可以在Run
函数里,完全自定义可控的方式处理程序
Run函数编写
即执行kubelet命令时的调用入口函数
对程序的输入命令进行初步解析,判断输入参数合法性
cleanFlagSet.Parse(args)
解析程序flags
如果出现有未定义的flags,将返回error
cleanFlagSet.Args()
- 解析程序子命令
- kubelet并不支持子命令,将直接报错并结束程序
cleanFlagSet.GetBool("help")
判断是否包含
--help
,有则直接跳转到kubelet help
,结束程序verflag.PrintAndExitIfRequested()
解析
--version
字段内部基于
type versionValue int
手动约定枚举类型versionValue
var versionFlag = Version(versionFlagName, VersionFalse, "Print version information and quit")
实质上就是基于
pflag
将一个*versionValue
类型的值绑定到名为versionFlagName
的flag
,其默认值为VersionFalse
,真实值存储在versionFlag
使用
AddFlags(fs *flag.FlagSet)
将此处声明的flag
注册到fs
中,即可接受到程序真实的参数输入传入值:
"raw"
: 打印版本号
,结束进程例如:
1
version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.1", GitCommit:"86ec240af8cbd1b60bcc4c03c20da9b98005b92e", GitTreeState:"clean", BuildDate:"2021-12-16T11:39:51Z", GoVersion:"go1.17.5", Compiler:"gc", Platform:"linux/amd64"}
"true"
: 打印程序名(此处默认为字符串"Kubernetes")+版本号
,结束进程例如:
1
Kubernetes v1.23.1
"false"
: 直接结束函数,无操作
额外补充:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15>// 此接口为pflag包内容
>type Value interface {
String() string
Set(string) error
Type() string
>}
>// 注意:可见到在verflag.go中对约定的枚举类型versionValue实现了pflag.Value接口
>// verflag.go: line 77~78
>*p = value // 这里的p可以是自定义类型,只要实现了pflag.Value接口就行。此处实质上是*Int(手动约定枚举类型)
>flag.Var(p, name, usage) // 即定义一个flag标志,与p绑定,默认值为value,名称为name,用法为usage
>// *p = VersionFalse // VersionFalse = 0
>// flag.Var(p, "version", "Print version information and quit")utilfeature.DefaultMutableFeatureGate.SetFromMap(kubeletConfig.FeatureGates)
kubeletConfig.FeatureGates
为map[string]bool
类型,存储了k8s alpha/experimental版本特性是否启用此函数作用:
- 用
kubeletConfig.FeatureGates
覆盖默认的FeatureGates
参数项- 内部核心实现涉及
know:Map
(存储了所有已知的特性及其描述)和enable: Map
(存储了实际的特性及其开关状态)
- 内部核心实现涉及
- 拦截对未知特性的设置
- 拦截对禁止修改(通过
know[Feature_name].LockToDefault : bool
进行判定)的特性的设置
- 用
options.ValidateKubeletFlags(kubeletFlags)
- 验证是否有非
kubelet
支持的flag(该结构决定存储的flag一定是kubernetes
支持的,但不一定是kubelet
支持) - 验证flag的设置是否与其它选项的设置冲突,例如
FeatureGate
(可能将某特性设置为禁用)
- 验证是否有非
对容器运行时为
remote
时可能出现的错误给出提示从文件加载
KubeletConfig
参数先从配置文件读取,如果命令行同时指定其中某字段,优先级:命令行>配置文件
特例:针对
KubeletConfig.FeatureGates
,未冲突字段采用合并的方式,冲突字段优先级:命令行>配置文件说明:巧妙的用了一个临时
pflag.FlagSet
而非最终保留的FlagSet
结构来对命令行参数进行再次解析,不会因此影响到KubeletFlags
,避免了整个应用的重复解析问题。从磁盘文件
kubelet.config
读取配置文件:kubeletConfig,err = loadConfigFile(configFile)
DefaultFs
utilfs.DefaultFs
实质上是对默认OS文件操作的一种封装,目的是可以自动的在所有传入的文件path前面自动加上一个root
路径代码:
1
2
3
4
5
6
7
8
9
10
11type DefaultFs struct {
root string
}
// 实现举例
func (fs *DefaultFs) Remove(name string) error {
real_name := filepath.Join(fs.root, name) // 自动加上前缀
return os.Remove(real_name)
}
// ...loader := configfiles.NewFsLoader(...)
1
2
3
4
5
6
7
8
9
10func NewFsLoader(fs utilfs.Filesystem, kubeletFile string) (Loader, error) {
// 此处初始化一个kubelet的默认文件编解码器:kubeletCodecs
return &fsLoader{
fs: fs, // 即为DefaultFs类型
kubeletCodecs: kubeletCodecs,
kubeletFile: kubeletFile,
}, nil
}数据读取以及格式化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20func (loader *fsLoader) Load() (*kubeletconfig.KubeletConfiguration, error) {
data, err := loader.fs.ReadFile(loader.kubeletFile)
// ...
kc, err := utilcodec.DecodeKubeletConfiguration(loader.kubeletCodecs, data)
// ...
// 读取kubeletconfig结构中所有路径字段的指针,形成 []*string
paths := kubeletconfig.KubeletConfigurationPathRefs(kc)
// 读取kubelet.config文件所在目录,作为root目录
root_dir := filepath.Dir(loader.kubeletFile)
// 将kubeletconfig结构中所有字段的目录,修改为:
// *path = filepath.Join(root_dir, *path)
resolveRelativePaths(paths, root_dir)
return kc, nil
}
kubeletConfigFlagPrecedence(kc *kubeletconfiginternal.KubeletConfiguration, args []string)
首先构造了一个假的全局
pflag.FlagSet
(实际上并不会使用,仅仅是局部变量)变量fs
以配置文件的
KubeletConfig
的值作为默认值向fs
注册flag
,并均标记为Deprecated
fs
解析命令行传入的所有参数,如果参数指定了KubeletConfig
的值,将会覆盖上述默认值针对
KubeletConfig.FeatureGates
取并集,冲突时优先级:命令行参数 > 配置文件写回
KubeletConfig.FeatureGates
的原值1
2
3
4
5
6
7
8// 命令行指定feature-gates的示例
--feature-gates \
APIListChunking=true|false (BETA - default=true) \
APIPriorityAndFairness=true|false (ALPHA - default=false) \
APIResponseCompression=true|false (BETA - default=true) \
AllAlpha=true|false (ALPHA - default=false)
.... \
WinOverlay=true|false (ALPHA - default=false)
说明:即针对
Kubeletconfig
参数配置优先级:命令行参数 > 配置文件,同时在命令行未特殊指定的情况下,保留原始的KubeletConfig.FeatureGates
值(特性开启/关闭状态尽可能不变)。**该过程不会影响到KubeletFlags
**的值存在原因:为了解决issue#56171: https://github.com/kubernetes/kubernetes/issues/56171 (保证二进制版本向后兼容)
newFlagSetWithGlobals()
实例化一个
*pflag.FlagSet
结构,拥有全局的flag.FlagSet
(即flag.CommandLine
)所拥有的所有flags
(除了技术限制外,都被标记为Deprecated
)newFakeFlagSet(...)
在
newFlagSetWithGlobals()
的基础上创建一个增强版*pflag.FlagSet
结构,实质上仅仅把所有的Value绑定到了一个空结构体延伸参考:
1
2
3
4// 对f中的所有flag以字母顺序或字典顺序执行:fn(flag)
func (f *FlagSet) VisitAll(fn func(*Flag)){
// ...
}options.NewKubeletFlags().AddFlags(fs)
- 实例化一次性的
options.KubeletFlags
结构,此处假定为kf
- 向
fs
注册了kubelet
所有的flags
, 值与kf
的字段绑定,实质上放弃了对传入KubeletFlags
参数值的读取
- 实例化一次性的
options.AddKubeletConfigFlags(fs, kc)
- 以配置文件的
KubeletConfig
的值作为默认值向fs
注册flag
,因此如果命令行参数重新制定,将会覆盖默认值,否则保持不变 - 因为在后期版本中,这些字段都被迁移到通过
--config=$file
中的$file
指定,因此标记为Deprecated
- 以配置文件的
对于配置文件有值,但是命令行参数没有指定的
KubeletConfig.FeatureGates
参数,使用配置文件的值进行补充写回,达到合并目的。冲突字段则优先级:命令行参数 > 配置文件1
2
3
4
5for k, v := range original {
if _, ok := kc.FeatureGates[k]; !ok {
kc.FeatureGates[k] = v // 值不存在时原值写回,存在(即从命令行参数读取到对应的flag)则使用新值
}
}utilfeature.DefaultMutableFeatureGate.SetFromMap(kubeletConfig.FeatureGates)
由于上面更新了
Kubeletconfig
的值,因此同步更新k8s alpha/experimental版本特性开闭状态
验证
kubeletConfig
的内容是否合法:kubeletconfigvalidation.ValidateKubeletConfiguration(kubeletConfig)
保证内容格式合法确保
kubeletConfig.KubeReservedCgroup
为kubeletConfig.KubeletCgroups
首部开始的子字符串,即KubeReservedCgroup
路径为KubeletCgroups
的子路径延伸阅读:
cgroup
(control group)是Linux内核的一项功能,提供了一系列资源管理控制器,由systemd
自动挂载,用来控制进程对资源的分配,包括CPU、内存、网络带宽等kubeletConfig.KubeletCgroups
可由--kubelet-cgroups
指定:创建和运行Kubelet的cgroups的绝对名称。kubeletConfig.KubeReservedCgroup
可由--kube-reserved-cgroup
指定:顶级cgroup的绝对名称,用于管理通过--system-reserved
标志预留计算资源的非kubernetes
组件,例如"/system-reserverd"
默认为""
动态
KubeletConfig
配置: 指定此参数时,本地的--config
将不起作用--dynamic-config-dir
指定目录,需确保KubeletConfig.FeatureGates
的DynamicKubeletConfig
功能开启。关于此功能具体说明详见:https://kubernetes.io/blog/2018/07/11/dynamic-kubelet-configuration/方式:
内部会通过
BootstrapKubeletConfigController(...)
创建并引导一个Configuration控制器
,该控制器通过函数委托的方式,通过KubeletConfig
的结构体指针和kubeletConfigFlagPrecedence
(上面提及过),完成对Kubeletconfig
的动态刷新高级别流程描述:
初始化日志记录,并记录启动时读取到的所有的
flags
(包括name
和value
)。注意:
推荐写入
KubeletConfig
中的配置参数,实质上也被注册为flag
(虽然标记为Deprecated
),因此也会包含在内启动
kubelet
时没有显示赋值的flag
也会包含默认值,因此也会包含在内由于
kubeletConfig
的结构字段是以指针的形式与flag
绑定,因此读入kubeletconfig
配置文件,影响到最终记录的这部分flags
的值。即此处记录到的flags
是指代所有(命令行参数+配置文件)读入的参数的值。
创建
kubeletServer
结构1
2
3
4
5// 实质上即包含了kubelet所有启动参数(命令行参数[kubeletFlags] + 配置文件引入[KubeletConfig])的结构体
kubeletServer := &options.KubeletServer{
KubeletFlags: *kubeletFlags,
KubeletConfiguration: *kubeletConfig,
}初始化
kubeletDeps := UnsecuredDependencies(...)
此处内部会检查TLS证书、私钥等等信息。注意:它内部不会启动任何进程,仅返回适合运行的依赖项或错误
实质是是运行
Kubelet
所必须依赖的操作接口结合,它们在运行时逐渐完善。(例如:对容器的操作
依赖于对容器运行时接口的实现
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31// 查看它的结构,实际上是一个接口集合,包括对卷、容器运行时、kube-apiserver等操作的接口
type Dependencies struct {
Options []Option
// Injected Dependencies
Auth server.AuthInterface
CAdvisorInterface cadvisor.Interface
Cloud cloudprovider.Interface
ContainerManager cm.ContainerManager
DockerOptions *DockerOptions // 此处被实例化
EventClient v1core.EventsGetter
HeartbeatClient clientset.Interface
OnHeartbeatFailure func()
KubeClient clientset.Interface
Mounter mount.Interface
HostUtil hostutil.HostUtils
OOMAdjuster *oom.OOMAdjuster
OSInterface kubecontainer.OSInterface
PodConfig *config.PodConfig
Recorder record.EventRecorder
Subpather subpath.Interface
VolumePlugins []volume.VolumePlugin
DynamicPluginProber volume.DynamicPluginProber
TLSOptions *server.TLSOptions
KubeletConfigController *kubeletconfig.Controller
RemoteRuntimeService internalapi.RuntimeService
RemoteImageService internalapi.ImageManagerService
dockerLegacyService legacy.DockerLegacyService
// remove it after cadvisor.UsingLegacyCadvisorStats dropped.
useLegacyCadvisorStats bool
}将上面实例化的
Configuration控制器
加入到kubeletDeps
中未启动态
KubeletConfig
配置时,此值为nil1
kubeletDeps.KubeletConfigController = kubeletConfigController // 实质上也再次表明了kubeletDeps的作用
检查权限
checkPermissions()
即确保当前执行
kubelet
的系统用户的uid
为0,通常即root
用户。可通过如下示例查看当前用户信息1
2[root@Centos7 ~]# id
uid=0(root) gid=0(root) 组=0(root)设置上下文信号,以便
kubelet
和docker shim
重复使用ctx := genericapiserver.SetupSignalContext()
这里需要了解
golang
标准库的context
,执行cancel()
后,所有ctx.done()
将成功运行。可参考:https://blog.csdn.net/u011957758/article/details/82948750
实际上是启动一个go线程,监听系统信号
syscall.SIGTERM
(即操作系统的pkill
)和os.Interrupt
(通常由Ctrl+C
触发),即中断程序信号
- 第一次收到中断信号,将为
ctx
执行cancel()
,这将使得所有<-ctx.done()
结束阻塞,一般情况会执行go 线程正常退出 - 第二次收到中断信号,直接使用
os.Exit(1)
强制结束进程
- 第一次收到中断信号,将为
访问
Pod
时隐藏头部信息此处没看懂如何生效
1
2
3
4config := kubeletServer.KubeletConfiguration.DeepCopy()
for k := range config.StaticPodURLHeader {
config.StaticPodURLHeader[k] = []string{"<masked>"}
}运行kubelet
1
2
3
4
5// ctx:
// kubeletServer:kubelet运行时所有输入参数
// kubeletDeps: 存放kubelet运行依赖接口的结构体指针
// utilfeature.DefaultFeatureGate: 描述了本次运行针对若干版本特性的开启/关闭
Run(ctx, kubeletServer, kubeletDeps, utilfeature.DefaultFeatureGate)
设置
cleanFlagSet
添加
kubeletFlags
(即命令行参数)添加
kubeletconfig
对应的flags(虽然推荐使用配置文件,但仍旧保留命令行参数,标记为Deprecated
添加
GlobalFlags
,即补上相比原生的命令行应用(即flag.CommandLine
)缺少的那部分全局flags
。经历此步骤以后,自定义的
cleanFlagSet
具备原生自带的flag.CommandLine
的所有功能
替换
cmd
的默认UsageFunc
andHelpFunc
因为默认的这两个函数会由于
global flags
污染自定义的flagset
1
2
3
4
5
6
7
8const usageFmt = "Usage:\n %s\n\nFlags:\n%s"
cmd.SetUsageFunc(func(cmd *cobra.Command) error {
fmt.Fprintf(cmd.OutOrStderr(), usageFmt, cmd.UseLine(), cleanFlagSet.FlagUsagesWrapped(2))
return nil
})
cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
fmt.Fprintf(cmd.OutOrStdout(), "%s\n\n"+usageFmt, cmd.Long, cmd.UseLine(), cleanFlagSet.FlagUsagesWrapped(2))
})
4. 运行kubelet
入口:
1
2
3
4
5 // ctx:
// kubeletServer:kubelet运行时所有输入参数
// kubeletDeps: 存放kubelet运行依赖接口的结构体指针
// utilfeature.DefaultFeatureGate: 描述了本次运行针对若干版本特性的开启/关闭
Run(ctx, kubeletServer, kubeletDeps, utilfeature.DefaultFeatureGate)
针对
Windows
运行环境执行特定初始化:initForOS(s.KubeletFlags.WindowsService, s.KubeletFlags.WindowsPriorityClass)
WindowsPriorityClass
: 设置与Kubelet
进程关联的优先级类,可能的值如下:- IDLE_PRIORITY_CLASS (64)
- BELOW_NORMAL_PRIORITY_CLASS (16384)
- NORMAL_PRIORITY_CLASS (32)
- ABOVE_NORMAL_PRIORITY_CLASS (32768)
- HIGH_PRIORITY_CLASS (128)
- REALTIME_PRIORITY_CLASS (256)
1
2// 注意区分此处`init_windows.go`和`init_windows_test.go`
initForOS(s.KubeletFlags.WindowsService, s.KubeletFlags.WindowsPriorityClass)执行
run(ctx, s, kubeDeps, featureGate)
更新
Feature Gate
验证
KubeletConfig
和KubeletFlags
参数合法性:options.ValidateKubeletServer(...)
验证通过
文件锁(flock)
协调潜在的多个运行的Kubelet
进程时,给定参数是否合法:判断s.ExitOnLockContention
和s.LockFilePath
的值如果
flock
路径存在- 获取
Lock
1
unix.Flock(fd, unix.LOCK_EX)
LOCK_SH
: 共享锁,在给定时间内多个进程可能持有给定文件的共享锁LOCK_EX
: 互斥锁,在给定时间内只有一个进程可以持有给定文件的互斥锁LOCK_UN
: 删除此进程当前持有的锁
成功时返回nil,否则返回error。
如果
kubelet
设置为ExitOnLockContention
(已经有kubelet
在运行时直接Exit
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23func watchForLockfileContention(path string, done chan struct{}) error {
// 初始化一个Watcher
// `go w.readEvents()`开启一个go线程,循环读取事件信息,解析成Event发送到 w.Event channel。
// 当系统事件信息通道被关闭(read返回0),或者done channel被写入数据时,事件内容解析结束
watcher, err := inotify.NewWatcher()
// ...
// 向操作系统注册对flock文件的监控,此时readEvents()将开始能得到数据,之前应处于读阻塞状态
watcher.AddWatch(path, inotify.InOpen|inotify.InDeleteSelf)
// ...
go func() {
select {
case ev := <-watcher.Event: // 读取到Event时退出select
klog.InfoS("inotify event", "event", ev)
case err = <-watcher.Error:
klog.ErrorS(err, "inotify watcher error")
}
close(done) // 停止ReadEvent
watcher.Close() // 向操作系统取消对flock文件的监控
}()
return nil
}
- 获取
初始化
configz
:initConfigz(...)
即将
kubeletconfig
转化至v1beta1
版本格式,存储在configz
包的全局变量configs
中,其key="kubeletconfig"
configs
类型为map[string]*Config
1
2
3type Config struct {
val interface{}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19func initConfigz(kc *kubeletconfiginternal.KubeletConfiguration) error {
// 实质上cs := &(configz.configs["kubeletconfig"])
// 上述configs是configz包外不可见的全局变量,所以`configz.configs`形式仅便于理解,实际上不符合语法!!
cz, err := configz.New("kubeletconfig")
// ...
setConfigz(cz, kc)
// ...
return nil
}
func setConfigz(cz *configz.Config, kc *kubeletconfiginternal.KubeletConfiguration) error {
// 定义格式转化器
versioned := kubeletconfigv1beta1.KubeletConfiguration{}
// ...
scheme.Convert(kc, &versioned, nil) // 将kubeletconfig转化为v1beta1版本格式
//...
cz.Set(versioned) // [忽略语法问题] 相当于configz.configs["kubeletconfig"].val = versioned
return nil
}判断
s.ShowHiddenMetricsForVersion
显示隐藏指标的版本,此值暂未仔细研究,描述文档内容如下:
The previous version for which you want to show hidden metrics.
Only the previous minor version is meaningful, other values will not be allowed.
The format is. , e.g.: ‘1.16’.
The purpose of this format is make sure you have the opportunity to notice if the next release hides additional metrics,
rather than being surprised when they are permanently removed in the release after that.
Logging specifies the options of logging.判断是否进入
standaloneMode
,当--kubeconfig
未设置或内容为""
时将开启此时
Kubelet
将无需Kube-ApiServer
可独立运行,通常用于调试、测试等容错性处理,如果传入的
kubeDeps
为nil
,将在此处用kubelet参数
和featuregate
初始化在正常情况下,此处传入的
kubeDeps
在cmd的run
中已经赋值初始化云管理控制器
--cloud-provider
同于指定第三方的类似kube-controller-manager
,此部分详见:kubernetes云管理控制器文档- 若
--cloud-provider=external
,跳过此步骤 - 否则:
- 对于非
external
的弃用日志提示:- 如果是
openstack
,则日志提示修正为external
,并给出弃用
警告 - 如果是
aws
、azure
、gce
、vsphere
,则直接给出弃用
警告 - 否则,无操作
- 如果是
- 初始化云管理控制器为
cloud
- 如果未指定
--cloud-provider
,或者检测到--cloud-provider=external
,则cloud=nil
- 否则,根据
--cloud-config
指定的文件初始化cloud
- 如果未指定
- 对于非
- 若
读入
node-hostname
,此处字母会自动转化为小写。如果未通过--hostname-override
赋值,将通过os.Hostname()
自动获取提示:正常情况下,
hostname
大小写不敏感读取
node-nodename
仅当已经成功初始化
cloud-provider
时,从云管理控制器获取节点名称
,否则指定为hostname
,即与上述node-hostname
相同