Kubernetes
源码版本:remotes/origin/release-1.25
Kubernetes
编译出来的Kubelet
版本:Kubernetes v1.24.0-beta.0.2463+ee7799bab469d7
Kubernetes
集群实验环境:使用Kubernetes v1.25.4
二进制的方式搭建了一个单节点集群
K8S 单节点单节点搭建可以参考:Kubernetes v1.25 搭建单节点集群用于Debug K8S源码
Golang
版本:go1.19.3 linux/amd64
IDEA
版本:2022.2.3
Delve
版本:1.9.1
[root@k8s-master1 kubernetes]#
[root@k8s-master1 kubernetes]# dlv version
Delve Debugger
Version: 1.9.1
Build: $Id: d81b9fd12bfa603f3cf7a4bc842398bd61c42940 $
[root@k8s-master1 kubernetes]#
[root@k8s-master1 kubernetes]# go version
go version go1.19.3 linux/amd64
[root@k8s-master1 kubernetes]#
[root@k8s-master1 kubernetes]# kubectl version
WARNING: This version information is deprecated and will be replaced with the output from kubectl version --short. Use --output=yaml|json to get the full version.
Client Version: version.Info{Major:"1", Minor:"25", GitVersion:"v1.25.4", GitCommit:"872a965c6c6526caa949f0c6ac028ef7aff3fb78", GitTreeState:"clean", BuildDate:"2022-11-09T13:36:36Z", GoVersion:"go1.19.3", Compiler:"gc", Platform:"linux/amd64"}
Kustomize Version: v4.5.7
Server Version: version.Info{Major:"1", Minor:"25", GitVersion:"v1.25.4", GitCommit:"872a965c6c6526caa949f0c6ac028ef7aff3fb78", GitTreeState:"clean", BuildDate:"2022-11-09T13:29:58Z", GoVersion:"go1.19.3", Compiler:"gc", Platform:"linux/amd64"}
[root@k8s-master1 kubernetes]#
[root@k8s-master1 kubernetes]#
[root@k8s-master1 kubernetes]# kubectl get nodes -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master1 Ready 31h v1.25.4 192.168.11.71 CentOS Linux 7 (Core) 3.10.0-1160.80.1.el7.x86_64 containerd://1.6.10
[root@k8s-master1 kubernetes]#
[root@k8s-master1 kubernetes]#
[root@k8s-master1 kubernetes]# kubectl get componentstatus
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
etcd-0 Healthy {"health":"true","reason":""}
controller-manager Healthy ok
scheduler Healthy ok
[root@k8s-master1 kubernetes]#
Kubelet
启动参数配置如下:
[root@k8s-master1 kubernetes]# ps -ef|grep "/usr/local/bin/kubelet"
root 7972 1 6 07:06 ? 00:00:06 /usr/local/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig --kubeconfig=/etc/kubernetes/kubelet.kubeconfig --config=/etc/kubernetes/kubelet-conf.yml --container-runtime-endpoint=unix:///run/containerd/containerd.sock --node-labels=node.kubernetes.io/node= --v=8
root 9549 6424 0 07:07 pts/0 00:00:00 grep --color=auto /usr/local/bin/kubelet
[root@k8s-master1 kubernetes]#
Kubelet
参数配置如下:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
address: 0.0.0.0
port: 10250
readOnlyPort: 10255
authentication:anonymous:enabled: falsewebhook:cacheTTL: 2m0senabled: truex509:clientCAFile: /etc/kubernetes/pki/ca.pem
authorization:mode: Webhookwebhook:cacheAuthorizedTTL: 5m0scacheUnauthorizedTTL: 30s
cgroupDriver: systemd
cgroupsPerQOS: true
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
containerLogMaxFiles: 5
containerLogMaxSize: 10Mi
contentType: application/vnd.kubernetes.protobuf
cpuCFSQuota: true
cpuManagerPolicy: none
cpuManagerReconcilePeriod: 10s
enableControllerAttachDetach: true
enableDebuggingHandlers: true
enforceNodeAllocatable:
- pods
eventBurst: 10
eventRecordQPS: 5
evictionHard:imagefs.available: 15%memory.available: 100Minodefs.available: 10%nodefs.inodesFree: 5%
evictionPressureTransitionPeriod: 5m0s
failSwapOn: true
fileCheckFrequency: 20s
hairpinMode: promiscuous-bridge
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 20s
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
imageMinimumGCAge: 2m0s
iptablesDropBit: 15
iptablesMasqueradeBit: 14
kubeAPIBurst: 10
kubeAPIQPS: 5
makeIPTablesUtilChains: true
maxOpenFiles: 1000000
maxPods: 110
nodeStatusUpdateFrequency: 10s
oomScoreAdj: -999
podPidsLimit: -1
registryBurst: 10
registryPullQPS: 5
resolvConf: /etc/resolv.conf
rotateCertificates: true
runtimeRequestTimeout: 2m0s
serializeImagePulls: true
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 4h0m0s
syncFrequency: 1m0s
volumeStatsAggPeriod: 1m0s
Util.Manager
是一个通用Manager
的抽象,基于此Manager
,我们可以用于简单的管理一些资源对象,譬如,SecretManager, ConfigMapManager
就是基于Util.Manager
实现的
Manager |
我们首先看看Manager
的接口定义,一共定义了三个接口,如下:
GetObject
:既然是用于管理某种资源,那么肯定需要一个接口获取该资源,GetObject
接口就是用来干这个事情的。在K8S
中,使用namespace
作为资源的简单隔离,使用name
做为资源在同一namespace
的唯一标识,因此使用namespace, name
作为参数RegisterPod, UnRegisterPod
暂时还不清楚咋用,但是这两接口的实现必须是幂等的// pkg/kubelet/util/manager/manager.go
type Manager interface {GetObject(namespace, name string) (runtime.Object, error)RegisterPod(pod *v1.Pod)UnregisterPod(pod *v1.Pod)
}
CacheBasedManager |
Util.Manager
一共有两种实现,CacheBasedManager
就是其中一种实现,我们来看看其具体逻辑
Store |
除了Manager
接口,Util.Manager
中还定义了Store
接口
// pkg/kubelet/util/manager/manager.go
type Store interface {AddReference(namespace, name string)DeleteReference(namespace, name string)Get(namespace, name string) (runtime.Object, error)
}
ObjectStore |
Store
接口一共有两种实现,其中之一就是ObjectStore
,它是基于TTL
的实现,比较重要的是GetObjectFunc, GetObjectTTLFunc
;
GetObjectFunc
:该方法一般是使用OjbjectStore
方传递进来,一般使用就是根据name, namespace
查询apiserver
GetObjectTTLFunc
:追踪了以下源码,这个方法一般是查询当前Node
的Annotation
,这个Annotation
的Key
为node.alpha.kubernetes.io/ttl
,值就是TTL
值// GetObjectTTLFunc defines a function to get value of TTL.
type GetObjectTTLFunc func() (time.Duration, bool)// GetObjectFunc defines a function to get object with a given namespace and name.
type GetObjectFunc func(string, string, metav1.GetOptions) (runtime.Object, error)type objectKey struct {namespace stringname stringuid types.UID
}// objectStoreItems is a single item stored in objectStore.
type objectStoreItem struct {refCount intdata *objectData
}type objectData struct {sync.Mutexobject runtime.Objecterr errorlastUpdateTime time.Time
}// objectStore is a local cache of objects.
type objectStore struct {getObject GetObjectFuncclock clock.Clocklock sync.Mutexitems map[objectKey]*objectStoreItemdefaultTTL time.DurationgetTTL GetObjectTTLFunc
}
AddReference |
具体逻辑如下:
name
以及namespace
生成对象的Key
,这个Key
就算缓存Map
的Key
1
func (s *objectStore) AddReference(namespace, name string) {key := objectKey{namespace: namespace, name: name}s.lock.Lock()defer s.lock.Unlock()item, exists := s.items[key]if !exists {item = &objectStoreItem{refCount: 0,data: &objectData{},}s.items[key] = item}item.refCount++item.data = nil
}
DeleteReference |
源码比较简单,就是把引用计数减一
func (s *objectStore) DeleteReference(namespace, name string) {key := objectKey{namespace: namespace, name: name}s.lock.Lock()defer s.lock.Unlock()if item, ok := s.items[key]; ok {item.refCount--if item.refCount == 0 {delete(s.items, key)}}
}
Get |
我们来看看Get
的逻辑,如下:
Manager.Register
接口是用来干嘛的,apiserver
重新获取func (s *objectStore) Get(namespace, name string) (runtime.Object, error) {key := objectKey{namespace: namespace, name: name}data := func() *objectData {s.lock.Lock()defer s.lock.Unlock()item, exists := s.items[key]if !exists {return nil}if item.data == nil {item.data = &objectData{}}return item.data}()if data == nil {return nil, fmt.Errorf("object %q/%q not registered", namespace, name)}data.Lock()defer data.Unlock()if data.err != nil || !s.isObjectFresh(data) {opts := metav1.GetOptions{}if data.object != nil && data.err == nil {util.FromApiserverCache(&opts)}object, err := s.getObject(namespace, name, opts)if err != nil && !apierrors.IsNotFound(err) && data.object == nil && data.err == nil {return object, err}if (err == nil && !isObjectOlder(object, data.object)) || apierrors.IsNotFound(err) {data.object = objectdata.err = errdata.lastUpdateTime = s.clock.Now()}}return data.object, data.err
}
ObjectCache |
AddReference |
DeleteReference |
Get |
下一篇:端口号及作用