kubelet的主体流程部分,主要是为了理解kubelet组件的主体流程是如何运行的,是如何获取pod信息,然后如何对pod进行部署和update等操作。
(主要是根据网上一些公开的信息,再根据自己的理解来进行整合,加深自己对k8s源码的学习)
1、从cmd/kubelet/kubelet.go开始main()函数
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
//kubelet 的main函数入口,新建一个NewKubeletServer
//NewKubeletServer()初始化kubelet Server的fields为默认值。然后在初始化flags和logs之后就可开始Run kubelet Server
s := app.NewKubeletServer()
//解析flag
s.AddFlags(pflag.CommandLine)
//future work:后面要了解参数是如何写到系统里面的?是InitFlags如何运作么?
util.InitFlags()
util.InitLogs()
defer util.FlushLogs()
verflag.PrintAndExitIfRequested()
if err := s.Run(nil); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
}
main函数主要执行NewKubeletServer()、AddFlags(pflag.CommandLine)、 s.Run(nil)这三个步骤,下面具体分析这三个函数
2、NewKubeletServer()解析
定义在cmd/kubelet/server.go
NewKubeletServer()创建一个KubeletServer,主要是完成参数的初始化—with default values
return &KubeletServer{…}
下面 给出部分参数的含义:
Address: net.ParseIP("0.0.0.0"),
ContainerRuntime: "docker",
DockerExecHandlerName: "native",
HealthzBindAddress: net.ParseIP("127.0.0.1"),
HealthzPort: 10248,
ImageGCHighThresholdPercent: 90,//表示此盘利用率超过90%的时候,会一直对image资源进行回收
ImageGCLowThresholdPercent: 80,//表示此盘利用率低于80%的时候,不会进行GC
KubeConfig: util.NewStringFlag("/var/lib/kubelet/kubeconfig"),
MaxContainerCount: 100, //每个节点最多保留100个死亡实例
MaxPerPodContainerCount: 2, //每个容器最多保留2个死亡实例
RegisterNode: true, // will be ignored if no apiserver is configured
ResourceContainer: "/kubelet",
RootDirectory: defaultRootDir, //默认值是/var/lib/kubelet,存放配置及VM卷等数据
3、 s.Run(nil)
定义在cmd/kubelet/server.go
/*
Run 基于指定的KubeletConfig运行一个KubeletServer,never exist!
KubeletConfig可能是nil的。If nil, 在KubeletServer中利用默认值完成初始化设置
If not nil,the default values 会被忽略
*/
func (s *KubeletServer) Run(kcfg *KubeletConfig) error {
if kcfg == nil {
//第一次是通过s.Run(nil)来调用
//准备一个KubeletConfig,配置一些参数
//KubeletConfig会返回适合运行的KubeletConfig,如果服务器设置无效,则返回错误。 它不会启动任何后台进程。
cfg, err := s.KubeletConfig()**[1]**
if err != nil {
return err
}
kcfg = cfg
//调用CreateAPIServerClientConfig初始化clientConfig
//CreateAPIServerClientConfig使用command line flags来生成 client.Config,including api-server-list
//KubeClient是kubelet 和 Api server传递信息的唯一途径。
CreateAPIServerClientConfig根据用户的传递--kubeconfig或者默认.kubeconfig文件来解析client配置。
clientConfig, err := s.CreateAPIServerClientConfig()
if err == nil {
/*
最终初始化KubeClient。
定义在client "k8s.io/kubernetes/pkg/client/unversioned/helper.go"
New(c *Config)为指定的配置创建一个Kubernetes client。
该client可以对pods,replication controllers, daemons, and services这些对象执行list, get, update and delete操作。
如果提供的配置无效,则返回错误。
*/
kcfg.KubeClient, err = client.New(clientConfig)
}
if err != nil && len(s.APIServerList) > 0 {
glog.Warningf("No API client: %v", err)
}
//cloudprovider 和IaaS云商有关
cloud, err := cloudprovider.InitCloudProvider(s.CloudProvider, s.CloudConfigFile)
if err != nil {
return err
}
glog.V(2).Infof("Successfully initialized cloud provider: %q from the config file: %q\n", s.CloudProvider, s.CloudConfigFile)
kcfg.Cloud = cloud
}
/*
启动cadvisor来监控本地的容器
通过CAdvisor我们可以看到kuberlet管理的机器上container的资源统计信息
cadvisor源码在pkg/kubelet/cadvisor/cadvisor_linux.go中
*/
if kcfg.CAdvisorInterface == nil {
ca, err := cadvisor.New(s.CAdvisorPort)
if err != nil {
return err
}
kcfg.CAdvisorInterface = ca
}
util.ReallyCrash = s.ReallyCrashForTesting
rand.Seed(time.Now().UTC().UnixNano())
/*
设置preferred Dockercfg 文件path,这个是为了读取.dockercfg文件,
该文件中的secret可用于pull/push docker registry中的docker镜像,默认的路径为:/var/lib/kubelet
*/
credentialprovider.SetPreferredDockercfgPath(s.RootDirectory)
glog.V(2).Infof("Using root directory: %v", s.RootDirectory)
// TODO(vmarmol): Do this through container config.
oomAdjuster := oom.NewOomAdjuster()
/*
linux的oom机制,当系统发生OOM时,oom_adj值越小,越不容易被系统kill掉 kubelet一般设置自身oom值为 -900 取值范围是[-1000,+1000]
主要是通过设置/proc/ /oom_score_adj来控制
设置为-1000,该进程就被排除在OOM Killer强制终止的对象外
*/
if err := oomAdjuster.ApplyOomScoreAdj(0, s.OOMScoreAdj); err != nil {
glog.Warning(err)
}
/*
---代码中RunKubelet是下一个入口******
RunKubelet中会新起一个goroutine来异步运行kubelet;
接下来的代码还会执行:if s.HealthzPort > 0提供健康检查的http服务
*/
if err := RunKubelet(kcfg, nil); err != nil {**[2]**
return err
}
if s.HealthzPort > 0 {
/*
这段code会启动一个http server来提供health check功能,其实目前就提供了一个/healthz/ping的endpoint,返回的http status code为200就正常。
Kubernetes默认提供的http端口如下(在pkg/master/ports/ports.go中定义):
KubeletStatusPort = 10248 // kubelet的health port,就是上面的HealthzPort。
ProxyStatusPort = 10249 // kube proxy的health port。
KubeletPort = 10250 // kubelet server的port。
SchedulerPort = 10251 // kube scheduler的port。
ControllerManagerPort = 10252 // kube controller manager 的port。
KubeletReadOnlyPort = 10255 // 用于heapster监控和收集kubelet信息使用。
*/
healthz.DefaultHealthz()
go util.Until(func() {
err := http.ListenAndServe(net.JoinHostPort(s.HealthzBindAddress.String(), strconv.Itoa(s.HealthzPort)), nil)
if err != nil {
glog.Errorf("Starting health server failed: %v", err)
}
}, 5*time.Second, util.NeverStop)
}
if s.RunOnce