云原生Kubernetes(k8s)之容器的探测

Posted Lion Long

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了云原生Kubernetes(k8s)之容器的探测相关的知识,希望对你有一定的参考价值。

Kubernetes(k8s)之容器的探测

一、探测类型及使用场景

1.1、startupProbe(启动探测)

指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被禁用,直到此探针成功为止。探测成功之后,启动探测停止。如果启动探测失败,kubelet 将杀死容器,而容器依其 重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success。

使用场景:
容器需要较长时间才能启动就绪的 Pod ,可以指定启动探针。那么可以避免设置一个超长时间间隔的存活探测。例如:容器需要在启动期间加载大型数据、配置文件或执行迁移等

1.2、readinessProbe(就绪探测)

指示容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 Failure。 如果容器不提供就绪态探针,则默认状态为 Success。就绪探测失败时,不会杀死容器进程,只会将端点从service中移除,使其收不到流量。

使用场景:

  1. 仅在探测成功时才开始向 Pod 发送请求流量,意味着pod只在探测成功之后才开始接受请求数据。
  2. 如果应用程序对后端服务有严格的依赖性,可以同时实现存活态和就绪态探针,存活态探针检测通过后,可以通过就绪态探针会额外检查每个所需的后端服务是否可用

1.3、livenessProbe(存活探测)

指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为 Success。

使用场景:

  1. 如果希望容器在探测失败时被杀死并重新启动,并指定 restartPolicy 为 “Always” 或"OnFailure"。
  2. 如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,可以不需要指定存活探针。kubelet 将根据 Pod 的 restartPolicy 自动执行修复操作。

二、检查机制

(1)exec。在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
(2)httpGet。对容器的 IP 地址上指定端口和路径执行 HTTP GET 请求。如果响应的状态码大于等于 200 且小于400,则诊断被认为是成功的。
(3)tcpSocket。对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。
(4)grpc。使用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC健康检查。 如果响应的状态是 “SERVING”,则认为诊断成功。 gRPC 探针是一个 alpha 特性,只有在你启用了 “GRPCContainerProbe” 特性时才能使用。

三、探测结果

(1)Success(成功),容器通过了诊断。
(2)Failure(失败),容器未通过诊断。
(3)Unknown(未知),诊断失败,因此不会采取任何行动。

四、容器探测案例

apiVersion: v1
kind: Pod
metadata:
  name: myhello-pod
  namespace: default
  labels:
    name: myhello-pod
    env: dev
spec:
  restartPolicy: Always
  initContainers:
  - name: init-myservice
    image: busybox
    # 查找命名空间下myservice服务,如果存在则执行成功,如果不存在则一直查找
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox
    # 查找命名空间下mydb服务,如果存在则执行成功,如果不存在则一直查找
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
  containers:
  - name: myhello
    image: nongtengfei/hello:curl
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    command: ["./app"]
    args: ["--param1=k8s-p1", "--param2=k8s-p2"]
    resources:
      limits:
        cpu: 200m
        memory: 500Mi
      requests:
        cpu: 100m
        memory: 200Mi
    env: # 注入到容器的环境变量
    - name: env1
      value: "k8s-env1"
    - name: env2
      value: "k8s-env2"
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c","echo post start command exec >> /tmp/data"]
      preStop:
        exec:
          command: ["/bin/sh", "-c","echo pre stop command exec >> /tmp/data"]
    startupProbe:
      exec:
        command: ["/bin/sh", "-c","statuscode=`curl -o /dev/null -s -w % http_code http://localhost/healthz`; [ $$statuscode -le 400 ] || exit 1"]
      # 指定初始化时间,即探针在容器启动之后的延迟时长
      initialDelaySeconds: 5
      # 探测周期,即每隔多长时间探测一次
      periodSeconds: 5
      # 最小连续失败次数,即连续失败多少次表示探测失败
      failureThreshold: 3
      # 最小连续成功次数,即连续探测成功多少次表示探测成功,liveness 和 startup 必须为1
      successThreshold: 1
      # 探测超时时间
      timeoutSeconds: 1
    readinessProbe:
      httpGet:
        path: /health
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 3
      successThreshold: 1
      timeoutSeconds: 1
    livenessProbe:
      httpGet:
        path: /health
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 3
      successThreshold: 1
      timeoutSeconds: 1
  - name: myredis #容器的名称
    image: redis #容器对应的 Docker Image
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
    resources:
      limits:
        cpu: 200m
        memory: 500Mi
      requests:
        cpu: 100m
        memory: 200Mi
    livenessProbe:
      tcpSocket:
        port: 6379
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 3
      successThreshold: 1
      timeoutSeconds: 1

云原生之K8S中Pod健康检测、服务可用性检查详解

参考技术A

中秋明月,豪门有,贫家也有。极慰人心。 ——烽火戏诸侯《剑来》

探测的目的 : 用来维持 pod的健壮性,当pod挂掉之后,deployment会生成新的pod,但如果pod是正常运行的,但pod里面出了问题,此时deployment是监测不到的。故此需要探测(probe)-pod是不是正常提供服务的

Kubernetes 对 Pod 的 健康 状态可以通过两类探针来检查: LivenessProbe 和 ReadinessProbe , kubelet定期执行这两类探针来诊断容器的 健康 状况。都是通过deployment实现的

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

对于每种探测方式,需要设置 initialDelaySeconds 和 timeoutSeconds 等参数,它们的含义分别如下。

Kubernetes的ReadinessProbe机制可能无法满足某些复杂应用对容器内服务可用状态的判断

Pod的Readiness Gates在Pod定义中的ReadinessGate字段进行设置。下面的例子设置了一个类型为www.example.com/feature-1的新ReadinessGate:

用于判断容器是否存活(Running状态) ,如果LivenessProbe探针探测到容器不 健康 ,则kubelet将杀掉该容器,并根据容器的重启策略做相应的处理

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

资源文件定义

运行这个deploy。当pod创建成功后,新建文件,并睡眠30s,删掉文件在睡眠。使用liveness检测文件的存在

运行超过30s后。文件被删除,所以被 健康 检测命中,pod根据重启策略重启

99s后已经从起了第二次

查看节点机docker中的容器ID,前后不一样,确定是POD被杀掉后重启。

通过容器的IP地址、端口号及路径调用HTTP Get方法,如果响应的状态码大于等于200且小于400,则认为容器 健康 。
创建资源文件,即相关参数使用

运行deploy,这个的探测机制访问Ngixn的默认欢迎页

当欢迎页被删除时,访问报错,被检测命中,pod重启

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

访问8080端口,但是8080端口未开放,所以访问会超时,不能建立连接,命中检测,重启Pod

用于判断容器服务是否可用(Ready状态) ,达到Ready状态的Pod才可以接收请求。负责不能进行访问

资源文件定义,使用钩子建好需要检查的文件

创建3个有Ngixn的pod,通过POD创建一个SVC做测试用

修改主页文字

修改标签

要删除文件检测

使用POD创建SVC

测试SVC正常,三个POD会正常 负载

删除文件测试

会发现pod-liveness的pod已经不提供服务了

kube-apiserver.yaml中的使用,两种探针同时使用

以上是关于云原生Kubernetes(k8s)之容器的探测的主要内容,如果未能解决你的问题,请参考以下文章

云原生之K8S中Pod健康检测、服务可用性检查详解

云原生之kubernetes实战部署Octant开源可视化k8s管理平台

华为云大咖带你玩转云原生基础设施之K8s

华为云大咖带你玩转云原生基础设施之K8s

云原生之kuberneteskubernetes集群下的健康检查使用方法

云原生之kubernetes实战k8s集群核心资源对象之Pod