Kubernetes Pod(Pod Hook?Pod 健康检查?Pod 资源配置?)(十八)
一、Pod Hook
我们知道 Pod 是 Kubernetes 集群中的最小单元,而 Pod 是由容器组成的,所以在讨论 Pod 的生命周期的时候我们可以先来讨论下容器的生命周期。实际上 Kubernetes 为我们的容器提供了生命周期的钩子,就是我们说的Pod Hook,Pod Hook 是由 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。我们可以同时为 Pod 中的所有容器都配置 hook。
Kubernetes 为我们提供了两种钩子函数:
- PostStart:这个钩子在容器创建后立即执行。但是,并不能保证钩子将在容器 ENTRYPOINT 之前运行,因为没有参数传递给处理程序。主要用于资源部署、环境准备等。不过需要注意的是如果钩子花费太长时间以至于不能运行或者挂起,容器将不能达到 running 状态。
- PreStop:这个钩子在容器终止之前立即被调用。它是阻塞的,意味着它是同步的,所以它必须在删除容器的调用发出之前完成。主要用于优雅关闭应用程序、通知其他系统等。如果钩子在执行期间挂起,Pod 阶段将停留在 running 状态并且永不会达到 failed 状态。
如果 PostStart 或者 PreStop 钩子失败, 它会杀死容器。所以我们应该让钩子函数尽可能的轻量。当然有些情况下,长时间运行命令是合理的, 比如在停止容器之前预先保存状态。
另外我们有两种方式来实现上面的钩子函数:
- Exec - 用于执行一段特定的命令,不过要注意的是该命令消耗的资源会被计入容器。
- HTTP - 对容器上的特定的端点执行 HTTP 请求。
以下示例中,定义了一个 Nginx Pod,其中设置了 PostStart 钩子函数,即在容器创建成功后,写入一句话到 /usr/share/message 文件中:(pod-poststart.yaml)
apiVersion: v1
kind: Pod
metadata:
name: hook-demo1
spec:
containers:
- name: hook-demo1
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
直接创建上面的 Pod:
$ kubectl apply -f pod-poststart.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hook-demo1 1/1 Running 0 43s
创建成功后可以查看容器中 /usr/share/message 文件是否内容正确:
$ kubectl exec -it hook-demo1 cat /usr/share/message
Hello from the postStart handler
当用户请求删除含有 Pod 的资源对象时(如 Deployment 等),K8S 为了让应用程序优雅关闭(即让应用程序完成正在处理的请求后,再关闭软件),K8S 提供两种信息通知:
- 默认:K8S 通知 node 执行 docker stop 命令,docker 会先向容器中 PID 为 1 的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认超时时间(30s),会继续发送SIGKILL的系统信号强行 kill 掉进程
- 使用 Pod 生命周期(利用PreStop回调函数),它在发送终止信号之前执行
默认所有的优雅退出时间都在30秒内。kubectl delete 命令支持 --grace-period=选项,这个选项允许用户用他们自己指定的值覆盖默认值。值'0'代表强制删除 pod。 在 kubectl 1.5 及以上的版本里,执行强制删除时必须同时指定 --force --grace-period=0。
强制删除一个 pod 是从集群状态还有 etcd 里立刻删除这个 pod,只是当 Pod 被强制删除时, APIServer 不会等待来自 Pod 所在节点上的 kubelet 的确认信息:pod 已经被终止。在 API 里 pod 会被立刻删除,在节点上, pods 被设置成立刻终止后,在强行杀掉前还会有一个很小的宽限期。
以下示例中,定义了一个 Nginx Pod,其中设置了PreStop钩子函数,即在容器退出之前,优雅的关闭 Nginx:(pod-prestop.yaml)
apiVersion: v1
kind: Pod
metadata:
name: hook-demo2
spec:
containers:
- name: hook-demo2
image: nginx
lifecycle:
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"] # 优雅退出
---
apiVersion: v1
kind: Pod
metadata:
name: hook-demo3
spec:
volumes:
- name: message
hostPath:
path: /tmp
containers:
- name: hook-demo2
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: message
mountPath: /usr/share/
lifecycle:
preStop:
exec:
command: ['/bin/sh', '-c', 'echo Hello from the preStop Handler > /usr/share/message']
上面定义的两个 Pod,一个是利用 preStop 来进行优雅删除,另外一个是利用 preStop 来做一些信息记录的事情,同样直接创建上面的 Pod:
$ kubectl apply -f pod-prestop.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hook-demo2 1/1 Running 0 67s
hook-demo3 1/1 Running 0 67s
创建完成后,我们可以直接删除 hook-demo2 这个 Pod,在容器删除之前会执行 preStop 里面的优雅关闭命令,这个用法在后面我们的滚动更新的时候用来保证我们的应用零宕机非常有用。第二个 Pod 我们声明了一个 hostPath 类型的 Volume,在容器里面声明挂载到了这个 Volume,所以当我们删除 Pod,退出容器之前,在容器里面输出的信息也会同样的保存到宿主机(一定要是 Pod 被调度到的目标节点)的 /tmp 目录下面,我们可以查看 hook-demo3 这个 Pod 被调度的节点:
$ kubectl describe pod hook-demo3
Name: hook-demo3
Namespace: default
Priority: 0
Node: node1/10.151.30.22
Start Time: Tue, 12 Nov 2019 14:33:54 +0800
......
可以看到这个 Pod 被调度到了 node1 这个节点上,我们可以先到该节点上查看 /tmp 目录下面目前没有任何内容:
$ ls /tmp/
现在我们来删除 hook-demo3 这个 Pod,安装我们的设定在容器退出之前会执行 preStop 里面的命令,也就是会往 message 文件中输出一些信息:
$ kubectl delete pod hook-demo3
pod "hook-demo3" deleted
$ ls /tmp/
message
$ cat /tmp/message
Hello from the preStop Handler
另外 Hook 调用的日志没有暴露个给 Pod,所以只能通过 describe 命令来获取,如果有错误将可以看到 FailedPostStartHook 或 FailedPreStopHook 这样的 event。
二、Pod 健康检查
现在在 Pod 的整个生命周期中,能影响到 Pod 的就只剩下健康检查这一部分了。在 Kubernetes 集群当中,我们可以通过配置liveness probe(存活探针)和readiness probe(可读性探针)来影响容器的生命周期:
kubelet 通过使用 liveness probe 来确定你的应用程序是否正在运行,通俗点将就是是否还活着。一般来说,如果你的程序一旦崩溃了, Kubernetes 就会立刻知道这个程序已经终止了,然后就会重启这个程序。而我们的 liveness probe 的目的就是来捕获到当前应用程序还没有终止,还没有崩溃,如果出现了这些情况,那么就重启处于该状态下的容器,使应用程序在存在 bug 的情况下依然能够继续运行下去。
kubelet 使用 readiness probe 来确定容器是否已经就绪可以接收流量过来了。这个探针通俗点讲就是说是否准备好了,现在可以开始工作了。只有当 Pod 中的容器都处于就绪状态的时候 kubelet 才会认定该 Pod 处于就绪状态,因为一个 Pod 下面可能会有多个容器。当然 Pod 如果处于非就绪状态,那么我们就会将他从 Service 的 Endpoints 列表中移除出来,这样我们的流量就不会被路由到这个 Pod 里面来了。
和前面的钩子函数一样的,我们这两个探针的支持下面几种配置方式:exec:执行一段命令
http:检测某个 http 请求
tcpSocket:使用此配置,kubelet 将尝试在指定端口上打开容器的套接字。如果可以建立连接,容器被认为是健康的,如果不能就认为是失败的。实际上就是检查端口。
我们先来给大家演示下存活探针的使用方法,首先我们用 exec 执行命令的方式来检测容器的存活,如下:(liveness-exec.yaml)
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec
spec:
containers:
- name: liveness
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
我们这里需要用到一个新的属性:livenessProbe,下面通过 exec 执行一段命令:
periodSeconds:表示让 kubelet 每隔5秒执行一次存活探针,也就是每5秒执行一次上面的cat /tmp/healthy命令,如果命令执行成功了,将返回0,那么 kubelet 就会认为当前这个容器是存活的,如果返回的是非0值,那么 kubelet 就会把该容器杀掉然后重启它。默认是10秒,最小1秒。
initialDelaySeconds:表示在第一次执行探针的时候要等待5秒,这样能够确保我们的容器能够有足够的时间启动起来。大家可以想象下,如果你的第一次执行探针等候的时间太短,是不是很有可能容器还没正常启动起来,所以存活探针很可能始终都是失败的,这样就会无休止的重启下去了,对吧?
我们在容器启动的时候,执行了如下命令:
$ /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是不是就会失败了(默认检测失败3次才认为失败),所以这个时候就会重启容器了。
我们来创建下该 Pod,然后在 30 秒内,查看 Pod 的 Event:
$ kubectl apply -f liveness-exec.yaml
$ kubectl describe pod liveness-exec
......
Normal Started 20s kubelet, node2 Started container liveness
......
Normal Started 46s kubelet, node2 Started container liveness
Warning Unhealthy 3s (x3 over 13s) kubelet, node2 Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
Normal Killing 3s kubelet, node2 Container liveness failed liveness probe, will be restarted
我们可以观察到容器是正常启动的,在隔一会儿,比如 40s 后,再查看下 Pod 的 Event,在最下面有一条信息显示 liveness probe 失败了,容器将要重启。然后可以查看到 Pod 的 RESTARTS 值加 1 了:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
liveness-exec 1/1 Running 1 1m
同样的,我们还可以使用HTTP GET请求来配置我们的存活探针,我们这里使用一个 liveness 镜像来验证演示下:(liveness-http.yaml)
apiVersion: v1
kind: Pod
metadata:
name: liveness-http
spec:
containers:
- name: liveness
image: cnych/liveness
args:
- /server
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
同样的,根据 periodSeconds 属性我们可以知道 kubelet 需要每隔3秒执行一次 liveness Probe,该探针将向容器中的 server 的 8080 端口发送一个 HTTP GET 请求。如果 server 的 /healthz 路径的 handler 返回一个成功的返回码,kubelet 就会认定该容器是活着的并且很健康,如果返回失败的返回码,kubelet 将杀掉该容器并重启它。initialDelaySeconds 指定kubelet 在该执行第一次探测之前需要等待3秒钟。
我们可以来查看下上面的 healthz 的实现:
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"))
}
})
大概意思就是最开始前 10s 返回状态码200,10s 过后就返回状态码500。所以当容器启动3秒后,kubelet 开始执行健康检查。第一次健康检查会成功,因为是在 10s 之内,但是 10 秒后,健康检查将失败,因为现在返回的是一个错误的状态码了,所以 kubelet 将会杀掉和重启容器。
同样的,我们来创建下该 Pod 测试下效果,10 秒后,查看 Pod 的 event,确认 liveness probe 失败并重启了容器:
$ kubectl apply -f liveness-http.yaml
$ kubectl describe pod liveness-http
......
Normal Pulled 12s (x3 over 76s) kubelet, node1 Successfully pulled image "cnych/liveness"
Normal Created 12s (x3 over 76s) kubelet, node1 Created container liveness
Normal Started 11s (x3 over 76s) kubelet, node1 Started container liveness
......
Normal Pulling 15s (x4 over 102s) kubelet, node1 Pulling image "cnych/liveness"
Warning Unhealthy 15s (x9 over 87s) kubelet, node1 Liveness probe failed: HTTP probe failed with statuscode: 500
Normal Killing 15s (x3 over 81s) kubelet, node1 Container liveness failed liveness probe, will be restarted
......
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
liveness-http 1/1 Running 3 2m2s
除了上面的 exec 和 httpGet 两种检测方式之外,还可以通过 tcpSocket 方式来检测端口是否正常,大家可以按照上面的方式结合kubectl explain命令自己来验证下这种方式。
另外前面我们提到了探针里面有一个initialDelaySeconds的属性,可以来配置第一次执行探针的等待时间,对于启动非常慢的应用这个参数非常有用,比如 Jenkins、Gitlab 这类应用,但是如何设置一个合适的初始延迟时间呢?这个就和应用具体的环境有关系了,所以这个值往往不是通用的,这样的话可能就会导致一个问题,我们的资源清单在别的环境下可能就会健康检查失败了,为解决这个问题,在 Kubernetes v1.16 版本官方特地新增了一个 startupProbe(启动探针),该探针将推迟所有其他探针,直到 Pod 完成启动为止,使用方法和存活探针一样:
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30 # 尽量设置大点
periodSeconds: 10
比如上面这里的配置表示我们的慢速容器最多可以有5分钟(30个检查 * 10秒= 300s)来完成启动。
有的时候,应用程序可能暂时无法对外提供服务,例如,应用程序可能需要在启动期间加载大量数据或配置文件。在这种情况下,您不想杀死应用程序,也不想对外提供服务。那么这个时候我们就可以使用readiness probe来检测和减轻这些情况。 Pod 中的容器可以报告自己还没有准备,不能处理 Kubernetes 服务发送过来的流量。readiness probe的配置跟liveness probe基本上一致的。唯一的不同是使用readinessProbe而不是livenessProbe。两者如果同时使用的话就可以确保流量不会到达还未准备好的容器,准备好过后,如果应用程序出现了错误,则会重新启动容器。对于就绪探针我们会在后面 Service 的章节和大家继续介绍。
另外除了上面的initialDelaySeconds和periodSeconds属性外,探针还可以配置如下几个参数:
- timeoutSeconds:探测超时时间,默认1秒,最小1秒。
- successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功。默认是 1,但是如果是liveness则必须是 1。最小值是 1。
- failureThreshold:探测成功后,最少连续探测失败多少次才被认定为失败。默认是 3,最小值是 1。
三、Pod 资源配置
实际上上面几个步骤就是影响一个 Pod 生命周期的大的部分,但是还有一些细节也会在 Pod 的启动过程进行设置,比如在容器启动之前还会为当前的容器设置分配的 CPU、内存等资源,我们知道我们可以通过 CGroup 来对容器的资源进行限制,同样的,在 Pod 中我们也可以直接配置某个容器的使用的 CPU 或者内存的上限。那么 Pod 是如何来使用和控制这些资源的分配的呢?
首先对于 CPU,我们知道计算机里 CPU 的资源是按“时间片”的方式来进行分配的,系统里的每一个操作都需要 CPU 的处理,所以,哪个任务要是申请的 CPU 时间片越多,那么它得到的 CPU 资源就越多,这个很容器理解。
然后还需要了解下 CGroup 里面对于 CPU 资源的单位换算:
1 CPU = 1000 millicpu(1 Core = 1000m)
0.5 CPU = 500 millicpu (0.5 Core = 500m)
这里的 m 就是毫、毫核的意思,Kubernetes 集群中的每一个节点可以通过操作系统的命令来确认本节点的 CPU 内核数量,然后将这个数量乘以1000,得到的就是节点总 CPU 总毫数。比如一个节点有四核,那么该节点的 CPU 总毫量为 4000m,如果你要使用0.5 core,则你要求的是 4000*0.5 = 2000m。在 Pod 里面我们可以通过下面的两个参数来限制和请求 CPU 资源:
- spec.containers[].resources.limits.cpu:CPU 上限值,可以短暂超过,容器也不会被停止
- spec.containers[].resources.requests.cpu:CPU请求值,Kubernetes 调度算法里的依据值,可以超过
这里需要明白的是,如果resources.requests.cpu设置的值大于集群里每个节点的最大 CPU 核心数,那么这个 Pod 将无法调度,因为没有节点能满足它。
到这里应该明白了,requests 是用于集群调度使用的资源,而 limits 才是真正的用于资源限制的配置,如果你需要保证的你应用优先级很高,也就是资源吃紧的情况下最后再杀掉你的 Pod,那么你就把你的 requests 和 limits 的值设置成一致,在后面应用的 Qos 中会具体讲解。
比如,现在我们定义一个 Pod,给容器的配置如下的资源:(pod-resource-demo1.yaml)
apiVersion: v1
kind: Pod
metadata:
name: resource-demo1
spec:
containers:
- name: resource-demo1
image: nginx
ports:
- containerPort: 80
resources:
requests:
memory: 50Mi
cpu: 50m
limits:
memory: 100Mi
cpu: 100m
这里,CPU 我们给的是 50m,也就是 0.05core,这 0.05 core 也就是占了 1 CPU 里的 5% 的资源时间。而限制资源是给的是 100m,但是需要注意的是 CPU 资源是可压缩资源,也就是容器达到了这个设定的上限后,容器性能会下降,但是不会终止或退出。比如我们直接创建上面这个 Pod:
$ kubectl apply -f pod-resource-demo1.yaml
创建完成后,我们可以看到 Pod 被调度到 node2 这个节点上:
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
resource-demo1 1/1 Running 0 12m 10.244.3.58 node2
然后我们到 node2 节点上去查看 Pod 里面启动的 resource-demo1 这个容器:
$ docker ps |grep resource-demo1
c9e654d573fd nginx "nginx -g 'daemon of…" 14 minutes ago Up 14 minutes k8s_resource-demo1_resource-demo1_default_020bc461-170a-4936-9c22-7c8516972d39_0
37ab54a2490a gcr.azk8s.cn/google_containers/pause:3.1 "/pause" 14 minutes ago Up 14 minutes k8s_POD_resource-demo1_default_020bc461-170a-4936-9c22-7c8516972d39_0
其中第一个容器就是我们的主容器,第二容器是 Infra 容器,我们可以去查看下主容器的信息:
$ docker inspect c9e654d573fd
......
"CpuShares": 51,
"Memory": 104857600,
"NanoCpus": 0,
"CgroupParent": "kubepods-burstable-pod020bc461_170a_4936_9c22_7c8516972d39.slice",
"BlkioWeight": 0,
"BlkioWeightDevice": null,
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 100000,
"CpuQuota": 10000,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DiskQuota": 0,
"KernelMemory": 0,
"MemoryReservation": 0,
"MemorySwap": 104857600,
"MemorySwappiness": null,
"OomKillDisable": false,
......
实际上我们就可以看到这个容器的一些资源情况,Pod 上的资源配置最终也还是通过底层的容器运行时去控制 CGroup 来实现的,我们可以进入如下目录查看 CGroup 的配置,该目录就是 CGroup 父级目录,而 CGroup 是通过文件系统来进行资源限制的,所以我们上面限制容器的资源就可以在该目录下面反映出来:
$ cd /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod020bc461_170a_4936_9c22_7c8516972d39.slice
$ ls
cgroup.clone_children cpu.cfs_period_us docker-37ab54a2490a48c88918f53572e053784238bf3720cb1ae5bf01052040aba9a4.scope
cgroup.event_control cpu.cfs_quota_us docker-c9e654d573fd3e3e9a8bb78f3f904e60a59aa3384b344117fd401529e982ae37.scope
cgroup.procs cpu.rt_period_us notify_on_release
cpuacct.stat cpu.rt_runtime_us tasks
cpuacct.usage cpu.shares
cpuacct.usage_percpu cpu.stat
$ cat cpu.cfs_quota_us
10000
其中 cpu.cfs_quota_us 就是 CPU 的限制值,如果要查看具体的容器的资源,我们也可以进入到容器目录下面去查看即可。
最后我们了解下内存这块的资源控制,内存的单位换算比较简单:
1 MiB = 1024 KiB,内存这块在 Kubernetes 里一般用的是Mi单位,当然你也可以使用Ki、Gi甚至Pi,看具体的业务需求和资源容量。
单位换算
这里注意的是MiB ≠ MB,MB 是十进制单位,MiB 是二进制,平时我们以为 MB 等于 1024KB,其实1MB=1000KB,1MiB才等于1024KiB。中间带字母 i 的是国际电工协会(IEC)定的,走1024乘积;KB、MB、GB是国际单位制,走1000乘积。
这里要注意的是,内存是不可压缩性资源,如果容器使用内存资源到达了上限,那么会OOM,造成内存溢出,容器就会终止和退出。我们也可以通过上面的方式去通过查看 CGroup 文件的值来验证资源限制。
下一篇将介绍Kubernetes中ReplicaSet控制器
(转发请注明出处:http://www.cnblogs.com/zhangyongli2011/ 如发现有错,请留言,谢谢)
Kubernetes Pod(Pod Hook?Pod 健康检查?Pod 资源配置?)(十八)的更多相关文章
- Pod生命周期和健康检查
Pod生命周期和健康检查 Pod的生命周期涵盖了前面所说的PostStart 和 PreStop在内 Pod phase Pod的status定义在 PodStatus对象中,其中有一个phase字段 ...
- 2.k8s.Pod生命周期,健康检查
#Pod生命周期,健康检查 pod创建过程 Init容器 就绪探测 存活探测 生命周期钩子 #Pod创建过程 master节点:kubectl -> kube-api -> kubenle ...
- Docker Kubernetes 健康检查
Docker Kubernetes 健康检查 提供Probe探测机制,有以下两种类型: livenessProbe:如果检查失败,将杀死容器,然后根据Pod的重启策略来决定是否重启. readines ...
- Knative Serving 健康检查机制分析
作者| 阿里云智能事业群技术专家牛秋霖(冬岛) 导读:从头开发一个Serverless引擎并不是一件容易的事情,今天咱们就从Knative的健康检查说起.通过健康检查这一个点来看看Serverles ...
- kubernetes之pod健康检查
目录 kubernetes之pod健康检查 1.概述和分类 2.LivenessProbe探针(存活性探测) 3.ReadinessProbe探针(就绪型探测) 4.探针的实现方式 4.1.ExecA ...
- Kubernetes中Pod的健康检查
本文介绍 Pod 中容器健康检查相关的内容.配置方法以及实验测试,实验环境为 Kubernetes 1.11,搭建方法参考kubeadm安装kubernetes V1.11.1 集群 0. 什么是 C ...
- Kubernetes Pod 健康检查
参考文档: https://jimmysong.io/kubernetes-handbook/guide/configure-liveness-readiness-probes.html 一.Pod的 ...
- Kubernetes中Pod健康检查
目录 1.何为健康检查 2.探针分类 2.1.LivenessProbe探针(存活性探测) 2.2.ReadinessProbe探针(就绪型探测) 3.探针实现方法 3.1.Container Exe ...
- K8s中Pod健康检查源代码分析
了解k8s中的Liveness和Readiness Liveness: 表明是否容器正在运行.如果liveness探测为fail,则kubelet会kill掉容器,并且会触发restart设置的策略. ...
- pod健康检查(liveness probe存活探针&&readiness probe 可读性探针)
在Kubernetes集群当中,我们可以通过配置liveness probe(存活探针)和readiness probe(可读性探针)来影响容器的生存周期.参考文档:https://kubernete ...
随机推荐
- C#从6.0~9.0都更新了什么?
一.C#6中新增的功能 get 只读属性 简洁的语法来创建不可变类型,仅有get访问器: public string FirstName { get; } public string LastName ...
- MySQL 实现 EF Code First TimeStamp/RowVersion 并发控制
在将项目迁移到MySQL 5.6.10数据库上时,遇到和迁移到PostgreSQL数据库相同的一个问题,就是TimeStamp/RowVersion并发控制类型在非Microsoft SQL Serv ...
- Sysbench 使用总结
Sysbench使用总结 实践环境 CentOS 7.8 Sysbench 1.0.20 下载地址:https://github.com/akopytov/sysbench/archive/refs/ ...
- 【Python】GUI开发笔记
一.环境搭建: 1.Pycharm开发工具 pycharm历史版本 https://www.jetbrains.com/pycharm/download/other.html 破解插件 https:/ ...
- 【JavaScript】JQuery-Ztree 演示demo
使用CDN引用JQuery和ZTree的资源 demo页的代码: <!DOCTYPE html> <html lang="en"> <head> ...
- 【Java】【常用类】Date 日期类
java.util.Date java.sql.Date 创建日期对象和打印结果 public class DateTest { public static void main(String[] ar ...
- 【Vue】Re09 Webpack 第一部分(介绍、安装、配置)
一.Webpack的用途 webpack要解决的是统一网页资源的问题 前端工程化出现了很多问题,就是兼容性,浏览器所不能解析 所以需要一个打包,转换等方式处理 二.安装描述介绍 下载安装NodeJS, ...
- 买二手NVIDIA网卡被坑记录:某宝的咸鱼二手交易网站上购入NVIDIA Mellanox ConnectX-3 网卡 居然不支持Windows 11操作系统 —— 老二手40Gbps的NVIDIA网卡已经不被新操作系统支持
原本是打算去大连的人工智能计算中心去做技术负责人的,不过考虑到工作性质再考虑到自己的一些现实情况也就放弃了这个职位(比较在大连理工大学的博士学位还没有读下来,还是有所牵挂的).同时,由于自己已经退出了 ...
- MindSpore1.3.0 GPU pip方式安装 —— Ubuntu18.04系统 (最终安装结果为成功)需要管理员权限,sudo安装
官网地址: https://www.mindspore.cn/install =========================================================== 安 ...
- Java和LWJGL的关于OpenAL的文章
一.OpenAL的原理和基本概念: 1.1 OpenAL的架构 OpenAL的架构同样基于三个核心组件:Context(上下文).Source(声源)和Buffer(缓冲区).Context代表了音频 ...