概述
Kubernetes 基础的第一篇,从Pod开始,入门部分参考华为云的文档,深入部分参考design proposals和k8s源码。
内容
101笔记
关键字段
- metadata
- spec.containers
- spec.containers.resources.requests/limits
- spec.containers.env
- spec.containers.command
- spec.imagePullSecrets
优雅退出
需要容器内部代码处理信号,进行优雅退出
- SIGTERM
- SIGKILL
lifecycle
- spec.containers.lifecycle.postStart
- spec.containers.lifecycle.preStop
PLEG proposal
Pod Lifecycle Event Generator 提出的目的是取代老kubelet为每个Pod创建一个routine导致的性能和拓展性问题。
Goals
- 减少不必要的event
- 降低对Runtime的并发请求
- 支持不同的Runtime
Overview
- kubelet监听2个方向的事件,1. api-server的Pod的spec改变;2. Runtime的Pod的status改变
- PLEG解决的是第2种事件
Details
- type PodLifecycleEventGenerator interface (pleg.go)
- type GenericPLEG struct (generic.go)
- Start流程:
- go wait.Until 启动周期性 relist
- 从Runtime获取所有Pod,更新current
- 产生event
- 更新cache
- 更新old:g.podRecords.update(pid)
- 发送event(chan满了则丢弃事件)
- 更新cache Time
Pod Cache Proposal
不同于 https://git.k8s.io/kubernetes/pkg/kubelet/container/runtime_cache.go
,runtime-pod-cache是对PodStatus的缓存,而且尽可能做到最新,以便kubelet减少通过CRI获取容器状态的次数。
interface
type Cache interface {
Get(types.UID) (*PodStatus, error)
Set(types.UID, *PodStatus, error, time.Time)
// GetNewerThan is a blocking call that only returns the status
// when it is newer than the given time.
GetNewerThan(types.UID, time.Time) (*PodStatus, error)
Delete(types.UID)
UpdateTime(time.Time)
}
cache实现
type cache struct {
// Lock which guards all internal data structures.
lock sync.RWMutex
// Map that stores the pod statuses.
pods map[types.UID]*data
// cache中所有Pod都是在timestamp之后存入cache的
timestamp *time.Time
// Map that stores the subscriber records.
subscribers map[types.UID][]*subRecord
}
type data struct {
// 类似于v1.Pod中的ContainerStatus
status *PodStatus
// Error got when trying to inspect the pod.
err error
// Time when the data was last modified.
modified time.Time
}
subscribe 和 notify 机制
注意 interface 中有个特殊的方法:GetNewerThan(types.UID, time.Time) (*PodStatus, error)。 它的语义是当UID容器在ts之后更新时,获取到它的status(阻塞式)。
这里就需要注册机制(func (c *cache) subscribe
):
- 阻塞通过
ch := make(chan *data, 1)
和 <- ch实现 - 注册通过
c.subscribers[id] = append(c.subscribers[id], &subRecord{time: timestamp, ch: ch})
notify 机制也不复杂,本质上是一个slice,当ts发生更新时,遍历slice中符合条件的订阅者,向他们发送事件,剩下的slice如果长度大于0,则赋值给slice成员,否则删除这个UID的注册