ASP.NET Core on K8S深入学习(6)Health Check


640?wx_fmt=gif

本篇已加入《.NET Core on K8S学习实践系列文章索引》,可以点击查看更多容器化技术相关系列文章。预计阅读时间为10分钟。


01

关于K8S中的健康监测


640?wx_fmt=png

  所谓Health Check,就是健康检查,即防微杜渐。K8S是一个编排引擎可以帮助我们快捷地部署容器集群,如果部署上错误的容器导致服务崩溃,通常情况下我们都会通过一些高可用机制进行故障转移。但是,前提条件是有健康检查。

  K8S自然帮我们考虑到了这个问题,健康检查是K8S的重要特性之一,默认有健康检查机制,此外还可以主动设置一些自定义的健康检查。

  默认情况下,每个容器启动时都会执行一个进程,由Dockerfile中的CMD或ENTRYPOINT指定。如果进程退出时的返回码不为0,则认为容器发生了故障,K8S会根据重启策略(restartPolicy)重启容器。

  例如下面这个例子,它模拟了容器发生故障的场景,注意下面配置文件中的args选项的定义:

apiVersion: v1kind: Podmetadata:  name: edc-healthcheck-demo  labels:    test: healthcheckspec:  restartPolicy: OnFailure  containers:    - name: healthcheck      image: busybox      imagePullPolicy: IfNotPresent      args:      - /bin/sh      - -c      - sleep 10; exit 1

  其中 sleep 10; exit 1代表启动10秒之后就非正常退出(返回码不为0),然后通过kubectl创建Pod:

kubectl apply -f health-check.yaml

  过一段时间后查看Pod的状态,如下图所示:

  640?wx_fmt=png

   可以看到,该容器已经重启了2次。也可以看出,restartPolicy简单直接暴力有效,不由感叹重启大法好!

  但是,也要正视一个问题:必须等到进程退出后的返回值是非零才会触发重启策略,不能直接监测容器是否是健康

  那么,K8S中有没有更好的机制能够实现智能一点的健康检查呢?答案就是使用Liveness与Readinesss。


02

Liveness探测


Liveness初体验

一句话Liveness:如果检测有问题(如果健康检查失败),重启pod!至于怎么检测,你说了算(自定义判断容器是否健康的条件)! 

  Liveness提供了一些重要的参数:

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

  下面实践一个小例子创建一个Pod:

#command自己定义,例子为 /tmp/healthy 不存在则认为pod有问题,大家根据实际业务来自定义。apiVersion: v1kind: Podmetadata:  labels:    test: liveness  name: liveness-demospec:  containers:  - name: liveness    image: busybox    args:    - /bin/sh    - -c    - touch /tmp/healthy; sleep 30; rm -rf/tmp/healthy; sleep 10    livenessProbe:      exec:        command:        - cat        - /tmp/healthy      initialDelaySeconds: 10      periodSeconds: 5

  这里启动pod后会创建文件夹 /tmp/healthy,30秒后删除,在我们的设置中,如果 /tmp/healthy 存在,则认为容器处于正常状态,否则认为发生故障。

  需要注意的就是livenessProbe部分的定义了:

  (1)探测方法:通过cat命令查看/tmp/healthy是否存在;如果返回值为0,则探测成功;否则,探测失败;

  (2)initialDelaySeconds: 10 => 容器启动10秒之后开始执行liveness探测;

  (3)periodSeconds: 5 => 每5秒执行一次liveness探测;如果连续执行3次探测都失败,那么就会杀掉并重启容器;

  下面快速地验证一下:

  (1)kubectl创建demo

kubectl apply -f liveness-demo.yaml

  (2)查看pod日志

kubectl describe pod liveness-demo

  结果如下图所示:

  640?wx_fmt=png

   30秒之后,/tmp/healthy 被删除了,liveness探测失败,又过了几十秒,重复探测均失败后,开启了重启容器。

  640?wx_fmt=png

Liveness探针

      上面的例子使用的是Liveness的exec探针,此外K8S还有几种其他类型的探针:

  • exec:在容器中执行一个命令,如果命令退出码返回0则表示探测成功,否则表示失败

  • tcpSocket:对指定的容IP及端口执行一个TCP检查,如果端口是开放的则表示探测成功,否则表示失败

  • httpGet:对指定的容器IP、端口及路径执行一个HTTP Get请求,如果返回的状态码在 [200,400)之间则表示探测成功,否则表示失败

  针对tcpSocket的例子:这里会检测80端口是否可以正常访问;

#检测80端口是否联通apiVersion: v1kind: Podmetadata:  labels:    test: readiness  name: readiness-tcpspec:  containers:  - name: readiness    image: nginx    readinessProbe:      failureThreshold: 3      tcpSocket:        port: 80      initialDelaySeconds: 10      periodSeconds: 10      successThreshold: 1      timeoutSeconds: 10

  针对httpGet的例子:这里会检测index.html文件是否可以正常访问;

#访问80端口的index.html文件是否存在apiVersion: v1kind: Podmetadata:  labels:    test: readiness  name: readiness-httpgetspec:  containers:  - name: readiness    image: nginx    readinessProbe:      failureThreshold: 3      httpGet:        path: /index.html        port: 80        scheme: HTTP      initialDelaySeconds: 10      periodSeconds: 10      successThreshold: 1      timeoutSeconds: 10

03

Readiness探测


Readiness初体验

一句话Readiness:如果检查失败,K8S会将该Pod从服务代理的分发后端去除,不再让其接客(分发请求给该Pod)。如果检测成功,那么K8S就会将容器加入到分发后端,重新对外接客(对外提供服务)。 

  下面继续以上面Liveness的例子来实践一下:


apiVersion: v1kind: Podmetadata:  labels:    test: readiness  name: readiness-demospec:  containers:  - name: readiness    image: busybox    args:    - /bin/sh    - -c    - touch /tmp/healthy; sleep 30; rm -rf/tmp/healthy; sleep 10    readinessProbe:      exec:        command:        - cat        - /tmp/healthy      initialDelaySeconds: 10      periodSeconds: 5

  readinessProbe的配置语法与livenessProbe完全一致,但执行后的效果却不一样,见下图所示:

  640?wx_fmt=png

  可以看出:

  (1)刚被创建时,其READY状态为不可用;

  (2)15秒(initialDelaySeconds + periodSeconds = 10 + 5 = 15)之后,第一次进行Readiness探测成功,其READY状态变为可用。

  (3)30秒之后,/tmp/healthy被删除,连续3次Readiness探测均失败后,其READY状态又变为了不可用。

  此外,我们也可以通过 kubectl describe pod readiness-demo 查看到更想起的日志信息。

与Liveness的对比

        Liveness与Readiness都是K8S的Health Check机制,Liveness探测是重启容器,而Readiness探测则是将容器设置为不可用,不让其再接受Service转发的请求。

  Liveness与Readiness是独立执行的,二者无依赖,可以单独使用也可以同时使用。


04

Health Check在K8S中的应用


在Scale Up中的应用

      对于多副本应用,当执行Scale Up操作时,新的副本会作为后端服务加入到Service的负载均衡列表中。但是,很多时候应用的启动都需要一定的时间做准备(比如加载缓存、连接数据库等等),这时我们可以通过Readiness探测判断容器是否真正就绪,从而避免将请求发送到还未真正就绪的后端服务。

  下面一个示例YAML配置文件定义了Readiness探测,重点关注readinessProbe部分:

apiVersion: apps/v1kind: Deploymentmetadata:  name: edc-webapi-deployment  namespace: aspnetcorespec:  replicas: 2  selector:    matchLabels:      name: edc-webapi  template:    metadata:      labels:        name: edc-webapi    spec:      containers:      - name: edc-webapi-container        image: edisonsaonian/k8s-demo:1.2        ports:        - containerPort: 80        imagePullPolicy: IfNotPresent        readinessProbe:          httpGet:            scheme: HTTP            path: /api/health            port: 80          initialDelaySeconds: 10          periodSeconds: 5
---
apiVersion: v1kind: Servicemetadata: name: edc-webapi-service namespace: aspnetcorespec: type: NodePort ports: - nodePort: 31000 port: 8080 targetPort: 80 selector: name: edc-webapi

  对于readinessProbe部分:

  (1)schema指定了协议,这里是HTTP协议,也可以是HTTPS协议;

  (2)path指定访问路径,这里是我们自定义的一个Controller中的接口:简单地返回一个状态码为200的响应;

    [Produces("application/json")]    [Route("api/Health")]    public class HealthController : Controller    {        [HttpGet]        public IActionResult Get() => Ok("ok");    }

  (3)port指定端口,这里是容器的端口80;

  (4)initialDelaySeconds和periodSeconds指定了容器启动10秒之后开始探测,然后每隔5秒执行探测,如果发生3次以上探测失败,则该容器会从Service的负载均衡中移除,直到下次探测成功后才会重新加入。

在Rolling Update中的应用

    假设现在有一个正常运行的多副本应用,我们要对其进行滚动更新即Rolling Update,K8S会逐步用新Pod替换旧Pod,结果就有可能发生这样的一个场景:当所有旧副本被替换之后,而新的Pod由于人为配置错误一直无法启动,因此整个应用将无法处理请求,无法对外提供服务,后果很严重!

  因此,Readiness探测还提供了用于避免滚动更新中出现这种情况的一些解决办法,比如maxSurge和maxUnavailable两个参数,用来控制副本替换的数量。

  继续以上面的YAML配置文件为例,重点关注strategy部分:

apiVersion: apps/v1kind: Deploymentmetadata:  name: edc-webapi-deployment  namespace: aspnetcorespec:  strategy:    rollingupdate:      maxSurge: 25%      maxUnavailable: 25%  replicas: 10  selector:    matchLabels:      name: edc-webapi  template:    metadata:      labels:        name: edc-webapi    spec:      containers:      - name: edc-webapi-container        image: edisonsaonian/k8s-demo:1.2        ports:        - containerPort: 80        imagePullPolicy: IfNotPresent        readinessProbe:          httpGet:            scheme: HTTP            path: /api/health            port: 80          initialDelaySeconds: 10          periodSeconds: 5
---
apiVersion: v1kind: Servicemetadata: name: edc-webapi-service namespace: aspnetcorespec: type: NodePort ports: - nodePort: 31000 port: 8080 targetPort: 80 selector: name: edc-webapi

  (1)maxSurge : 25% => 控制滚动更新过程中副本总数超过预期(这里预期是10个副本 replicas: 10)的上限,可以是数值也可以是百分比,然后向上取整。这里写的百分比,默认值是25%;

  如果预期副本数为10,那么副本总数的最大值为RoundUp(10 + 10 * 25%)=13个。

  (2)maxUnavailable : 25% => 控制滚动更新过程中不可用的副本(这里预期是10个副本 replicas: 10)占预期的最大比例,可以是数值也可以是百分比,然后向下取整,同样地默认值也是25%;

  如果预期副本总数为10,那么可用的副本数至少要为10-roundDown(10 * 25%)=10-2=8个。

  综上看来,maxSurge的值越大,初始创建的新副本数量就越多;maxUnavaliable值越大,初始销毁的旧副本数量就越多;


05

小结


本文探索了K8S中的默认健康检查机制以及Liveness和Readiness两种各有特点的探测机制,并通过一些小例子进行了说明。不过由于笔者也是初学,对于这一块没有过多实践经验,因此也是讲的比较粗浅,也希望以后能够有更多的实际经验分享与各位。


参考资料:

(1)CloudMan,《每天5分钟玩转Kubernetes》

(2)李振良,《一天入门Kubernets教程》

(3)马哥(马永亮),《Kubernetes快速入门》

(4)华仔,《[译]Kubernetes最佳实践:使用Readiness和Liveness探测做Health Check》

(5)benjanmin杨,《K8S中的Health Check》

(6)条子在洗澡,《K8S健康性检查-探测》



恰童鞋骚年,风华不再正茂,仍想挥斥方遒

640?wx_fmt=jpeg


点个在看少个bug ?


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/314263.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Polynomial(2019南昌邀请赛)(拉格朗日插值)

Polynomial 思路 题目给的是一个nnn次多项式,要我们求∑ilr\sum\limits_{i l} ^{r}il∑r​,也就是一个累加的形式,容易想到转换成求前缀和。 所以我们考虑求前缀和,容易得到这个多项式的前缀和一定是≥n&≤n1\geq n \&…

P3356 火星探险问题(网络流)

P3356 火星探险问题 对于一个第一次经过会有价值,但是之后经过没有价值的点,我们的处理方法就是只连一条流量为1并且有费用的边,再连接流量为INF但是没有费用的边,这样我们要使得价值最大就会优先流有费用的边。

ASP.NET Core 使用 JWT 自定义角色/策略授权需要实现的接口

目录① 存储角色/用户所能访问的 API② 实现 IAuthorizationRequirement 接口③ 实现 TokenValidationParameters④ 生成 Token⑤ 实现服务注入和身份认证配置⑥ 实现登陆⑦ 添加 API 授权策略⑧ 实现自定义授权校验⑨ 一些有用的代码① 存储角色/用户所能访问的 API例如 使用 …

EOJ Monthly 2019.11 E. 数学题(反演 + 杜教筛 + 拉格朗日插值)

EOJ Monthly 2019.11 ∑i1n∑a11i∑a21i∑a31i⋯∑ak−1i∑aki[gcd(a1,a2,a3,…,ak−1,ak,i)1]∑i1n∑d∣iμ(d)⌊id⌋k∑d1nμ(d)∑d∣i⌊id⌋k∑d1nμ(d)∑t1ndtk\sum_{i 1} ^{n} \sum_{a_1 1} ^{i} \sum_{a_2 1} ^{i} \sum_{a_3 1} ^{i} \dots \sum_{a_{k - 1}} ^{i} \s…

打表

打表 众所周知,打表是一项非常非常重要的技能QAQ 寻找通项:直接观察一元函数或者一些dp值或者sg值的规律注意二进制:有些规律不在10进制下,而是存在于二进制下观察递推关系:有时候无法得到有用的通项,但是…

关于 .Net Core runtimeconfig 文件说明

项目的bin\debug\netcoreapp${Version}下面能够找到这个${AppName}.runtimeconfig.json文件,简单来说,它就是用来定义应用程序所用的共享框架(.Net Core App)以及运行时选项 的一个文件。一个简单的例子{ "runtimeOptions&q…

F. Cowmpany Cowmpensation(树形dp + 拉格朗日插值)

F. Cowmpany Cowmpensation 首先一般dp推导dp[i][j]∏u∈soni∑k1jdp[v][k]dp[i][j] \prod\limits_{u \in son_i} \sum\limits_{k 1} ^{j} dp[v][k]dp[i][j]u∈soni​∏​k1∑j​dp[v][k] 这个是毫无疑问的,然后我们考虑如何得到d≥nd \geq nd≥n的情况。 我们…

P4055 [JSOI2009]游戏(二分图匹配+博弈)

P4055 [JSOI2009]游戏 对于一个网格,上面有一些障碍物不能走,A选择起点,然后B走到相邻的四个格子之一,然后轮流移动不能移动的一方失败。求解所有可以赢的初始位置。 首先对于这个问题要想到网格图上博弈,两个人走的…

net core 3.0 之Grpc新特性小试牛刀

作者: 相信微服务大家伙都有听说和知道,好处弊端咱也不多说了,Grpc算是一个比较全面的微服务框架,也得到微软的支持总结下来就是,跨平台,可靠,通信快,扩展性强,网络消耗小…

Fraction Construction Problem(拓展欧几里德)

Fraction Construction Problem 思路 cd−efab\frac{c}{d} - \frac{e}{f} \frac{a}{b}dc​−fe​ba​ a<b&f<ba < b \& f < ba<b&f<b 1≤1,e≤410121 \leq 1, e \leq 4 \times10 ^{12}1≤1,e≤41012 当b 1时&#xff0c;一定无解。 gcd(a, b…

CF1168D Anagram Paths(由必要到充分/虚树)

CF1168D Anagram Paths 对于这道题首先有一个关键的性质&#xff0c;那就是对于一个树&#xff0c;它是可重排的&#xff0c;当且仅当在树上任意一个节点&#xff0c;所有字母在相关联的字符串中出现次数最大值之和小于当前点到叶子的距离。这个性质可以通过归纳证明&#xff0…

基于Coravel定时任务之计算总页数

在物联网系统中&#xff0c;需要计算底端所有设备的总数&#xff0c;除以分页每页显示数量&#xff0c;进行一个总页数的显示。包括状态&#xff0c;告警&#xff0c;日志等等数据都需要对应的总页数的显示。2.1 TaskSchedulerTaskScheduler库只支持.net&#xff0c;且需要结合…

拉格朗日插值

拉格朗日插值 简要阐述 结论给定n1n 1n1个点最多可以得到一个nnn次多项式的表达式&#xff0c;并且f(x)∑i1nyi∏j∤ix−xjxi−yjf(x) \sum_{i 1} ^{n} y_i \prod\limits_{j \nmid i}\frac{x - x_j}{x_i - y_j}f(x)∑i1n​yi​j∤i∏​xi​−yj​x−xj​​我们随便往里带入…

A Story of One Country (Hard)(中途相遇法/启发式分裂)

A Story of One Country (Hard) https://www.luogu.com.cn/problem/solution/CF1181E2 首先考虑暴力的做法&#xff0c;就是每次排序然后寻找分割点&#xff0c;对分割点左右两边分治处理&#xff0c;但是这样的复杂度是 最坏情况下O(n2logn)O(n^2logn)O(n2logn) 然后我们考…

Docker系列之AspNetCore Runtime VS .NetCore Runtime VS SDK(四)

接下来我们就要慢慢步入在.NET Core中使用Docker的殿堂了&#xff0c;如题在开始之前&#xff0c;我们需要搞清楚一些概念&#xff0c;要不然看到官方提供如下一系列镜像&#xff0c;我们会一脸懵逼&#xff0c;不知道到底要使用哪一个。AspNetCore Runtime VS .NetCore Runti…

HDU 6750 Function(莫比乌斯反演)(2020百度之星初赛1)

Function 推式子 S(n)∑i1n∑d∣id[gcd(d,id)1]∑d1nd∑d∣i[gcd(d,id)1]∑d1nd∑i1nd[gcd(d,i)1]∑d1nd∑i1nd∑k∣gcd(d,i)μ(k)∑k1nμ(k)k∑d1nkd∑i1nk2dtk2d∑t1nnt∑k2∣tμ(k)ktk2∑k1nμ(k)k∑k2∣tnttk2itk2∑k1nμ(k)k∑i1nk2nik2iS(n) \sum_{i 1} ^{n} \sum_{d …

P5170 【模板】类欧几里得算法

P5170 【模板】类欧几里得算法 https://www.cnblogs.com/bztMinamoto/p/10334354.html 对于类欧几里得算法&#xff0c;本质上可以理解为一条直线下的整点个数&#xff0c;是一个矩形区域。 然后将整数部分提出&#xff0c;就可以使得这个直线斜率较小&#xff0c;那么我们就可…

.NET Core跨平台部署于Docker(Centos)- 视频教程

.NET Core跨平台部署于Docker,Docker部署于Centos中&#xff0c;演示跨平台特性&#xff01;以下视频教程&#xff0c;请带上耳机开始聆听往期教程&#xff1a;.NET开发框架(一)-框架介绍与视频演示.NET开发框架(二)-框架功能简述.NET开发框架(三)-高可用服务器端设计.NET开发框…

矩阵快速幂各类题型总结(一般,共轭,1 * n, 矩阵简化)

Reading comprehension 这个不难找出递推式f[n]f[n−1]2f[n−2]1f[n] f[n - 1] 2f[n - 2] 1f[n]f[n−1]2f[n−2]1。 /*Author : lifehappy */ #pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc.h>using namespace std;typedef long long ll;co…

【清华集训2014】Sum)(类欧几里得算法)

【清华集训2014】Sum 然后本质上我们需要求解的就是那个带根号式子的奇偶性&#xff0c;然后我们发现这个式子很像是类欧几里得算法&#xff0c;求解一个斜率为无理数直线下的整点个数&#xff0c;然后我们直接对于一般形式求解&#xff0c;那么就是每次利用整数部分将斜率减小…