• linux运维、架构之路-K8s健康检查Health Check


    一、Health Check介绍

            强大的自愈能力是k8s容器编排引擎一个重要特性,自愈能力的默认实现方式为自动重启发生故障的容器,另外还可以利用Liveness和Readiness探测机制设置更精细的健康检查。

    • 零停机部署
    • 避免部署无效的镜像
    • 更加安全的滚动升级

    二、K8S健康检查方式

    1、k8s默认的健康检查

           每个容器启动时都会执行一个进程,此进程由Dockerfile的CMD或ENTRYPOINT指定。如果进程退出返回码为非0,则认为容器发生故障,k8s会根据restartPolicy重启容器。

    ①创建应用测试

    apiVersion: v1
    kind: Pod
    metadata:
      name: healthcheck
      labels:
        test: healthcheck
    spec:
      restartPolicy: OnFailure
      containers:
      - name: healthcheck
        image: busybox
        args:
        - /bin/sh
        - -c
        - sleep 10;exit 1

    ②Pod的restartPolicy设置为OnFailure,默认策略为Always,执行创建Pod

    kubectl apply -f healthcheck.yaml

    ③过几分钟查看Pod状态,发现容器已经重启了3次

    [root@k8s-node1 health_check]# kubectl get pods healthcheck 
    NAME          READY     STATUS    RESTARTS   AGE
    healthcheck   0/1       Error     3          2m

    容器进程返回值非0,k8s则认为容器发生故障,需要重启,有不少场景下发生故障,但进程不会退出,比如访问web服务时发生500内部错误,可能是负载过高,也可能是资源死锁,此时httpd进程并没有异常退出,在这种情况下重启容器可能是最直接、最有效的解决方案,处理此类场景那就用到了k8s的Liveness探测。

    2、Liveness探测

           Liveness探测让用户可以自定义判断容器是否健康的条件,如果探测失败,k8s就会重启容器。

    ①创建应用演示

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

    以上yaml文件说明:启动Pod后首先创建文件/tmp/healthy,30秒后删除,如果文件/tmp/healthy存在,则认为容器处于正常状态,反之发生故障。

    探测方法:

    • 通过cat命令检查/tmp/healthy文件是否存在,如果命令执行成功,返回值为0,k8s会认为本次Liveness探测成功;如果命令返回值非0,本次Liveness探测失败
    • initialDelaySeconds: 10 指容器启动10秒后开始执行Liveness探测,如果你的应用启动要花30秒,那么initialDelaySeconds的值就应该大于30。
    • periodSeconds: 5 指每5秒执行一次Liveness探测,k8s如果连续执行3次Liveness探测均失败,则会杀掉重启容器

    ②创建Pod并查看

    kubectl apply -f liveness.yaml
    kubectl describe pod liveness

     ③35秒之后,日志显示/tmp/healthy已经不存在了,Liveness连续几次探测失败,容器会被重启

     ④再次查看pod,发现已经重启1次

    [root@k8s-node1 health_check]# kubectl get pods liveness 
    NAME       READY     STATUS    RESTARTS   AGE
    liveness   1/1       Running   1          1m

    3、Readiness探测

            Liveness探测可以告诉k8s什么时候通过重启容器实现自愈;Readiness探测告诉k8s什么时候可以将容器加入到service负载均衡池中,对外提供服务。

    ①Readiness探测配置与Liveness探测完全一样

    apiVersion: v1
    kind: Pod
    metadata:
      name: readiness
      labels:
        test: readiness
    spec:
      restartPolicy: OnFailure
      containers:
      - name: readiness
        image: busybox
        args:
        - /bin/sh
        - -c
        - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 10
          periodSeconds: 5

    ②创建并查看

    kubectl apply -f readiness.yaml
    [root@k8s-node1 health_check]# kubectl get pod readiness
    NAME        READY     STATUS    RESTARTS   AGE
    readiness   0/1       Running   0          8s
    
    [root@k8s-node1 health_check]# kubectl get pod readiness
    NAME        READY     STATUS    RESTARTS   AGE
    readiness   1/1       Running   0          18s
    
    [root@k8s-node1 health_check]# kubectl get pod readiness
    NAME        READY     STATUS    RESTARTS   AGE
    readiness   0/1       Running   0          49s

    探测方法:

    • 刚创建时,READY状态不可用
    • 15秒后,第一次进行Readiness探测并成功返回,设置READY为可用
    • 30秒后,/tmp/healthy被删除,连续3次Readiness探测失败后,READY被设置为不可用

    ③查看日志详情

    kubectl describe pod readiness

     4、Readiness探测与Liveness探测区别

    • Readiness探测与Liveness探测是两种Health Check机制,如果不特意配置,k8s对两种探测采取相同的默认行为,均通过判断容器启动进程的返回值是否为0判断探测是否成功。
    • 两种探测配置方法完全一样,支持的配置参数也一样,不同在于探测失败后,Liveness探测是重启容器,Readiness探测则将容器设置为不可用,不接收service转发的请求
    • Readiness探测与Liveness探测是独立执行的,二者之间没有依赖,可以单独使用,也可以同时使用,用Liveness探测判断容器是否需要重启以实现自愈,用Readiness探测判断容器是否已经准备好对外提供服务

     三、Health Check在Scale UP中的应用

                在多副本应用中,当执行Scale Up新增一个副本的场景中,考虑到应用启动需要一些时间,比如加载缓存数据、连接数据库等,这里就可以通过Readiness探测判断容器是否就绪,避免将请求发送到还没准备好的
    后端。

    1、创建应用测试

    apiVersion: apps/v1beta2
    kind: Deployment
    metadata:
      name: web
    spec:
      replicas: 3
      template:
        metadata:
          labels:
            app: web
        spec:
          containers:
          - name: web
            image: httpd
            ports:
            - containerPort: 8080
            readinessProbe:
              httpGet:
                scheme: HTTP     #指定协议,默认为HTTP
                path: /healthy   #访问路径
                port: 8080
              initialDelaySeconfs: 10
              periodSeconds: 5  
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: web-svc
    spec:
      selector:
        app: web
      ports:
       - protocol: TCP
         port: 8080
         targetPort: 80

    注:这里使用了不同与exec的另一种探测方法httpGet,k8s对该方法探测成功的判断是http请求返回码在200~400之间

    2、上面配置作用

    • 容器启动10秒后开始探测
    • 如果http://[container_ip]:8080/healthy返回码不是200~400,表示容器没有就绪,不接收Service web-svc的请求。
    • 每隔5秒探测一次
    • 直到返回码为200~400,表明容器已经就绪,然后将其加入到web-svc的负载中,开始处理请求。
    • 探测继续以5秒的间隔执行,如果连续3次失败,容器会从负载中移除,直到再次探测成功后重新加入负载

    四、Health Check在滚动更新中的应用

                Health Check另一个重要场景就是滚动更新,现有一个正常运行的多副本应用,接下来要对应用进行更新,比如升级成高版本的image,k8s会启动新副本的过程如下:

    • 正常情况一下启动的新副本需要10秒左右完成准备工作,在此之前无法响应业务请求
    • 由于人为配置错误,副本始终无法完成准备工作,比如无法连接后端的数据库
    生产环境中,如果没有配置Health Check,默认Health Check机制会认为容器已经就绪,进行会逐步用新副本替换现有副本,当所有旧副本都被替换后,整个应用将无法处理请求,无法提供服务,
    如果正确配置了Health Check,新副本只有通过了Readiness探测才会被添加到Service,如果探测不成功,现有副本不会被会部替换,业务仍然正常进行。

    1、创建应用测试

    kubectl apply -f app-v1.yaml --record
    apiVersion: apps/v1beta1
    kind: Deployment
    metadata:
      name: app
    spec:
      replicas: 10
      template:
        metadata:
          labels:
            run: app
        spec:
          containers:
          - name: app
            image: busybox
            args:
            - /bin/sh
            - -c
            - sleep 10; touch /tmp/healthy; sleep 30000
            readinessProbe:
              exec:
                command:
                - cat
                - /tmp/healthy
              initialDelaySeconds: 10
              periodSeconds: 5

    2、10秒后查看所有副本通过了Readiness探测

    [root@k8s-node1 health_check]# kubectl get deployment app
    NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    app       10        10        10           10          7m
    [root@k8s-node1 health_check]# kubectl get pods
    NAME                       READY     STATUS    RESTARTS   AGE
    app-58594c894-4bfzn        1/1       Running   0          6m
    app-58594c894-5wnxv        1/1       Running   0          6m
    app-58594c894-9jspd        1/1       Running   0          6m
    app-58594c894-bmgp9        1/1       Running   0          6m
    app-58594c894-d8r72        1/1       Running   0          6m
    app-58594c894-k42zf        1/1       Running   0          6m
    app-58594c894-rvnpl        1/1       Running   0          6m
    app-58594c894-ssg9w        1/1       Running   0          6m
    app-58594c894-z2qd6        1/1       Running   0          6m
    app-58594c894-zb6d8        1/1       Running   0          6m

    3、进行滚动更新,创建app-v2.yaml

    apiVersion: apps/v1beta1
    kind: Deployment
    metadata:
      name: app
    spec:
      replicas: 10
      template:
        metadata:
          labels:
            run: app
        spec:
          containers:
          - name: app
            image: busybox
            args:
            - /bin/sh
            - -c
            - sleep 3000
            readinessProbe:
              exec:
                command:
                - cat
                - /tmp/healthy
              initialDelaySeconds: 10
              periodSeconds: 5

    4、验证新副本中不存在/tmp/healthy,能否通过Readiness探测

    [root@k8s-node1 health_check]# kubectl get deployment app
    NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    app       10        13        5            8           1h
    #DESIRED 10:表示期望状态是10个副本
    #CURRENT 13: 表示当前副本总数,8个旧副本+5个新副本
    #UP-TO-DATE 5:表示当前已完成更新的副本数
    #AVAILABLE 8:表示当前处于可用的副本数 [root@k8s
    -node1 health_check]# kubectl get pods NAME READY STATUS RESTARTS AGE app-58594c894-4bfzn 1/1 Running 0 1h app-58594c894-5wnxv 1/1 Running 0 1h app-58594c894-9jspd 1/1 Running 0 1h app-58594c894-bmgp9 1/1 Running 0 1h app-58594c894-d8r72 1/1 Running 0 1h app-58594c894-k42zf 1/1 Running 0 1h app-58594c894-ssg9w 1/1 Running 0 1h app-58594c894-z2qd6 1/1 Running 0 1h app-67f89fbd77-4fkq5 0/1 Running 0 1m app-67f89fbd77-7fgjg 0/1 Running 0 1m app-67f89fbd77-krf8w 0/1 Running 0 1m app-67f89fbd77-r25rx 0/1 Running 0 1m app-67f89fbd77-wdrsr 0/1 Running 0 1m

    5、为什么新创建副本数是5个,同时只销毁2个旧副本

    • 1、maxSurge
    • 此参数控制滚动更新过程中副本总数超过DESIRED的上限,默认值为25%,也可以是具体的整数,上面例子中,DESIRED为10,副本总数CURRENT最大值即为:10+10*25%=13,maxSurge值越大,初始创建的新副本就越多。
    • 2、maxUnavailable
    • 此参数控制滚动更新过程中,不可用的副本占DESIRED的最大比例。同样maxUnavailable默认值也为25%,那么可用的副本至少为10-10*25%=8,maxUnavailable值越大,初始销毁的副本数量就越多

    6、正常滚动更新过程

    • 创建3个新副本使副本总数达到13个
    • 销毁2个旧副本使可用的副本数降到8个
    • 当2个旧副本成功销毁后,再创建2个新副本,保持副本总数为13个
    • 当新副本通过Readiness探测后,会使可用副本数增加,超过8个
    • 进而可以继续销毁更多的副本,使可用副本数回到8
    • 旧副本的销毁使副本总数低于13,这样可以继续创建新的副本
    • 这个过程一直持续进行,最终所有的旧副本被新副本替换,滚动更新完成
    • 如果滚动更新失败,使用命令kubectl rollout undo deployment app快速回滚到上一版本

    7、自定义maxSurge和maxUnavailable

    apiVersion: apps/v1beta1
    kind: Deployment
    metadata:
      name: app
    spec:
      strategy:
        rollingUpdate:
          maxSurge: 35%
          maxUnavailable: 35%
      replicas: 10
      template:
        metadata:
          labels:
            run: app
        spec:
          containers:
          - name: app
            image: busybox
            args:
            - /bin/sh
            - -c
            - sleep 10; touch /tmp/healthy; sleep 30000
            readinessProbe:
              exec:
                command:
                - cat
                - /tmp/healthy
              initialDelaySeconds: 10
              periodSeconds: 5
  • 相关阅读:
    搭建redis sentinel 和 cluster
    ASP.NET WebForm Ajax请求Handler的经验
    ASP.NET WebForm Identity使用
    Github Pages 无法调用 node_modules 文件夹的解决方案
    聊聊手机之--小米6
    boostrap-非常好用但是容易让人忽略的地方【7】:list-unstyled list-inline
    boostrap-非常好用但是容易让人忽略的地方【6】:role属性
    monaco-editor使用
    关于oppo和vivo这两年强势崛起的反思
    Build 2017(简体中文视频)
  • 原文地址:https://www.cnblogs.com/yanxinjiang/p/11977392.html
Copyright © 2020-2023  润新知