
pod还未调度,pod的nodeName是空的,此时pod处于Pending状态。调度后此时pod处于ContainerCreating状态。启动后pod处于Running状态。用户删除pod时,pod立即处于Terminating状态。停止容器进程,删除网络,卸载目录挂载,删除finalizer。即删除所有和pod有关的对象(gone)。pod中的所有容器进程都异常退出了,或者至少有一个容器进程exit非0,且重启策略为Never,那么pod处于Failed状态。node由于网络原因,无法上报状态,那么pod处于Unknown状态。pod中的所有容器进程都正常退出了,且重启策略为Never,那么pod处于Successd状态。pod被kubelet驱逐了,那么pod处于Evicted状态。下图就是上面pod状态流转步骤的简化,Pod状态机:


kubectl get pod中的STATUS是由pod中status的conditions和phase计算得来的。

常见的比如CrashLoopBackOff:phase状态为running,但是容器进程退出了。
最下面的Outofcpu/OutofMemory:由于kubelet有准入插件,当node的cpu或者内存不足时,就会出现这个状态。

resources.memory.request 防止容器进程被 OOMKill;emptydir.sizeLimit 并且确保数据写入不超过 emptyDir 的限制,防止 Pod 被驱逐。超过期望副本数最大比例(或最大值),这个值调的越大,副本更新速度越快。不可用副本数最大比例(或最大值),这个值越小,越能保证服务稳定,更新越平滑;


当计算节点检测到内存压力时,Kubernetes 会按 BestEffort-> Burstable->Guaranteed的顺序驱逐pod,Burstable 适用于大多数场景。因为它既支持超卖,又锁定一定的资源,可以平衡资源利用率和应用的性能。
当node状态异常时,nodeLifeCycleController会监听这种node和node上的pod。当node状态为notReady或unreachable时,这个node就会被打上如下的taint。
NoExecute:node上的pod被驱逐NoSchedule:不往这个node上调度podtaints:
- effect: NoSchedule
key: node.kubernetes.io/unreachable
timeAdded: "2022-03-09T11:25:10Z"
- effect: NoExecute
key: node.kubernetes.io/unreachable
timeAdded: "2022-03-09T11:25:21Z"
- effect: NoSchedule
key: node.kubernetes.io/not-ready
timeAdded: "2022-03-09T11:24:28Z"
- effect: NoExecute
key: node.kubernetes.io /not-ready
timeAdded: "2022-03-09T11:24:32z"
但是pod也有对应的tolerations。由于网络可能会抖动,所以需要tolerationSeconds,默认是300s。如果是依赖于本地存储状态的有状态应用应增大 toleration Seconds 比如900s以避免被驱逐。

在初始化阶段(Ready 之前)进行的健康检查,startupPorbe运行后才运行liveness和readness。此Probe应该设置较长的间隔时间,避免过于频繁的监测影响应用启动。就绪状态检查,只在pod刚创建时才会有,标志着这个pod创建之后是否符合起来了的标准,通过之后,pod进入ready状态。存活探测,只在pod成功ready运行之后,才会进行的探测。确保pod一直处于正常可提供服务的状态,检查失败时,意味着该应用进程已经无法正常提供服务,kubelet会终止该容器进程,并按照 restartPolicy 决定是否重启。状态应该由某控制器修改。apiVersion: v1
kind: Pod
...
spec:
readinessGates:
# 这个配置只是加了个conditions.type
- conditionType: www.example.com/feature-1
dnsPolicy: ClusterFirst
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2022-09-12T09:14:26Z"
message: corresponding condition of pod readiness gate "www.example.com/feature-1"
does not exist.
reason: ReadinessGatesNotReady
status: "False"
# 上面说加了个conditions.type,为什么type是ready?
type: Ready
未解决疑问:为什么type是ready?
Post-start:容器启动后还需要做一些额外的操作,可以执行Post-start script。无法保证script和容器的 Entrypoint谁先运行。
Pre-Stop:用户删除容器时,会先运行Pre-Stop script,这里面可以定义优雅终止。然后kubelet会发kill -SIGTERM不再接受新的连接,然后再发kill -SIGKILL。



优雅的初始化进程应该:
正确处理系统信号量,将信号量转发给子进程;先等待并确保所有子进程退出;清理孤儿子进程。func main() {
...
klog.Info("Server Started")
// 监听 OS shutdown 信号
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
<-signalChan
klog.Info("Server Stopped")
ctx, concel := context.WithTimeout(context.Background(), 5*time.Second)
defer func {
// extra handling here
concel()
}
if err := svr.Shutdown(ctx); err != nil {
klog.Errorf("HTTP Server Shutdown Failed: %v", err)
}
}