K8s中Pod健康检查源代码分析

了解k8s中的Liveness和Readiness

Liveness: 
表明是否容器正在运行。如果liveness探测为fail,则kubelet会kill掉容器,并且会触发restart设置的策略。默认不设置的情况下,该状态为success.
Readiness: 
表明容器是否可以接受服务请求。如果readiness探测失败,则endpoints控制器会从endpoints中摘除该Pod IP。在初始化延迟探测时间之前,默认是Failure。如果没有设置readiness探测,该状态为success。

代码分析

基于Kubernetes 1.11.0

1.启动探测

在kubelet启动是时候会启动健康检查的探测:
kubelet.go中Run方法

...
kl.probeManager.Start() //启动探测服务
...

2.看一下probeManager都做了哪些事情

prober_manager.go中我们看一下这段代码:

// Manager manages pod probing. It creates a probe "worker" for every container that specifies a
// probe (AddPod). The worker periodically probes its assigned container and caches the results. The
// manager use the cached probe results to set the appropriate Ready state in the PodStatus when
// requested (UpdatePodStatus). Updating probe parameters is not currently supported.
// TODO: Move liveness probing out of the runtime, to here.
type Manager interface {// AddPod creates new probe workers for every container probe. This should be called for every// pod created.AddPod(pod *v1.Pod)// RemovePod handles cleaning up the removed pod state, including terminating probe workers and// deleting cached results.RemovePod(pod *v1.Pod)// CleanupPods handles cleaning up pods which should no longer be running.// It takes a list of "active pods" which should not be cleaned up.CleanupPods(activePods []*v1.Pod)// UpdatePodStatus modifies the given PodStatus with the appropriate Ready state for each// container based on container running status, cached probe results and worker states.UpdatePodStatus(types.UID, *v1.PodStatus)// Start starts the Manager sync loops.Start()
}

这是一个Manager的接口声明,该Manager负载pod的探测。当执行AddPod时,会为Pod中每一个容器创建一个执行探测任务的worker, 该worker会对所分配的容器进行周期性的探测,并把探测结果缓存。当UpdatePodStatus方法执行时,该manager会使用探测的缓存结果设置PodStatus为近似Ready的状态:

3.一“探”究竟

先看一下探测的struct

type Probe struct {// The action taken to determine the health of a containerHandler `json:",inline" protobuf:"bytes,1,opt,name=handler"`// Number of seconds after the container has started before liveness probes are initiated.// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes// +optionalInitialDelaySeconds int32 `json:"initialDelaySeconds,omitempty" protobuf:"varint,2,opt,name=initialDelaySeconds"`// Number of seconds after which the probe times out.// Defaults to 1 second. Minimum value is 1.// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes// +optionalTimeoutSeconds int32 `json:"timeoutSeconds,omitempty" protobuf:"varint,3,opt,name=timeoutSeconds"`// How often (in seconds) to perform the probe.// Default to 10 seconds. Minimum value is 1.// +optionalPeriodSeconds int32 `json:"periodSeconds,omitempty" protobuf:"varint,4,opt,name=periodSeconds"`// Minimum consecutive successes for the probe to be considered successful after having failed.// Defaults to 1. Must be 1 for liveness. Minimum value is 1.// +optionalSuccessThreshold int32 `json:"successThreshold,omitempty" protobuf:"varint,5,opt,name=successThreshold"`// Minimum consecutive failures for the probe to be considered failed after having succeeded.// Defaults to 3. Minimum value is 1.// +optionalFailureThreshold int32 `json:"failureThreshold,omitempty" protobuf:"varint,6,opt,name=failureThreshold"`
}

initialDelaySeconds: 表示容器启动之后延迟多久进行liveness探测
timeoutSeconds:每次执行探测的超时时间
periodSeconds:探测的周期时间
successThreshold:最少连续几次探测成功的次数,满足该次数则认为success。
failureThreshold:最少连续几次探测失败的次数,满足该次数则认为fail

Handler:
不论是liveness还是readiness都支持3种类型的探测方式:执行命令、http方式以及tcp方式。

// Handler defines a specific action that should be taken
// TODO: pass structured data to these actions, and document that data here.
type Handler struct {// One and only one of the following should be specified.// Exec specifies the action to take.// +optionalExec *ExecAction `json:"exec,omitempty" protobuf:"bytes,1,opt,name=exec"`// HTTPGet specifies the http request to perform.// +optionalHTTPGet *HTTPGetAction `json:"httpGet,omitempty" protobuf:"bytes,2,opt,name=httpGet"`// TCPSocket specifies an action involving a TCP port.// TCP hooks not yet supported// TODO: implement a realistic TCP lifecycle hook// +optionalTCPSocket *TCPSocketAction `json:"tcpSocket,omitempty" protobuf:"bytes,3,opt,name=tcpSocket"`
}

接下来看一下prober.go中的runProbe方法。

func (pb *prober) runProbe(probeType probeType, p *v1.Probe, pod *v1.Pod, status v1.PodStatus, container v1.Container, containerID kubecontainer.ContainerID) (probe.Result, string, error) {timeout := time.Duration(p.TimeoutSeconds) * time.Secondif p.Exec != nil {glog.V(4).Infof("Exec-Probe Pod: %v, Container: %v, Command: %v", pod, container, p.Exec.Command)command := kubecontainer.ExpandContainerCommandOnlyStatic(p.Exec.Command, container.Env)return pb.exec.Probe(pb.newExecInContainer(container, containerID, command, timeout))}if p.HTTPGet != nil {scheme := strings.ToLower(string(p.HTTPGet.Scheme))host := p.HTTPGet.Hostif host == "" {host = status.PodIP}port, err := extractPort(p.HTTPGet.Port, container)if err != nil {return probe.Unknown, "", err}path := p.HTTPGet.Pathglog.V(4).Infof("HTTP-Probe Host: %v://%v, Port: %v, Path: %v", scheme, host, port, path)url := formatURL(scheme, host, port, path)headers := buildHeader(p.HTTPGet.HTTPHeaders)glog.V(4).Infof("HTTP-Probe Headers: %v", headers)if probeType == liveness {return pb.livenessHttp.Probe(url, headers, timeout)} else { // readinessreturn pb.readinessHttp.Probe(url, headers, timeout)}}if p.TCPSocket != nil {port, err := extractPort(p.TCPSocket.Port, container)if err != nil {return probe.Unknown, "", err}host := p.TCPSocket.Hostif host == "" {host = status.PodIP}glog.V(4).Infof("TCP-Probe Host: %v, Port: %v, Timeout: %v", host, port, timeout)return pb.tcp.Probe(host, port, timeout)}glog.Warningf("Failed to find probe builder for container: %v", container)return probe.Unknown, "", fmt.Errorf("Missing probe handler for %s:%s", format.Pod(pod), container.Name)
}

1.执行命令方式
通过newExecInContainer方法调用CRI执行命令:

// ExecAction describes a "run in container" action.
type ExecAction struct {// Command is the command line to execute inside the container, the working directory for the// command  is root ('/') in the container's filesystem. The command is simply exec'd, it is// not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use// a shell, you need to explicitly call out to that shell.// Exit status of 0 is treated as live/healthy and non-zero is unhealthy.// +optionalCommand []string `json:"command,omitempty" protobuf:"bytes,1,rep,name=command"`
}

2.http GET方式
通过http GET方式进行探测。
Port:表示访问容器的端口
Host:表示访问的主机,默认是Pod IP

// HTTPGetAction describes an action based on HTTP Get requests.
type HTTPGetAction struct {// Path to access on the HTTP server.// +optionalPath string `json:"path,omitempty" protobuf:"bytes,1,opt,name=path"`// Name or number of the port to access on the container.// Number must be in the range 1 to 65535.// Name must be an IANA_SVC_NAME.Port intstr.IntOrString `json:"port" protobuf:"bytes,2,opt,name=port"`// Host name to connect to, defaults to the pod IP. You probably want to set// "Host" in httpHeaders instead.// +optionalHost string `json:"host,omitempty" protobuf:"bytes,3,opt,name=host"`// Scheme to use for connecting to the host.// Defaults to HTTP.// +optionalScheme URIScheme `json:"scheme,omitempty" protobuf:"bytes,4,opt,name=scheme,casttype=URIScheme"`// Custom headers to set in the request. HTTP allows repeated headers.// +optionalHTTPHeaders []HTTPHeader `json:"httpHeaders,omitempty" protobuf:"bytes,5,rep,name=httpHeaders"`
}

3.tcp方式
通过设置主机和端口即可进行tcp方式访问

// TCPSocketAction describes an action based on opening a socket
type TCPSocketAction struct {// Number or name of the port to access on the container.// Number must be in the range 1 to 65535.// Name must be an IANA_SVC_NAME.Port intstr.IntOrString `json:"port" protobuf:"bytes,1,opt,name=port"`// Optional: Host name to connect to, defaults to the pod IP.// +optionalHost string `json:"host,omitempty" protobuf:"bytes,2,opt,name=host"`
}

此处脑洞一下:如果三种探测方式都设置了,会如何执行处理?

思考

通过k8s部署生产环境应用时,建议设置上liveness和readiness, 这也是保障服务稳定性的最佳实践。
另外由于Pod Ready不能保证实际的业务应用Ready可用,在最新的 1.14 版本中新增了一个Pod Readiness Gates 特性 。通过这个特性,可以保证应用Ready后进而设置Pod Ready。

结尾

针对上面的脑洞:如果三种探测方式都设置了,会如何执行处理?
答:我们如果在Pod中设置多个探测方式,提交配置的时候会直接报错:
undefined
此处继续源代码:在validation.go中validateHandler中进行了限制(也为上面Handler struct提到的"One and only one of the following should be specified."提供了事实依据)


func validateHandler(handler *core.Handler, fldPath *field.Path) field.ErrorList {numHandlers := 0allErrors := field.ErrorList{}if handler.Exec != nil {if numHandlers > 0 {allErrors = append(allErrors, field.Forbidden(fldPath.Child("exec"), "may not specify more than 1 handler type"))} else {numHandlers++allErrors = append(allErrors, validateExecAction(handler.Exec, fldPath.Child("exec"))...)}}if handler.HTTPGet != nil {if numHandlers > 0 {allErrors = append(allErrors, field.Forbidden(fldPath.Child("httpGet"), "may not specify more than 1 handler type"))} else {numHandlers++allErrors = append(allErrors, validateHTTPGetAction(handler.HTTPGet, fldPath.Child("httpGet"))...)}}if handler.TCPSocket != nil {if numHandlers > 0 {allErrors = append(allErrors, field.Forbidden(fldPath.Child("tcpSocket"), "may not specify more than 1 handler type"))} else {numHandlers++allErrors = append(allErrors, validateTCPSocketAction(handler.TCPSocket, fldPath.Child("tcpSocket"))...)}}if numHandlers == 0 {allErrors = append(allErrors, field.Required(fldPath, "must specify a handler type"))}return allErrors
}

原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/518949.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSE:阿里在线应用如何演进成Serverless架构

Cloud Service Engine,简称CSE,是中间件部门研发的面向通用Serverless计算的中间件产品,目标是具备AWS Lambda的各种优势,同时可以解决AWS Lambda的关键技术缺陷。 AWS Lambda如果用于核心业务,可能会有以下缺陷&…

郫都区计算机学校,成都郫县好升学的计算机学校有哪些

【郫县好一、成都郫县希望1.成都郫县希望职业学校/招生代码:512632.成都郫县希望职业学校/学校简介:成都郫县希望职业学校学校是由郫都区教育局批准成立的,由希望集团投资创办的一所全日制、专业化的民办中等职业学校, 由郫都区教育局主管。学…

技术大佬:今年还学Python,傻了吧? 网友:就你敢说!

随着AI的兴起,Python彻底火了。据Stack Overflow调研报告:Python的月活用户已超越了Java、成为第一,全民Python已为“大势所趋”。那么,程序员有必要追捧Python吗?Python的真香是真香吗?技术大佬&#xff1…

基于Tablestore的Wifi设备监管系统架构实现

Wifi设备监管 某知名跨国公司,在全球范围内拥有大量园区,园区内会有不同部门的同事在一起办公。每个园区内都要配备大量的Wifi设备从而为园区同事提供方便的上网服务。因此,集团需要一套完善的监管系统维护所有的Wifi设备。 公司通过监管系…

聊聊安卓折叠屏给交互设计和开发带来的变化

很多年前,前端同学都觉得PC端的适配(兼容处理)难,都认为移动端的时代适配会容易得多,也无需考虑那么多的事情。事实并非如此,移动端的时代同样面临着各种适配的处理。特别是刘海机的出现,前端需…

你以为这样写代码很6,但我看不懂

来源 | 沉默王二责编| Carol封图| CSDN│下载于视觉中国为了提高 Java 编程的技艺,作者最近在 GitHub 上学习一些高手编写的代码。下面这一行代码(出自大牛之手)据说可以征服你的朋友,让他们觉得你写的代码很 6,来欣赏…

在闲鱼,我们如何用Dart做高效后端开发?

背景 像阿里其他技术团队以及业界的做法一样,闲鱼的大多数后端应用都是全部使用java来实现的。java易用、丰富的库、结构容易设计的特性决定了它是进行业务开发的最好语言之一。后端应用中数据的存储、访问、转换、输出虽然都属于后端的范畴,但是其中变…

解决 mysql>com.mysql.jdbc.PacketTooBigException: Packet for query is too large (12073681 > 4194304)

com.mysql.jdbc.PacketTooBigException: Packet for query is too large 异常解决办法: 原因: 查询出的数据包过大,默认情况下mysql 的字段容量不够装,所以抛出此异常 解决办法: 第一步:首先通过SQLyog客…

MySQL数据库无完整备份删库,除了跑路还能怎么办?

来源 | 阿丸笔记责编| Carol封图| CSDN│下载于视觉中国“删库跑路”这个词儿,经常被挂在嘴边当玩笑,是因为大家都知道,一旦真的发生这样的事情,企业损失是无比惨重的。本文作者为 CSDN 博客的一位博主, 从他的描述中得…

区块链和大数据一起能否开启数据完整性的新纪元?

作者 | Vijay Singh Khatri译者 | 天道酬勤 责编 | 徐威龙封图| CSDN 下载于视觉中国每当提到区块链一词时,许多人都会将其与比特币等加密货币联系起来。这项技术通过加快交易速度、提供隐私和透明以及其他更多功能,确实改变了虚拟货币的世界。但是&…

带出7个“师弟”,支付宝BASIC College的辅导员是个伪90后

“我的花名是改之,不是‘有则改之无则加勉’的改之,而是‘杨过,字改之’的那个改之。”一见面,他对自己花名的介绍,就让人耳目一新。至于为什么要用杨过的字给自己起名,他也毫不扭捏地坦诚相告:…

整理了Kafka的一些常用工具,建议收藏备用!| 博文精选

作者 | 犀牛饲养员责编 | 徐威龙封面付费下载于视觉中国本文主要列举一些 Kafka 的常用工具,以及举了一些例子来帮助理解。有需要的小伙伴,可以 Mark 起来再看。环境以下的操作都是基于kafka_2.11-2.2.0工具新建topicbin/kafka-topics.sh --create --zoo…

阿里的初感知

很荣幸能加入阿里这个大家庭,在这短短的一个月里,阿里的一些不同让我印象深刻。 owner精神 入职第一天,上午进行了合同签订和简单的入职培训,下午就领了电脑设备到了办公区。 在电梯里,恰巧遇到了面试过我的同学&…

两大图灵奖得主点赞中国用AI检测新冠,AI还能做什么?

作者 | CV君来源 | 我爱计算机视觉封图| CSDN│下载于视觉中国在这次新冠肺炎疫情肆虐的时候,AI 成为对抗疫情的亮点,前几天两大图灵奖得主 Yoshua Bengio 和 Yann LeCun 在对比中美两国面对疫情处理时,特别点赞了我国企业使用深度学习检测新…

首次披露!阿里线下智能方案进化史

阿里妹导读:AI 技术已经从互联网走向零售、汽车、银行等传统行业。受限于延时、成本、安全等多方面的限制,单一的云解决方案往往不能满足场景需求。线下智能方案逐步成为了智能化过程中重要的一环,今天,我们就一起来了解这一环&am…

同方服务器操作系统安装,同方云服务器安装使用手册

同方云服务器安装使用手册 内容精选换一换制作Docker镜像,有以下两种方法。快照方式制作镜像(偶尔制作的镜像):在基础镜像上,比如Ubuntu,先登录镜像系统并安装Docker软件,然后整体制作快照,即可得到所需软件…

蚂蚁金服面对亿级并发场景的组件体系设计

5 月 6 日,InfoQ 主办的 QCon 2019 全球软件开发大会在北京举行。蚂蚁金服技术专家吕丹(凝睇)在大会上做了《蚂蚁金服面对亿级并发场景的组件体系设计》的分享,我们根据演讲整理如下: 今天,我主要想和大家…

聚焦效率与目标差距,数据才是远程办公的内核!

作者|帆软数据应用研究院 新冠肺炎疫情将远程办公推向了春节后的热度高峰,引爆了远程移动办公应用市场。在“不出门,不聚集”的战疫要求下,远程办公成为企业减小损失、复工过渡的首选。 然而在众多企业如火如荼开展远程办公的同…

“大团队”和“敏捷开发”,谁说不可兼得?

阿里妹导读:当小团队的产出跟不上业务需要,团队就面临规模化的问题。从1个团队到3个团队,仍可以通过简单的团队沟通保持高效协作。当产品复杂到需要5个以上团队同时开发时,我们需要一定的组织设计来保证团队间的顺畅协作&#xff…

英雄联盟祖安服务器要维护多久,祖安玩家的春天!英雄联盟将回归队内语音,娱乐玩家遭殃了?...

英雄联盟之所以能一直保持这么高的人气,就是因为丰富的游戏内容,无论是地图资源、英雄 、符文搭配和出装选择,每隔一段时间就会来一个大革新,而今年英雄联盟更是迎来了史无前例的大更新,装备系统大改,装备界…