1.存活探针

  使用Kubernetes的一个主要好处是,可以给Kubernetes—个容器列表来由其保持容器在集群中的运行。可以通过让Kubernetes创建pod资源,为其选择一个工作节点并在该节点上运行该pod的容器来完成此操作。但是,如果其中一个容器终止,或一个pod的所有容器都终止,怎么办?

  只要将pod调度到某个节点,该节点上的Kubelet就会运行pod的容器,从此只要该pod存在,就会保持运行。如果容器的主进程崩溃,Kubelet将重启容器。如果应用程序中有一个导致它每隔一段时间就会崩溃的bug, Kubernetes会自动重启应用程序,所以即使应用程序本身没有做任何特殊的事,在Kubernetes中运行也能自动获得自我修复的能力。

  即使进程没有崩溃,有时应用程序也会停止正常工作。例如,具有内存泄漏的 Java应用程序将开始抛出OutOfMemoryErrors,但JVM进程会一直运行。如果有一种方法,能让应用程序向Kubernetes发出信号,告诉Kubernetes它运行异常并让 Kubernetes重新启动,那就很棒了。

  我们已经说过,一个崩溃的容器会自动重启,所以也许你会想到,可以在应用中捕获这类错误,并在错误发生时退出该进程。当然可以这样做,但这仍然不能解决所有的问题。

  例如,你的应用因为无限循环或死锁而停止响应。为确保应用程序在这种情况下可以重新启动,必须从外部检查应用程序的运行状况,而不是依赖于应用的内部检测。

1.1 介绍存活探针

  Kubernetes可以通过存活探针(liveness probe)检查容器是否还在运行。可以为pod中的每个容器单独指定存活探针。如果探测失败,Kubernetes将定期执行探针并重新启动容器。

  Kubernetes有以下三种探测容器的机制:

  HTTPGET探针对容器的IP地址(你指定的端口和路径)执行HTTPGET请求。

    • 如果探测器收到响应,并且响应状态码不代表错误(换句话说,如果HTTP响应状态码是2xx或3xx),则认为探测成功。如果服务器返回错误响应状态码或者根本没有响应,那么探测就被认为是失败的,容器将被重新启动。
    • TCP套接字探针尝试与容器指定端口建立TCP连接。如果连接成功建立,则探测成功。否则,容器重新启动。
    • Exec探针在容器内执行任意命令,并检查命令的退出状态码。如果状态码是0,则探测成功。所有其他状态码都被认为失败。

1.2 创建基于HTTP的存活探针

  来看看如何为一个Node.js应用添加一个存活探针。因为它是一个Web应用程序,所以添加一个存活探针来检查其Web服务器是否提供请求是有意义的。但是因为这个Node.js应用程序太简单了,所以不得不人为地让它失败。

  要正确演示存活探针,需要稍微修改应用程序。在第五个请求之后,给每个请求返回HTTP状态码500 (Internal Server Error)--你的应用程序将正确处理前

  五个客户端请求,之后每个请求都会返回错误。多亏了存活探针,应用在这个时候会重启,使其能够再次正确处理客户端请求。

  你将创建一个包含HTTPGET存活探针的新pod,下面的代码显示了pod的yaml。

#代码4.1 将存活探针添加到pod
apiVersion: v1
kind: Pod
metadata:
name: kubia-liveness
spec:
containers:
- image: luksa/kubia-unhealthy #这个镜像包含了坏掉的应用
name: kubia
livenessProbe: #一个HTTP GET存活探针
httpGet:
path: / #请求
port: 8080 #探针连接的网络端口

  该pod的描述文件定义了一个httpGet存活探针,该探针告诉Kubernetes定期在端口 8080路径上执行HTTP GET请求,以确定该容器是否健康。这些请求在容器运行后立即开始。

  经过五次这样的请求(或实际的客户端请求)后,你的应用程序开始返回HTTP状态码500, Kubernetes会认为探测失败并重启容器。

1.3 使用存活探针

  要查看存活探针是如何工作的,请尝试立即创建该pod。大约一分半钟后,容器将重启。可以通过运行kubectl get看到:

$ kubectl get po kubia-liveness
NAME READY STATUS RESTARTS AGE
kubia-liveness 1/1 Running 1 2m

  RESTARTS列显示pod的容器已被重启一次(如果你再等一分半钟,它会再次重启,然后无限循环下去)。

  可以通过查看kubectl describe的内容来了解为什么必须重启容器,如下面的代码清单所示

$ kubectl describe po kubia-liveness
Name: kubia-liveness
......
Containers:
kubia:
Container ID: docker://480986f8
Image: luksa/kubia-unhealthy
Image ID: docker://sha256:2b208508
Port:
State: Running
Started: Sun, 14 May 2017 11:41:40 +0200 #容器正在运行
Last State: Terminated #先前的容器由于发生错误被终止,返回码是147
Reason: Error
Exit code: 137
Started: Mon, 01 Jan 0001 00:00:00 +0000
Finished: Sun, 14 M a y 2017 11:41:38 +0200
Ready: True
Restart Count: 1 #该容器已被重启一次
Liveness: http-get http://:8080/ delay=0s timeout=1s
period=l0s #success=1 #failure=3

  可以看到容器现在正在运行,但之前由于错误而终止。退出代码为137,这有特殊的含义——表示该进程由外部信号终止。数字137是两个数字的总和:128 + x,其中x是终止进程的信号编号。在这个例子中,x等于9,这是SIGKILL的信号编号,意味着这个进程被强行终止。

  在底部列出的事件显示了容器为什么终止一一Kubernetes发现容器不健康,所以终止并重新创建。

  注意:当容器被强行终止时,会创建一个全新的容器——而不是重启原来的容器。

1.4 配置存活探针的附加属性

  你可能己经注意到,kubectl describe还显示关于存活探针的附加信息:

Liveness http-get http://:8080/ delay=Os timeout=1s period=lOs #success=1  #failure=3

  除了明确指定的存活探针选项,还可以看到其他属性,例如delay (延迟)、timeout (超时)、period (周期)等。delay=0s部分显示在容器启动后立即开始探测。timeout仅设置为1秒,因此容器必须在1秒内进行响应,不然这次探测记作失败。每10秒探测一次容器(period=lOs),并在探测连续三次失败 (#failure=3)后重启容器。

  定义探针时可以自定义这些附加参数。例如,要设置初始延迟,请将 initialDelaySeconds属性添加到存活探针的配置中,如下面的代码清单所示。

#代码4.3 具有初始延迟的存活探针:kubia-liveness-probe-initial-delay.yaml
apiVersion: v1
kind: Pod
metadata:
name: kubia-liveness
spec:
containers:
- image: luksa/kubia-unhealthy
name: kubia
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 15 #kubernetes会在第一次探测前等待15秒,为了让有些启动长时间的程序有个缓冲
timeoutSeconds: 10 #超过10s或者返回码不在200~300内,就绪检查就失败
periodSeconds: 5 #每5秒检查一次

2.就绪探针

  如果pod没有准备好,如何处理服务请求呢?

  有些pod可能需要时间来加载配置或数据,或者可能需要执行预热过程以防止第一个用户请求时间太长影响了用户体验。在这种情况下,不希望该pod立即开始接收请求,尤其是在运行的实例可以正确快速地处理请求的情况下。不要将请求转发到正在启动的pod中,直到完全准备就绪。

2.1 介绍就绪探针

  了解了存活探针,以及它们如何通过确保异常容器自动重启来保持应用程序的正常运行。与存活探针类似,Kubernetes还允许为容器定义准备就绪探针。

  就绪探测器会定期调用,并确定特定的pod是否接收客户端请求。当容器的准备就绪探测返回成功时,表示容器已准备好接收请求。

  这个准备就绪的概念显然是每个容器特有的东西。Kubernetes只能检查在容器中运行的应用程序是否响应一个简单的GET/请求,或者它可以响应特定的URL路径(该URL导致应用程序执行一系列检查以确定它是否准备就绪)。考虑到应用程序的具体情况,这种确切的准备就绪的判定是应用程序开发人员的责任。

  就绪探针的类型

  像存活探针一样,就绪探针有三种类型:

    • Exec探针,执行进程的地方。容器的状态由进程的退出状态代码确定。
    • HTTP GET探针,向容器发送HTTP GET请求,通过响应HTTP状态代码,判断容器是否准备好。
    • TCP socket探针,它打开一个TCP连接到容器的指定端口。如果连接己建立,则认为容器己准备就绪。

  了解就绪探针的操作

  启动容器时,可以为Kubernetes配置一个等待时间,经过等待时间后才可以执行第一次准备就绪检查。之后,它会周期性地调用探针,并根据就绪探针的结果采取行动。如果某个pod报告它尚未准备就绪,则会从该服务中删除该pod。如果pod再次准备就绪,则重新添加pod。

  与存活探针不同,如果容器未通过准备检查,则不会被终止或重新启动。这是存活探针与就绪探针之间的重要区别。存活探针通过杀死异常的容器并用新的正常 容器替代它们来保持pod正常工作,而就绪探针确保只有准备好处理请求的pod才可以接收它们(请求)。这在容器启动时最为必要,当然在容器运行一段时间后也是有用的。

  如图5.11所示,如果一个容器的就绪探测失败,则将该容器从端点对象中移除。 连接到该服务的客户端不会被重定向到pod。这和pod与服务的标签选择器完全不匹配的效果相同。

  了解就绪探针的重要性

  设想一组pod(例如,运行应用程序服务器的pod)取决于另一个pod(例如,后端数据库)提供的服务。如果任何一个前端连接点出现连接问题并且无法再访问数据库,那么就绪探针可能会告知Kubernetes该pod没有准备好处理任何请求。如果其他pod实例没有遇到类似的连接问题,则它们可以正常处理请求。就绪探针确保客户端只与正常的pod交互,并且永远不会知道系统存在问题。

2.2 向pod 添加就绪探针

  接下来,将通过修改Replication Controller(deployment也一样)的pod模板来为现有的pod添加就绪探针。

  向pod template添加就绪探针

  可以通过kubectl edit命令来向己存在的ReplicationController中的pod模板添加探针。

$ kubectl edit rc kubia

  当在文本编辑器中打开ReplicationControlier的YAML时,在pod模板中查找容器规格,并将以下就绪探针定义添加到spec.template.spec.containers下的第一个容器。YAML看起来应该就像下面的代码清单。

#代码5.17 RC创建带有就绪探针的pod:kubia-rc-readinessprobe.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: kubia
spec:
replicas: 3
selector:
app: kubia
template:
metadata:
labels:
app: kubia
spec:
containers:
- name: kubia
image: luksa/kubia
ports:
- name: http
containerPort: 8080
readinessProbe: #pod中每个容器都会有一个就绪探针
exec: #使用exec的方式
command:
- ls
- /var/ready

  就绪探针将定期在容器内执行ls/var/ready命令。如果文件存在,则ls命令返回退出码0,否则返回非零的退出码。如果文件存在,则就绪探针将成功;否则,它会失败。

  定义这样一个奇怪的就绪探针的原因是,可以通过创建或删除有问题的文件来触发结果。该文件尚不存在,所以所有的pod现在应该报告没有准备好,是这样的吗?其实并不完全是,正如在前面章节中了解的那样,更改ReplicationController的pod模板对现有的pod没有影响。

  换句话说,现有的所有pod仍没有定义准备就绪探针。可以通过使用kubectl get pods列出pod并查看READY列。需要删除pod并让它们通过ReplicationController重新创建。新的pod将进行就绪检查会一直失败,并且不会将其作为服务的端点,直到在每个pod中创建/var/ready文件。

  观察并修改pod 就绪状态

  再次列出pod并检查它们是否准备好:

$ kubectl get po
NAME READY STATUS RESTARTS AGE
kubia-2rlqb 0/1 Running 0 lm
kubia-3raxl 0/1 Running 0 lm
kubia-3yw4s 0/1 Running 0 lm

  READY列显示出没有一个容器准备好。现在通过创建/var/ready文件使其中一个文件的就绪探针返回成功,该文件的存在可以模拟就绪探针成功:

  使用kubectl exec命令在kubia-2rlqb的pod容器内执行touch命令。 如果文件尚不存在,touch命令会创建该文件。就绪探针命令现在应该返回退出码0, 这意味着探测成功,并且现在应该显示pod己准备就绪。现在去查看其状态:

$ kubectl get po kubia-2rlqb
NAME READY STATUS RESTARTS AGE
kubia-2rlqb 0/1 Running 0 2

  该pod还没有准备好。有什么不对或者这是预期的结果吗?用kubectl describe来获得更详细的关于pod的信息。输出应该包含以下内容:

Readiness: exec [ls /var/ready] delay=0s timeout=1s period=10s #success=1  #failure=3

  准备就绪探针会定期检查--默认情况下每10秒检查一次。由于尚未调用就绪探针,因此容器未准备好。但是最晚10秒钟内,该pod应该己经准备就绪,其IP应该列为service的endpoint(运行kubectl get endpoint kubia-loadbalancer来确认)。

  服务打向单独pod

  现在可以点击几次服务网址,查看每个请求都被重定向到这个pod:

$ curl http://130.211.53.173
You've hit kubia-2rlqb
$ curl http://130.211.53.173
You've hit kubia-2rlqb
$ curl http://130.211.53.173
You've hit kubia-2rlqb

  即使有三个pod正在运行,但只有一个pod报告己准备好,因此是唯一的pod接收请求。如果现在删除该文件,则将再次从该服务中删除该容器。

2.3 了解就绪探针的实际作用

  此模拟就绪探针仅用于演示就绪探针的功能。在实际应用中,应用程序是否可以(并且希望)接收客户端请求,决定了就绪探测应该返回成功或失败。

  应该通过删除pod或更改pod标签而不是手动更改探针来从服务中手动移除pod。

  提示:如果想要从某个服务中手动添加或删除pod,请将enabled=true作为标签添加到pod,以及服务的标签选择器中。当想要从服务中移除pod时,删除标签。

  务必定义就绪探针,就绪探针当然在容器运行一段时间后也是有用的。可以检测失败的容器并移除。

3.总结

  1.使用存活探针,让Kubernetes在容器不再健康的情况下立即重启它(应用程序定义了健康的条件)。

  2.如果定义了就绪探针,请确保它返回成功;否则该pod不会成为服务的一部分。

kubernetes的存活探针和就绪探针的更多相关文章

  1. Kubernetes 存活、就绪探针

    在设计关键任务.高可用应用程序时,弹性是要考虑的最重要因素之一. 当应用程序可以快速从故障中恢复时,它便具有弹性. 云原生应用程序通常设计为使用微服务架构,其中每个组件都位于容器中.为了确保Kuber ...

  2. 【七】Kubernetes 探针介绍 - 存活、就绪探针案例测试

    一.探针概述 探针是有 kubelet 对容器执行的定期诊断,并不是由 Master 节点发起的探测,而是由每一个 Node 所在的 kubelet 进行探测,这样可以减轻 Master 节点系统负载 ...

  3. kubernets之就绪探针

    一 介绍就绪探针 1.1  开始介绍就绪探针之前,让我们来提问几个问题?第一,在sevice这章我们了解到, 当流量从Ingress被转发到服务,然后服务从其维护当Endponits 里面列表查找到任 ...

  4. 掌握SpringBoot-2.3的容器探针:深入篇

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:原创分类汇总及配套源码,涉及Java.Docker.K8S.DevOPS等 关于<Spr ...

  5. Kubernetes学习笔记(四):服务

    服务介绍 服务是一种为一组相同功能的pod提供单一不变接入点的资源.当服务存在时,他的IP和端口不会改变.客户端通过IP和端口建立连接,这些连接会被路由到任何一个pod上.如此,客户端不需要知道每个单 ...

  6. 《kubernetes + .net core 》dev ops部分

    目录 1.kubernetes 预备知识 1.1 集群资源 1.1.1 role 1.1.2 namespace 1.1.3 node 1.1.4 persistent volume 1.1.5 st ...

  7. Kubernetes在生产环境中的一些讨论

    pod是所有一切资源的中心,毫无疑问是Kubernetes中最重要的资源.毕竟, 每个应用都运行在pod中.为了确保知道如何开发能充分利用应用所在环境资源的应用,最后再从应用的角度来仔细看一下pod. ...

  8. Kubernetes生产环境最佳实践

    点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 众所周知,Kubernetes很难! 以下是在生产中使用 ...

  9. [转帖]Kubernetes及容器编排的总体介绍【译】

    Kubernetes及容器编排的总体介绍[译] 翻译自The New Stack<Kubernetes 生态环境>作者:JANAKIRAM MSV和 KRISHNAN SUBRAMANIA ...

随机推荐

  1. Pytorch多卡训练

    前一篇博客利用Pytorch手动实现了LeNet-5,因为在训练的时候,机器上的两张卡只用到了一张,所以就想怎么同时利用起两张显卡来训练我们的网络,当然LeNet这种层数比较低而且用到的数据集比较少的 ...

  2. [Linux] Shell 脚本实例(超实用)

    文件操作 为文件(test.sh)增加执行权限 chmod +x test.sh 列出当前文件夹下所有文件(每行输出一个) 1 #!/bin/bash 2 dir=`ls ./` 3 for i in ...

  3. mysql基础之mariadb的安装,连接,用户,密码,权限设置语句详解

    一.mariadb安装 1.配置mariadb源: [root@ren7 ~]# vim /etc/yum.repos.d/mariadb.repo [mariadb] name = MariaDB ...

  4. 5.6 date:显示与设置系统时间

    date命令 用于显示当前的系统时间或设置系统时间. date [选项] +[日期格式]   date命令的参数选项及说明 OPTION参数选项-d 时间字符串 显示指定字符串所描述的时间,而非当前时 ...

  5. struct位域

    1 总结下 结构体位域的使用 比如  则 struct _COM2 { u8 Len : 1;//低位 u8 EoN : 2; u8 Stop:1; u8 Bps:4;//高位 } union COM ...

  6. mysql数据库-备份方式简介与规范

    目录 1 应对场景: 2. 备份方式分类 2.1 按备份数据类型划分 2.2 按侵入程度划分 2.3 按备份方式划分 3 备份注意要点 4 还原要点 4.1 定期还原测试,验证备份可用性 4.2 还原 ...

  7. 使用原生JS,实现鼠标点击爱心效果 !!!

    使用原生JS,实现鼠标点击爱心效果 !!! 引言: 在很多时候我们都需要实现鼠标点击出现图案或者文字这样的效果,对于用户而言,这样的体验是很极致的.其实实现起来也很简单,下面一起来学习一下吧.文末附上 ...

  8. 西门子 S7-300 以太网模块连接 WINCC方案

    北京华科远创科技有限研发的远创智控ETH-YC模块,型号有MPI-ETH-YC01和PPI-ETH-YC01,适用于西门子S7-200/S7-300/S7-400.SMART S7-200.西门子数控 ...

  9. vue相关面试知识点总结

    vue v-for循环中为什么要用key?为什么index不能作为key? key 的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes.如 ...

  10. 聊聊java工程师换工作那些事

    最近有个读者在苦恼一件事,那就是有大公司在挖他,他要不要从所在的小公司,跳槽到大公司,前提是两家公司的待遇基本一致.由这个问题结合自己多年的工作经验,来谈谈java工程师要不要跳槽,何时跳槽,怎么跳槽 ...