zoukankan      html  css  js  c++  java
  • Docker系列(五):.Net Core实现k8s健康探测机制

           k8s通过liveness来探测微服务的存活性,判断什么时候该重启容器实现自愈。比如访问 Web 服务器时显示 500 内部错误,可能是系统超载,也可能是资源死锁,此时 httpd 进程并没有异常退出,在这种情况下重启容器可能是最直接最有效的解决方案。

           k8s通过readiness来探测微服务的什么时候准备就绪(例如初始化时,连接数据库,加载缓存数据等等,可能需要一段时间),然后将容器加入到server的负载均衡池中,对外提供服务。

           k8s默认健康检查机制:

                  每个容器启动时都会执行一个进程,此进程由 Dockerfile 的 CMD 或 ENTRYPOINT 指定。如果进程退出时返回码非零,则认为容器发生故障,Kubernetes 就会根据 restartPolicy 重启容器。如果不特意配置,Kubernetes 将对两种探测采取相同的默认行为。

    OK,那我们就来实现一下,新建.Net Core Api项目 k8s-healthcheck,新增Heathchecks控制器:

        [Route("/api/v1/heathchecks")]
        public class HeathchecksController : Controller
        {
            private readonly static DateTime _beginUtc = DateTime.Now;
    
            [HttpGet]
            [Route("test")]
            public ActionResult<IEnumerable<string>> Test()
            {
                return new string[] { "value1", "value2" };
            }
    
            [HttpGet]
            [ProducesResponseType((int)HttpStatusCode.OK)]
            [ProducesResponseType((int)HttpStatusCode.ServiceUnavailable)]
            [Route("liveness")]
            public async Task<IActionResult> Liveness()
            {
                return await Task.Run<IActionResult>(() =>
                {
                    if(DateTime.UtcNow.Subtract(_beginUtc).TotalSeconds>60*10)
                    {
                        Console.WriteLine("{0} HealthChecks.Api is dead start restarting...",DateTime.Now);
                        return this.NotFound();
                    }
                    else
                    {
                        Console.WriteLine("{0} HealthChecks.Api is alive.",DateTime.Now);
                        return this.Ok();
                    }
                });
            }
    
            [HttpGet]
            [ProducesResponseType((int)HttpStatusCode.OK)]
            [ProducesResponseType((int)HttpStatusCode.ServiceUnavailable)]
            [Route("readiness")]
            public async Task<IActionResult> Readiness()
            {
                return await Task.Run<IActionResult>(() =>
                {
                    if(DateTime.UtcNow.Subtract(_beginUtc).TotalSeconds<30)
                    {
                        Console.WriteLine("{0} HealthChecks.Api is not ready...",DateTime.Now);
                        return this.NotFound();
                    }
                    else
                    {
                        Console.WriteLine("{0} HealthChecks is ready,start accepting traffic...", DateTime.Now);
                        return this.Ok();
                    }
                });
            }
        }

    解释一下我们这里自定义的 liveness 和 readiness检查机制:

    liveness:存活10分钟,如果当前时间超过服务启动时间10分钟,则探测失败,否则探测成功。Kubernetes 如果连续执行 3 次 Liveness 探测均失败,就会杀掉并重启容器。

    readiness:准备就绪30秒,30秒后,如果连续 3 次 Readiness 探测均失败后,容器将被重置为不可用,不接收 service 转发的请求。

    从上面可以看到,我们可以根据自身的需求来实现这两种机制,然后,提供给k8s进行探测。

            k8s默认是根据命令进行探测的,由于我们需要与微服务结合,所以需要在yml文件中指定为http方式(备注:k8s提供了三种container probes方式:command、TCP check、HTTP Get,其他的方式希望大家下去自己实践),k8s对于http方式探测成功的判断条件是请求的返回代码在 200-400 之间。

    该项目的 deploy.yaml 内容如下:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      namespace: k8s-ecoysystem-apps
      name: k8s-healthcheck
      labels:
        app: k8s-healthcheck
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: k8s-healthcheck
      template:
        metadata:
          namespace: k8s-ecoysystem-apps
          labels:
            app: k8s-healthcheck
        spec:
          containers:
          - name: k8s-healthcheck
            imagePullPolicy: Always
            image: 1151322093/k8s-healthcheck
            ports:
            - containerPort: 80
            readinessProbe:
              httpGet:
                path: /api/v1/heathchecks/readiness
                port: 80
                scheme: HTTP 
              initialDelaySeconds: 30
              periodSeconds: 60 
            livenessProbe:
              httpGet:
                path: /api/v1/heathchecks/liveness
                port: 80
                scheme: HTTP 
              initialDelaySeconds: 120
              periodSeconds: 60

    运行:kubectl apply -f deploy.yaml,然后通过 kubectl get pod -n k8s-ecoysystem-apps查看当前运行的pod,可以看到创建开始是不可以的,Ready状态数量是0。

    稍等等待一会发现都可以用了:

    然后我们通过 kubectl describe pod k8s-healthcheck-5c85bdcb69-f9zk9 -n k8s-ecoysystem-apps 命令可以查看更具体的信息:

    刚开始readiness返回404不可用状态,不过我们设置的是30秒检查一次,所以很快状态就消除了,通过dashboard界面我们也可以看到更直观的信息:

    等待10分钟过后,Liveness检测将会返回失败,pod处于不可用状态:

     

    继续等待一会,集群就会自愈完成,前面说过,Liveness检测3次失败就会删除pod,并重启,重启之后就一轮新的检测:

    从上面图中可以看到集群已经重启过1次,继续等待一段时间,如图:

     Liveness 探测和 Readiness 探测是独立执行的,二者之间没有依赖,可以单独使用,也可以同时使用。用 Liveness 探测判断容器是否需要重启以实现自愈;用 Readiness 探测判断容器是否已经准备好对外提供服务

    OK,大功告成!!

  • 相关阅读:
    javascript控制页面(含iframe进行页面跳转)跳转、刷新的方法汇总
    window下安装docker
    http协议
    php环境选择
    jsmooth和exe4j
    域名解析
    clientHeight,offsetHeight,scrollHeight迷一样的三个值
    LinkedHashMap和hashMap和TreeMap的区别
    fiddler抓包
    mac下配置openfire
  • 原文地址:https://www.cnblogs.com/weiBlog/p/10056281.html
Copyright © 2011-2022 走看看