• Kubernetes Pod 健康检查


    参考文档: https://jimmysong.io/kubernetes-handbook/guide/configure-liveness-readiness-probes.html

    一、Pod的liveness和readiness探针

      当你使用kuberentes的时候,有没有遇到过Pod在启动后一会就挂掉然后又重新启动这样的恶性循环?你有没有想过kubernetes是如何检测pod是否还存活?虽然容器已经启动,但是kubernetes如何知道容器的进程是否准备好对外提供服务了呢?

      Kubelet使用liveness probe(存活探针)来确定何时重启容器。例如,当应用程序处于运行状态但无法做进一步操作,liveness探针将捕获到deadlock,重启处于该状态下的容器,使应用程序在存在bug的情况下依然能够继续运行下去

      Kubelet使用readiness probe(就绪探针)来确定容器是否已经就绪可以接受流量。只有当Pod中的容器都处于就绪状态时kubelet才会认定该Pod处于就绪状态。该信号的作用是控制哪些Pod应该作为service的后端。如果Pod处于非就绪状态,那么它们将会被从service的load balancer中移除。

      Probe支持以下三种检查方法:

    • httpGet:发送HTTP请求,返回200-400范围内状态码为成功
    • exec:执行shell命令,返回状态码0为成功
    • tcpSocket:发起TCP Socket建立则成功

    二、定义liveness命令(exec)

      许多长时间运行的应用程序最终会转换到broken状态,除非重新启动,否则无法恢复。Kubernetes提供了liveness probe来检测和补救这种情况。 

    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: liveness
      name: liveness-exec
    spec:
      containers:
      - name: liveness
        args:
        - /bin/sh
        - -c
        - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
        image: busybox
        livenessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 5
          periodSeconds: 5 

      该配置文件给Pod配置了一个容器。periodSeconds 规定kubelet要每隔5秒执行一次liveness probe。initialDelaySeconds 告诉kubelet在第一次执行probe之前要的等待5秒钟。探针检测命令是在容器中执行 cat /tmp/healthy 命令。如果命令执行成功,将返回0,kubelet就会认为该容器是活着的并且很健康。如果返回非0值,kubelet就会杀掉这个容器并重启它。

      容器启动时,执行该命令:  

    /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 create -f exec-lineness.yaml
    

      在30秒内,查看Pod的event:   

    kubectl describe pod liveness-exec
    
    # 显示正常
      Normal   Pulled                 34s (x3 over 3m)  kubelet, node-01   Successfully pulled image "busybox"
      Normal   Created                34s (x3 over 3m)  kubelet, node-01   Created container
      Normal   Started                33s (x3 over 3m)  kubelet, node-01   Started container
    

      启动35秒后,再次查看pod的event:    

    kubectl describe pod liveness-exec
    
    # 显示查询不到/tmp/healthy
     Normal   Scheduled              1m                 default-scheduler   Successfully assigned liveness-exec to master-01
      Normal   SuccessfulMountVolume  1m                 kubelet, master-01  MountVolume.SetUp succeeded for volume "default-token-v5vw9"
      Normal   Pulled                 1m                 kubelet, master-01  Successfully pulled image "busybox"
      Normal   Created                1m                 kubelet, master-01  Created container
      Normal   Started                1m                 kubelet, master-01  Started container
      Warning  Unhealthy              40s (x3 over 50s)  kubelet, master-01  Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
      Normal   Pulling                10s (x2 over 1m)   kubelet, master-01  pulling image "busybox"
      Normal   Killing                10s                kubelet, master-01  Killing container with id docker://liveness:Container failed liveness probe.. Container will be killed and recreated  

      然后就会将这个Pod删掉重建  

    [root@master-01 healthy]# kubectl get pod
    NAME                                READY     STATUS    RESTARTS   AGE
    liveness-exec                       1/1       Running   1          2m
    
    # RESTARTS 已经为1了
    

      

    三、定义一个liveness HTTP请求

      我们还可以使用HTTP GET请求作为liveness probe。 

    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: liveness
      name: liveness-http
    spec:
      containers:
      - name: liveness
        args:
        - /server
        image: tomtsang/dockerlibraryk8s-liveness
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
            httpHeaders:
              - name: X-Custom-Header
                value: Awesome
          initialDelaySeconds: 3
          periodSeconds: 3
    

      该配置文件只定义了一个容器,livenessProbe 指定kubelete需要每隔3秒执行一次liveness probe。initialDelaySeconds 指定kubelet在该执行第一次探测之前需要等待3秒钟。该探针将向容器中的server的8080端口发送一个HTTP GET请求。如果server的/healthz路径的handler返回一个成功的返回码,kubelet就会认定该容器是活着的并且很健康。如果返回失败的返回码,kubelet将杀掉该容器并重启它。

      任何大于200小于400的返回码都会认定是成功的返回码。其他返回码都会被认为是失败的返回码。

      查看该server的源码:server.go.

      最开始的10秒该容器是活着的, /healthz handler返回200的状态码。这之后将返回500的返回码。  

    http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
        duration := time.Now().Sub(started)
        if duration.Seconds() > 10 {
            w.WriteHeader(500)
            w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
        } else {
            w.WriteHeader(200)
            w.Write([]byte("ok"))
        }
    })
    

      容器启动3秒后,kubelet开始执行健康检查。第一次健康监测会成功,但是10秒后,健康检查将失败,kubelet将杀掉和重启容器。

      创建Pod:  

    kubectl create -f http-liveness.yaml
    

      10秒后,查看Pod的event,确认liveness probe失败并重启了容器。 

      Normal   Scheduled              24s               default-scheduler   Successfully assigned liveness-http to master-01
      Normal   SuccessfulMountVolume  24s               kubelet, master-01  MountVolume.SetUp succeeded for volume "default-token-v5vw9"
      Normal   Pulled                 19s               kubelet, master-01  Successfully pulled image "tomtsang/dockerlibraryk8s-liveness"
      Normal   Created                19s               kubelet, master-01  Created container
      Normal   Started                19s               kubelet, master-01  Started container
      Warning  Unhealthy              2s (x3 over 8s)   kubelet, master-01  Liveness probe failed: HTTP probe failed with statuscode: 500
      Normal   Pulling                1s (x2 over 23s)  kubelet, master-01  pulling image "tomtsang/dockerlibraryk8s-liveness"
      Normal   Killing                1s                kubelet, master-01  Killing container with id docker://liveness:Container failed liveness probe..
    

      

    四、定义TCP liveness探针

      第三种liveness probe使用TCP Socket。 使用此配置,kubelet将尝试在指定端口上打开容器的套接字。 如果可以建立连接,容器被认为是健康的,如果不能就认为是失败的。 

    apiVersion: v1
    kind: Pod
    metadata:
      name: goproxy
      labels:
        app: goproxy
    spec:
      containers:
      - name: goproxy
        image: gcr.io/google_containers/goproxy:0.1
        ports:
        - containerPort: 8080
        readinessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
        livenessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 15
          periodSeconds: 20
    

      如您所见,TCP检查的配置与HTTP检查非常相似。 此示例同时使用了readiness和liveness probe。 容器启动后5秒钟,kubelet将发送第一个readiness probe。 这将尝试连接到端口8080上的goproxy容器。如果探测成功,则该pod将被标记为就绪。Kubelet将每隔10秒钟执行一次该检查。

      除了readiness probe之外,该配置还包括liveness probe。 容器启动15秒后,kubelet将运行第一个liveness probe。 就像readiness probe一样,这将尝试连接到goproxy容器上的8080端口。如果liveness probe失败,容器将重新启动。

    五、使用命名端口

      可以使用命名的ContainerPort作为HTTP或TCP liveness检查:  

    ports:
    - name: liveness-port
      containerPort: 8080
      hostPort: 8080
    
    livenessProbe:
      httpGet:
      path: /healthz
      port: liveness-port
    

      

    六、定义readiness探针

      有时,应用程序暂时无法对外部流量提供服务。 例如,应用程序可能需要在启动期间加载大量数据或配置文件。 在这种情况下,你不想杀死应用程序,但你也不想发送请求。 Kubernetes提供了readiness probe来检测和减轻这些情况。 Pod中的容器可以报告自己还没有准备,不能处理Kubernetes服务发送过来的流量。

      Readiness probe的配置跟liveness probe很像。唯一的不同是使用 readinessProbe而不是livenessProbe。 

    readinessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5
    

      Readiness probe的HTTP和TCP的探测器配置跟liveness probe一样。

      Readiness和livenss probe可以并行用于同一容器。 使用两者可以确保流量无法到达未准备好的容器,并且容器在失败时重新启动。

      

    七、配置Probe  

    Probe中有很多精确和详细的配置,通过它们你能准确的控制liveness和readiness检查:

    • initialDelaySeconds:容器启动后第一次执行探测是需要等待多少秒。
    • periodSeconds:执行探测的频率。默认是10秒,最小1秒。
    • timeoutSeconds:探测超时时间。默认1秒,最小1秒。
    • successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功。默认是1。对于liveness必须是1。最小值是1。
    • failureThreshold:探测成功后,最少连续探测失败多少次才被认定为失败。默认是3。最小值是1。

    HTTP probe中可以给 httpGet设置其他配置项:

    • host:连接的主机名,默认连接到pod的IP。你可能想在http header中设置"Host"而不是使用IP。
    • scheme:连接使用的schema,默认HTTP。
    • path: 访问的HTTP server的path。
    • httpHeaders:自定义请求的header。HTTP运行重复的header。
    • port:访问的容器的端口名字或者端口号。端口号必须介于1和65525之间。

    对于HTTP探测器,kubelet向指定的路径和端口发送HTTP请求以执行检查。 Kubelet将probe发送到容器的IP地址,除非地址被httpGet中的可选host字段覆盖。 在大多数情况下,你不想设置主机字段。 有一种情况下你可以设置它。 假设容器在127.0.0.1上侦听,并且Pod的hostNetwork字段为true。 然后,在httpGet下的host应该设置为127.0.0.1。 如果你的pod依赖于虚拟主机,这可能是更常见的情况,你不应该是用host,而是应该在httpHeaders中设置Host头。

  • 相关阅读:
    Call指令和Ret指令讲解06 零基础入门学习汇编语言53
    【CSDN2012年度博客之星】喜欢本博客的读者,投票赠送《visual C++2010开发权威指南》电子稿感谢支持 ~(截至到2012年12月30日)
    本人新书< Visual C#2010开发权威指南>出版感谢大家一如既往的支持感谢CSDN总裁蒋涛以及他率领的CSDN团队提供的支持!
    在Windows Azure虚拟机上的SQL Server新教程
    Windows Azure Active Directory处理2000 亿个身份验证连接全球的人、 数据和设备
    宣布降低Windows Azure Storage的定价
    本人新书< Windows CE 7开发实战详解>出版感谢大家一如既往的支持感谢CSDN总裁蒋涛以及他率领的CSDN团队提供的支持!
    基于VC++2012图形化解决皇后问题
    3个 Windows Azure SQL Reporting开发的最佳做法
    现实世界的 Windows Azure: IT 公司提高其旗舰产品,为更多客户提供云解决方案
  • 原文地址:https://www.cnblogs.com/bigberg/p/9223402.html
Copyright © 2020-2023  润新知