《k8s权威指南》读书笔记-Pod生命周期&健康检查

4.Pod的生命周期和重启策略

  • 生命周期

    • Pod 遵循一个预定义的生命周期,起始于 Pending 阶段,如果至少 其中有一个主要容器正常启动,则进入 Running,之后取决于 Pod 中是否有容器以 失败状态结束而进入 Succeeded 或者 Failed 阶段。
  • Pod状态

    • Pending(悬决)

      • Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。

      • 此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间。

    • Running(运行中)

      • Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。

      • 至少有一个容器仍在运行,或者正处于启动或重启状态。

    • Succeeded(成功)

      • Pod 中的所有容器都已成功终止,并且不会再重启。
    • Failed(失败)

      • Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。

      • 也就是说,容器以非 0 状态退出或者被系统终止。

      • 如果某节点死掉或者与集群中其他节点失联,Kubernetes 会实施一种策略,将失去的节点上运行的所有 Pod 的 phase 设置为 Failed

    • Unknown(未知)

      • 因为某些原因无法取得 Pod 的状态。

      • 这种情况通常是因为与 Pod 所在主机通信失败。

  • Pod重启策略

    • Pod的重启策略(RestartPolicy)应用于Pod内的所有容器,并且仅在Pod所处的Node上由kubelet进行判断和重启操作。

    • 当某个容器异常退出或者健康检查失败时,kubelet将根据RestartPolicy的设置来进行相应的操作。

    • Pod的重启策略包括Always、OnFailure和Never,默认值为Always。

      • Always:当容器失效时,由kubelet自动重启该容器。

      • OnFailure:当容器终止运行且退出码不为0时,由kubelet自动重启该容器。

      • Never:不论容器运行状态如何,kubelet都不会重启该容器。

    • kubelet重启失效容器的时间间隔以sync-frequency乘以2n来计算,例如1、2、4、8倍等,最长延时5min,并且在成功重启后的10min后重置该时间。

    • Pod的重启策略与<font color=red>控制方式</font>息息相关,当前可用于管理Pod的控制器包括ReplicationController、Job、DaemonSet及直接通过kubelet管理(静态Pod)。每种控制器对Pod的重启策略要求如下:

      • RC和DaemonSet:必须设置为Always,需要保证该容器持续运行。

      • Job:OnFailure或Never,确保容器执行完成后不再重启。

      • kubelet:在Pod失效时自动重启它,不论将RestartPolicy设置为什么值,也不会对Pod进行健康检查。

    • 结合Pod的状态和重启策略,列出一些常见的状态转换场景:

image.png

5.Pod健康检查和服务可用性检查

5.1 Kubernetes 对 Pod 的健康状态可以通过探针来检查

  Kubernetes 对 Pod 的健康状态可以通过探针来检查,kubelet定期执行探针来诊断容器的健康状况。

  • LivenessProbe探针:

    • 用于判断容器是否存活(Running状态)

      • 如果LivenessProbe探针探测到容器不健康,则kubelet将杀掉该容器,并根据容器的重启策略做相应的处理。

      • 如果一个容器不包含LivenessProbe探针,那么kubelet认为该容器的LivenessProbe探针返回的值永远是Success。

  • ReadinessProbe探针:

    • 用于判断容器服务是否可用(Ready状态),达到Ready状态的Pod才可以接收请求。

      • 对于被Service管理的Pod,Service与Pod Endpoint的关联关系也将基于Pod是否Ready进行设置。

      • 如果在运行过程中Ready状态变为False,则系统自动将其从Service的后端Endpoint列表中隔离出去,后续再把恢复到Ready状态的Pod加回后端Endpoint列表。

      • 这样就能保证客户端在访问Service时不会被转发到服务不可用的Pod实例上。

  • startupProbe探针:

    • 指示容器中的应用是否已经启动。

      • 如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。

      • 如果启动探测失败,kubelet 将杀死容器,而容器依其 重启策略进行重启。

      • 如果容器没有提供启动探测,则默认状态为 Success

5.2 LivenessProbe和ReadinessProbe均可配置以下三种实现方式

(1)定义存活命令

ExecAction:在容器内部执行一个命令,如果该命令的返回码为0,则表明容器健康。

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy             # kubelet 在容器内执行命令 `cat /tmp/healthy` 来进行探测
      initialDelaySeconds: 5       # `initialDelaySeconds` 字段告诉 kubelet 在执行第一次探测前应该等待 5 秒
      periodSeconds: 5             # `periodSeconds` 字段指定了 kubelet 应该每 5 秒执行一次存活探测

  在这个配置文件中,可以看到 Pod 中只有一个容器。 periodSeconds 字段指定了 kubelet 应该每 5 秒执行一次存活探测。 initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 5 秒。 kubelet 在容器内执行命令 cat /tmp/healthy 来进行探测。 如果命令执行成功并且返回值为 0,kubelet 就会认为这个容器是健康存活的。 如果这个命令返回非 0 值,kubelet 会杀死这个容器并重新启动它。

例子:

下面例子中,通过删除/tmp/healthy,展示pod通过探针检查健康状态和重启的过程。

当容器启动时,执行如下的命令:


/bin/sh -c "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"

这个容器生命的前 30 秒, /tmp/healthy 文件是存在的。 所以在这最开始的 30 秒内,执行命令 cat /tmp/healthy 会返回成功代码。 30 秒之后,执行命令 cat /tmp/healthy 就会返回失败错误码。

创建 Pod:


kubectl apply -f exec-liveness.yaml

在 30 秒内,查看 Pod 的事件:


kubectl describe pod liveness-exec

输出结果表明还没有存活探测器失败:


FirstSeen    LastSeen    Count   From            SubobjectPath           Type        Reason      Message

--------- --------    -----   ----            -------------           --------    ------      -------

24s       24s     1   {default-scheduler }                    Normal      Scheduled   Successfully assigned liveness-exec to worker0

23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulling     pulling image "k8s.gcr.io/busybox"

23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulled      Successfully pulled image "k8s.gcr.io/busybox"

23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Created     Created container with docker id 86849c15382e; Security:[seccomp=unconfined]

23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Started     Started container with docker id 86849c15382e

35 秒之后,再来看 Pod 的事件:


#kubectl describe pod liveness-exec

//在输出结果的最下面,有信息显示存活探测器失败了,这个容器被杀死并且被重建了。

FirstSeen LastSeen    Count   From            SubobjectPath           Type        Reason      Message

--------- --------    -----   ----            -------------           --------    ------      -------

37s       37s     1   {default-scheduler }                    Normal      Scheduled   Successfully assigned liveness-exec to worker0

36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulling     pulling image "k8s.gcr.io/busybox"

36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulled      Successfully pulled image "k8s.gcr.io/busybox"

36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Created     Created container with docker id 86849c15382e; Security:[seccomp=unconfined]

36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Started     Started container with docker id 86849c15382e

2s        2s      1   {kubelet worker0}   spec.containers{liveness}   Warning     Unhealthy   Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory

再等另外 30 秒,检查看这个容器被重启了:


#kubectl get pod liveness-exec

//输出结果显示 RESTARTS 的值增加了 1。

NAME            READY     STATUS    RESTARTS   AGE

liveness-exec   1/1       Running   1          1m

(2)定义TCP的存活探测

  TCPSocketAction:通过容器的IP地址和端口号执行TCP检查,如果能够建立TCP连接,则表明容器健康。

apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: k8s.gcr.io/goproxy:0.1
    ports:
    - containerPort: 8080
    readinessProbe:        # 就绪探针
      tcpSocket:   #tcp
        port: 8080
      initialDelaySeconds: 5  
      periodSeconds: 10
    livenessProbe:        #存活探针
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20

就绪探针:kubelet 会在容器启动 5 秒后发送第一个就绪探测。 这会尝试连接 goproxy 容器的 8080 端口。 如果探测成功,这个 Pod 会被标记为就绪状态,kubelet 将继续每隔 10 秒运行一次检测。

存活探针:kubelet 会在容器启动 15 秒后进行第一次存活探测。 与就绪探测类似,会尝试连接 goproxy 容器的 8080 端口。 如果存活探测失败,这个容器会被重新启动。

(3)定义一个存活态HTTP请求接口

  HTTPGetAction:通过容器的IP地址、端口号及路径调用HTTP Get方法,如果响应的状态码大于等于200且小于400,则认为容器健康。

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/liveness
    args:
    - /server
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: Custom-Header
          value: Awesome
      initialDelaySeconds: 3   #启动容器后进行首次健康检查的等待时间,单位为s。
      periodSeconds: 3         #每隔3s检查一次  
      timeoutSeconds:1         #健康检查发送请求后等待响应的超时时间,单位为s。当超时发生时,kubelet会认为容器已经无法提供服务,将会重启该容器。

  在这个配置文件中,可以看到 Pod 也只有一个容器。 periodSeconds 字段指定了 kubelet 每隔 3 秒执行一次存活探测。 initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 3 秒。 kubelet 会向容器内运行的服务(服务会监听 8080 端口)发送一个 HTTP GET 请求来执行探测。 如果服务器上 /healthz 路径下的处理程序返回成功代码,则 kubelet 认为容器是健康存活的。 如果处理程序返回失败代码,则 kubelet 会杀死这个容器并且重新启动它。

  任何大于或等于 200 并且小于 400 的返回代码标示成功,其它返回代码都标示失败。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容