首页 > 编程语言 >kubelet backoff源码分析

kubelet backoff源码分析

时间:2023-07-16 11:12:01浏览次数:36  
标签:lastUpdate backoff kubelet 源码 time entry Backoff id

容器拉起流程

为了避免容器频繁拉起,kubelet通过backoff来限制(backoff表示上次容器退出时间与再次创建间隔时间,lastUpdate表示上次容器创建时间,backoff和lastUpdate只会在Next函数中会更新):
Pod中重启容器时(周期性执行SyncPod函数),Pod通过自身的Status找到当前容器上一次退出时间,记为t。
如果是第一次重启,那么直接重启容器,记录下次backoff的时间(初始值为10s,然后不断*2,最大5min),更新lastUpdate(当前时间)。
如果不是第一次重启,如果now() - t < backoff,那么说明等待时间不够,抛出CrashLoopBackOff错误(等到下一个SyncPod,重新比较这个值);否则,说明已经等待backoff时间了,执行backOff.Next(),更新backoff和lastUpdate,创建新容器。
如果lastUpdate与上一次容器退出时间间隔超过10分钟,那么把backoff重置为10s,更新lastUpdate。

源码位置

staging/src/k8s.io/client-go/util/flowcontrol/backoff.go

/*
Copyright 2015 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package flowcontrol

import (
	"sync"
	"time"

	"k8s.io/apimachinery/pkg/util/clock"
	"k8s.io/utils/integer"
)

type backoffEntry struct {
	backoff    time.Duration
	lastUpdate time.Time
}

type Backoff struct {
	sync.Mutex
	Clock           clock.Clock
	defaultDuration time.Duration
	maxDuration     time.Duration
	perItemBackoff  map[string]*backoffEntry
}

func NewFakeBackOff(initial, max time.Duration, tc *clock.FakeClock) *Backoff {
	return &Backoff{
		perItemBackoff:  map[string]*backoffEntry{},
		Clock:           tc,
		defaultDuration: initial,
		maxDuration:     max,
	}
}

func NewBackOff(initial, max time.Duration) *Backoff {
	return &Backoff{
		perItemBackoff:  map[string]*backoffEntry{},
		Clock:           clock.RealClock{},
		defaultDuration: initial,
		maxDuration:     max,
	}
}

// Get the current backoff Duration
func (p *Backoff) Get(id string) time.Duration {
	p.Lock()
	defer p.Unlock()
	var delay time.Duration
	entry, ok := p.perItemBackoff[id]
	if ok {
		delay = entry.backoff
	}
	return delay
}

// move backoff to the next mark, capping at maxDuration
func (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()
}

// Reset forces clearing of all backoff data for a given key.
func (p *Backoff) Reset(id string) {
	p.Lock()
	defer p.Unlock()
	delete(p.perItemBackoff, id)
}

// Returns True if the elapsed time since eventTime is smaller than the current backoff window
func (p *Backoff) IsInBackOffSince(id string, eventTime time.Time) bool {
	p.Lock()
	defer p.Unlock()
	entry, ok := p.perItemBackoff[id]
	if !ok {
		return false
	}
	if hasExpired(eventTime, entry.lastUpdate, p.maxDuration) {
		return false
	}
	return p.Clock.Since(eventTime) < entry.backoff
}

// Returns True if time since lastupdate is less than the current backoff window.
func (p *Backoff) IsInBackOffSinceUpdate(id string, eventTime time.Time) bool {
	p.Lock()
	defer p.Unlock()
	entry, ok := p.perItemBackoff[id]
	if !ok {
		return false
	}
	if hasExpired(eventTime, entry.lastUpdate, p.maxDuration) {
		return false
	}
	return eventTime.Sub(entry.lastUpdate) < entry.backoff
}

// Garbage collect records that have aged past maxDuration. Backoff users are expected
// to invoke this periodically.
func (p *Backoff) GC() {
	p.Lock()
	defer p.Unlock()
	now := p.Clock.Now()
	for id, entry := range p.perItemBackoff {
		if now.Sub(entry.lastUpdate) > p.maxDuration*2 {
			// GC when entry has not been updated for 2*maxDuration
			delete(p.perItemBackoff, id)
		}
	}
}

func (p *Backoff) DeleteEntry(id string) {
	p.Lock()
	defer p.Unlock()
	delete(p.perItemBackoff, id)
}

// Take a lock on *Backoff, before calling initEntryUnsafe
func (p *Backoff) initEntryUnsafe(id string) *backoffEntry {
	entry := &backoffEntry{backoff: p.defaultDuration}
	p.perItemBackoff[id] = entry
	return entry
}

// After 2*maxDuration we restart the backoff factor to the beginning
func hasExpired(eventTime time.Time, lastUpdate time.Time, maxDuration time.Duration) bool {
	return eventTime.Sub(lastUpdate) > maxDuration*2 // consider stable if it's ok for twice the maxDuration
}

SyncPod调用回退模块流程图

回退模块流程

判断是否还在回退中

更新backoff和lastupdate

总结

标签:lastUpdate,backoff,kubelet,源码,time,entry,Backoff,id
From: https://www.cnblogs.com/WJQ2017/p/17557591.html

相关文章

  • kubelet健康检查的3种方式
    httpGet发送一个HTTP请求,当返回码介于200~400之间时,检查成功。livenessProbe:httpGet:path:/index.htmlport:80httpHeaders:-name:X-Custom-Headervalue:AwesomeinitialDelaySeconds:5periodSeconds:5exec在容器中执行指定的......
  • goland+dlv远程调试kubelet
    Goland配置cd到main函数所在的go文件目录执行下面命令等待2分钟左右,直到出现APIserverlisteningat:[::]:8033/root/Downloads/dlvdebug--headless--listen=:8033--api-version=2----bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf--kubeconfig=/etc......
  • EaselJS 源码分析系列--第二篇
    在第一篇中我们大致分析了从:创建舞台->添加显示对象->更新显示对象的源码实现这一篇将主要分析几个常用显示对象自各draw方法的实现让我们看向例子examples/Text_simple.html这个例子中使用了三个显示对象类Bitmap、Text、ShapeBitmapdraw以下例子中添加了一......
  • 太爆了!阿里最新出品2023版JDK源码学习指南,Github三天已万赞
    近后台收到很多粉丝私信,说的是程序员究竟要不要去读源码?当下行情,面试什么样的薪资/岗位才会被问到源码?对此,我的回答是:一定要去读,并且要提到日程上来!据不完全统计,现在市面上不管是初级,中级,还是高级岗,面试的时候都有可能会问到源码中的问题,它已经成为程序员常规必备的一个技术点。如......
  • Python pygame实现中国象棋单机版源码
    今天给大家带来的是关于Python实战的相关知识,文章围绕着用Pythonpygame实现中国象棋单机游戏版展开,文中有非常详细的代码示例,需要的朋友可以参考下#-*-coding:utf-8-*-"""CreatedonSunJun1315:41:562021@author:Administrator"""importpygamefrompygame.local......
  • 如何定义yum源以及定制本地yum源码
    1、如何指定yum源地址cd/etc/yum.repos.d 可以指定centos、阿里云、163等,可自行百度搜索配置2、如何自定义yum源以centos集群为例制作yum源;当我们采用最小安装的方式安装完Linux系统后,会发现输入常用命令显示没有该命令,一般做法就使用yum命令进行安装;但是yum......
  • 下载k8s源码
    设置GOPATH环境变量goenv-wGO111MODULE=autocd$GOPATHmkdir-psrc/k8s.iocdsrc/k8s.iogitclonehttps://github.com/kubernetes/kubernetes.gitcdkubernetesgitcheckoutrelease-1.15设置GolandFile->Settings->GO->GOPATH勾选UseGOPATHthat's......
  • Windows子系统Ubuntu或虚拟机Ubuntu通过编译源码的方式安装wine8.0.1
    wine源码编译安装下载源码源码链接为:wine源码本文以8.1.1版本为例,下载的源码包为:wine-8.11.tar.xz拷贝包到Ubuntu使用xftp或其他工具,将压缩包拷贝到ubuntu下的home/$username/目录解包tar-Jxfwine-8.11.tar.xz //xz格式的包或tar-xvfyour_tar_file.tar //tar格式......
  • React18内核探秘:手写React高质量源码迈向高阶开发
    第1章课程简介试看1节|8分钟导学介绍课程内容,及你所获得~第2章登高望远,手写源码前的思想准备8节|54分钟建立全局观,为后续在源码中吸取精华做好思想准备,避免就源码而分析源码。第3章原始版-初始化渲染:实现最原始的渲染过程11节|122分钟实现初次渲染的基础逻辑,初步体验......
  • EaselJS 源码分析系列--第一篇
    什么是EaselJS?事儿还得从Flash说起,因为我最早接触的就是Flash,从Flash入行编程的Flash最早的脚本是Actionscript2.0它的1.0我是没用过。Actionscript2.0与Javascript非常像(es3时代的Javascript)后来又推出了完全面向对象的Actionscript3.0而毕业后的我也......