Pod 中容器重启流程
发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,背景测试的时候,通常需要将 Pod 中的 container 频繁地杀死,重启。在这个过程中,Pod 的状态经常会出现 CrashLoopBackOff,而且 container 重启的时间越来越长。
千家信息网最后更新 2026年11月02日Pod 中容器重启流程
背景
测试的时候,通常需要将 Pod 中的 container 频繁地杀死,重启。在这个过程中,Pod 的状态经常会出现 CrashLoopBackOff,而且 container 重启的时间越来越长。
分析
为了避免 container 频繁地 restart,k8s 对 container restart 过程做了限制,使用 back-off 的方法,官方文档中的说法是:
Failed containers that are restarted by Kubelet, are restarted with an exponential back-off delay, the delay is in multiples of sync-frequency 0, 1x, 2x, 4x, 8x … capped at 5 minutes and is reset after 10 minutes of successful execution.
- https://kubernetes-v1-4.github.io/docs/user-guide/pod-states/
这里先直接给出结论:
- 在 Pod 中 restart container 的时候(具体时机是,周期性执行 SyncPod() 的时候),Pod 会通过自身的 Status 结构找到当前这个 container(因为 Pod 中可能有多个 container)上一次退出的时间,记为 ts
- 如果是第一次 restart,那么直接重启 container,并且在 Kubelet 的 backOff.perItemBackoff (一个 map 结构,key 是根据 container 和所在 pod 对象计算出来的 id)中记录下次 backoff 的时间(初始值为 10s,然后按照指数增长,最大 5min)
- 如果不是第一次 restart,即 Kubelet 的 backOff.perItemBackoff 中已经有这个 container 的 backOff 记录,计为 backoff,那么
- 如果 now() - ts < backoff,表明等待的时间还不够,抛出 CrashLoopBackOff Event(然后等到下一个 SyncPod 的周期到的时候,重新比较这个值)
- 否则,说明已经等待 backoff 时间了,可以 restart 了,此时执行 backOff.Next(),将该容器对应的 backoff 翻倍,然后执行 restart 操作
- 在步骤 3 中计算 backoff 的过程中,还会去检查当前时间距离上一次 container 退出时的间隔,如果大于 2 * MaxContainerBackOff = 10 minutes,那么会将这个 container 对应的 backoff 重置为初始值 10s
源码细节
kubernetes/pkg/kubelet/kubelet.go
通过源码发现,kubernetes/pkg/kubelet/kubelet.go 文件中有两个常量:MaxContainerBackOff = 300 * time.SecondbackOffPeriod = time.Second * 10
使用这两个变量构造了一个 BackOff 对象,这个是 kubelet 的属性,对该 node 上所有 pod 都适用
klet.backOff = flowcontrol.NewBackOff(backOffPeriod, MaxContainerBackOff)BackOff 结构如下
type Backoff struct { sync.Mutex Clock clock.Clock defaultDuration time.Duration maxDuration time.Duration perItemBackoff map[string]*backoffEntry}然后在 SyncPod 方法中使用这个对象
// Call the container runtime's SyncPod callbackresult := kl.containerRuntime.SyncPod(pod, apiPodStatus, podStatus, pullSecrets, kl.backOff)- kubernetes/pkg/kubelet/kuberuntime/kuberuntime_manager.go
SyncPod 具体做的事有:
// SyncPod syncs the running pod into the desired pod by executing following steps://// 1. Compute sandbox and container changes.// 2. Kill pod sandbox if necessary.// 3. Kill any containers that should not be running.// 4. Create sandbox if necessary.// 5. Create init containers.// 6. Create normal containers.func (m *kubeGenericRuntimeManager) SyncPod(pod *v1.Pod, _ v1.PodStatus, podStatus *kubecontainer.PodStatus, pullSecrets []v1.Secret, backOff *flowcontrol.Backoff) (result kubecontainer.PodSyncResult) {同样在这个文件中,有一个关键的函数
// If a container is still in backoff, the function will return a brief backoff error and// a detailed error message. func (m *kubeGenericRuntimeManager) doBackOff(pod *v1.Pod, container *v1.Container, podStatus *kubecontainer.PodStatus, backOff *flowcontrol.Backoff) (bool, string, error) { var cStatus *kubecontainer.ContainerStatus for _, c := range podStatus.ContainerStatuses { if c.Name == container.Name && c.State == kubecontainer.ContainerStateExited { cStatus = c break } } if cStatus == nil { return false, "", nil } glog.Infof("checking backoff for container %q in pod %q", container.Name, format.Pod(pod)) // Use the finished time of the latest exited container as the start point to calculate whether to do back-off. ts := cStatus.FinishedAt // backOff requires a unique key to identify the container. key := getStableKey(pod, container) if backOff.IsInBackOffSince(key, ts) { if ref, err := kubecontainer.GenerateContainerRef(pod, container); err == nil { m.recorder.Eventf(ref, v1.EventTypeWarning, events.BackOffStartContainer, "Back-off restarting failed container") } err := fmt.Errorf("Back-off %s restarting failed container=%s pod=%s", backOff.Get(key), container.Name, format.Pod(pod)) glog.Infof("%s", err.Error()) return true, err.Error(), kubecontainer.ErrCrashLoopBackOff } backOff.Next(key, ts) return false, "", nil}其中 backOff.Next 函数定义如下
// move backoff to the next mark, capping at maxDurationfunc (p *Backoff) Next(id string, eventTime time.Time) { p.Lock() defer p.Unlock() entry, ok := p.perItemBackoff[id] if !ok || hasExpired(eventTime, entry.lastUpdate, p.maxDuration) { entry = p.initEntryUnsafe(id) } else { delay := entry.backoff * 2 // exponential entry.backoff = time.Duration(integer.Int64Min(int64(delay), int64(p.maxDuration))) } entry.lastUpdate = p.Clock.Now()}
时间
时候
对象
结构
过程
频繁
两个
函数
周期
文件
方法
源码
第一次
上一
容器
最大
不够
关键
变量
周期性
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
小米移动互联网科技园
博彦科技互联网金融
互联网科技工作委员会
喔噻互联网科技
新浪科技互联网
郑州华宇互联网科技
四川狮子座互联网科技
科技伦理 互联网公司
安控科技rtu产品工业互联网
互联网科技寓意
阿里互联网科技公司
语蝶互联网科技有限公司
互联网科技与大数据专业
想开互联网科技公司怎么样
畅思互联网科技
高科技互联网发展前景如何
互联网数据科技专业
众安科技工业互联网合作
易企秀互联网科技是做什么的
六子台科技互联网展会
互联网科技英文
互联网科技产品
厦门千工互联网科技有限公司
本届互联网博览会上的黑科技
晋城互联网科技
互联网第三次科技革命特征
互联网科技年终奖
南京一网一红互联网科技有限公司
唯美互联网科技
三亚科技创新互联网基地