基于prometheus的k8s集群监控指标测试和k8s-event事件的监控
转载自博客:
在我们的 Kuberenetes 集群中,我们偶尔会遇到集群节点内存不足并且 Linux 调用 OOM killer 的情况。查看日志,似乎调度到节点上的 Pod 正在请求比节点可以分配的内存更多的内存。
问题是,当 OOM killer 被调用时,它会打印出进程列表及其内存使用情况。但是,由于我们所有的 Docker 容器都是 Java 服务,因此“进程名称”仅显示为“java”,无法让我们追踪是哪个特定 Pod 导致了问题。
我如何获取计划在特定节点上运行哪些 Pod 以及何时运行的历史记录?
https://blog.csdn.net/kozazyh/article/details/111770462
事件监控
Kubernetes事件是可以深入了解集群内部事件的对象,例如调度程序做出了哪些决定或为什么从节点上驱逐了某些Pod。
事件监控是Kubernetes中的另一种监控方式,可以弥补资源监控在实时性、准确性和场景上的缺欠。开发者可以通过获取事件,实时诊断集群的异常与问题。
在Kubernetes中,事件分为两种,一种是Warning事件,表示产生这个事件的状态转换是在非预期的状态之间产生的;另外一种是Normal事件,表示期望到达的状态,和目前达到的状态是一致的。我们用一个Pod的生命周期进行举例,当创建一个Pod的时候,首先Pod会进入Pending的状态,等待镜像的拉取,当镜像录取完毕并通过健康检查的时候,Pod的状态就变为Running,此时会生成Normal的事件。而如果在运行中,由于OOM或者其他原因造成Pod宕掉,进入Failed的状态,而这种状态是非预期的,那么此时会在Kubernetes中产生Warning的事件。那么针对这种场景而言,如果我们能够通过监控事件的产生就可以非常及时的查看到一些容易被资源监控忽略的问题。
容器 OOMKilled 事件没有记录在事件中(issue)的补救方案:
可以使用 prometheus对OOMkilled POD 发出报警:
sum_over_time(kube_pod_container_status_terminated_reason{reason="OOMKilled"}[5m]) > 0
事件监控
Kubernetes事件是可以深入了解集群内部事件的对象,例如调度程序做出了哪些决定或为什么从节点上驱逐了某些Pod。
事件监控是Kubernetes中的另一种监控方式,可以弥补资源监控在实时性、准确性和场景上的缺欠。开发者可以通过获取事件,实时诊断集群的异常与问题。
在Kubernetes中,事件分为两种,一种是Warning事件,表示产生这个事件的状态转换是在非预期的状态之间产生的;另外一种是Normal事件,表示期望到达的状态,和目前达到的状态是一致的。我们用一个Pod的生命周期进行举例,当创建一个Pod的时候,首先Pod会进入Pending的状态,等待镜像的拉取,当镜像录取完毕并通过健康检查的时候,Pod的状态就变为Running,此时会生成Normal的事件。而如果在运行中,由于OOM或者其他原因造成Pod宕掉,进入Failed的状态,而这种状态是非预期的,那么此时会在Kubernetes中产生Warning的事件。那么针对这种场景而言,如果我们能够通过监控事件的产生就可以非常及时的查看到一些容易被资源监控忽略的问题。
背景信息
Kubernetes的架构设计基于状态机,不同的状态之间进行转换则会生成相应的事件,正常的状态之间转换会生成Normal等级的事件,正常状态与异常状态之间的转换会生成Warning等级的事件。
由于事件是API对象,因此它们存储在master上的apiserver中。为避免填满主磁盘,将执行保留策略:在上次发生事件后一小时删除事件。
我们希望能够在时间轴上看到kuberentes集群发生的所有各种情况,包括何时发现节点已死,何时添加新节点,何时pod崩溃以及何时重新启动。
到目前为止,我们发现的最好的方法是,kubectl get event --watch,
但这似乎有一些限制:
- 它没有回到过去那么长时间(我不确定它回到过去多少天。)
- 它结合了类似的事件,并按每个组中最新事件的时间对结果列表进行排序。由于该范围内的事件可能已与该范围外的后续事件合并,因此无法知道在某个时间范围内发生了什么。
kube-eventer
kube-eventer:是ACK维护的开源Kubernetes事件离线工具,可以将集群的事件离线到Elasticsearch、钉钉、微信等系统,并提供不同等级的过滤条件,实现事件的实时采集、定向告警、异步归档。
node-problem-detecto
node-problem-detector:是Kubernetes节点诊断的工具,可以将节点的异常,例如Docker Engine Hang、Linux Kernel Hang、网络出网异常、文件描述符异常转换为Node的事件,集合kube-eventer可以实现节点事件告警的闭环。
容器 OOMKilled 事件没有记录在事件中(issue)的补救方案:
可以使用 prometheus对OOMkilled POD 发出报警:
sum_over_time(kube_pod_container_status_terminated_reason{reason="OOMKilled"}[5m]) > 0
参考:
aliyun 解决方案:
https://github.com/AliyunContainerService/kube-eventer
https://github.com/AliyunContainerService/node-problem-detector
k8s官方解决方案:
https://github.com/kubernetes/node-problem-detector
Google Kubernetes 解决方案:
https://kubernetes.io/docs/tasks/debug-application-cluster/events-stackdriver/
容器 OOMKilled 事件没有记录在事件中:
https://github.com/kubernetes/kubernetes/issues/69676
转载自博客:https://blog.csdn.net/qq_42997214/article/details/83418535
测试目标:pod crash
如何模拟:
因为pod crash状态表明容器已启动,但又遭遇异常退出。所以,我们只需要启动的容器中,没有守护进程或是守护进程执行后退出即可。
测试过程:
首先,选择一个没有守护进程的镜像,比如centos基础镜像。
创建deployment,让k8s,根据deployment,启动pod,pod中的容器,使用不带守护进程的镜像。具体的deployment如下:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: test-crash
namespace: test
spec:
selector:
matchLabels:
business: monitoring
project: prometheus-jjj
template:
metadata:
labels:
business: monitoring
project: prometheus-jjj
spec:
containers:
- image: hub.mfwdev.com/base/centos:7.5.1804
imagePullPolicy: IfNotPresent
name: prometheus
nodeSelector:
size: large
restartPolicy: Always
操作过程:
// 创建deployement
kubectl apply -f test-crash.yaml
观察pod状态:
// 查看pod列表
kubectl get pod -n test
// 输出内容如下:
NAME READY STATUS RESTARTS AGE
test-crash-685757d55d-d9ckt 0/1 Completed 1 4s
// 这个pod,最开始变为 completed,表明容器以执行完成(因为没有守护进程,容器启动后,就会变为完成状态)
//再次观察pod
kubectl get pod -n test
// 输出内容如下:
NAME READY STATUS RESTARTS AGE
test-crash-685757d55d-d9ckt 0/1 CrashLoopBackOff 1 6s
// 此时,状态变为 CrashLoopBackOff,是因为k8s不允许pod销毁,会再次创建容器,如此往复,就是 pod crash 的过程。
观察Prometheus的告警状态:
图示,说明:
①:Prometheus中的 KubernetesPodCrash 栏,变为红色(也就是触发了告警)。
②:红色标记了 pod的名称,正是我们之前创建出来的pod名称。
③:由于pod触发Prometheus的告警rules,所以导致Prometheus发出告警,Prometheus告警表达式:
expr: changes(kube_pod_container_status_restarts_total{job!=""}[3m]) > 0
综上,验证通过。
测试目标:pod 未运行
如何模拟:
因为pod 未运行状态表明可能是集群内所有的node都不满足该pod请求的所需资源,导致pod无法正确调度。所以,我们只需要使创建的容器不能正常调度到node节点上即可。
测试过程:
首先,在deployment描述文件中定义一个不存在的标签,比如largexxxx。
创建deployment,让k8s,根据deployment,启动pod,具体的deployment如下:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: test-inactive
namespace: test
spec:
selector:
matchLabels:
business: monitoring
project: prometheus-jjj
template:
metadata:
labels:
business: monitoring
project: prometheus-jjj
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: prometheus
nodeSelector:
size: largexxxxx
restartPolicy: Always
操作过程:
//创建deployment
kubectl apply -f test-inactive.yaml
观察pod状态:
//查看pod列表
[root@node4 test]# kubectl get pods -n test
//输出内容如下:
NAME READY STATUS RESTARTS AGE
test-inactive-85c8b87497-lsjhd 0/1 Pending 0 23s
//pod处于Pending状态,是因为没有符合它所需要调度到带有largexxxxx标签的node节点,所以,它一直处于等待调度状态。
观察Prometheus的告警状态:
图示,说明:
①:Prometheus中的KubernetesPodNotRunning变为红色(已触发告警)。
②:图中标记pod名称,正是我们所创建的pod名称。
③:由于pod触发Prometheus的告警rules,所以导致Prometheus发出告警,Prometheus告警表达式:
expr: kube_pod_status_phase{phase!="Failed",phase!="Running",phase!="Succeeded"}
== 1
综上,验证通过。
测试目标:pod ooM
如何模拟:
因为pod oom状态表明pod中容器的使用超出它本身限制的内存,导致内存不足,从而引发 oom(out of memory)现象。因此,我们只需给启动的容器分配一个超出它本身限制的内存大小即可。
首先,给容器分配一个超出pod内存限制的内存。如pod内存限制为100,分配250M的内存。
创建deployment,让k8s,根据deployment,启动pod,具体的deployment如下:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
test-app: oom
name: testoom
namespace: test
spec:
replicas: 1
selector:
matchLabels:
test-app: oom
template:
metadata:
labels:
test-app: oom
spec:
containers:
- image: polinux/stress
imagePullPolicy: IfNotPresent
name: testoom
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]
resources:
limits:
memory: 100Mi
requests:
memory: 50Mi
dnsPolicy: ClusterFirst
nodeSelector:
size: large
restartPolicy: Always
操作过程:
//创建Deployment
kubectl apply -f test-oom.yaml
观察pod状态:
//查看pod列表
[root@node4 test]# kubectl get pods -n test
//输出内容如下
NAME READY STATUS RESTARTS AGE
testoom-6dd567f54c-v686c 0/1 CrashLoopBackOff 1 36s
//pod处于CrashLoopBackOff状态,是由于给容器分配250M的内存超过了100M的内存限制,导致内存不足,从而导致容器停止运行。
观察Prometheus告警:
图示,说明:
①:Prometheus中的KubernetesPodOOMKill变为红色(已触发告警)。
②:图中标记pod名称,正是我们所创建的pod名称。
③:由于pod触发Prometheus的告警rules,所以导致Prometheus发出告警,Prometheus告警表达式:
expr: changes(kube_pod_container_status_terminated_reason{reason="OOMKilled"}[1m]) > 0
综上,验证通过。
测试目标:容器使用的磁盘
如何模拟:
当容器磁盘使用超过规定的时候,便会触发告警。因此,我们在Prometheus告警rules中添加一条磁盘使用的规则即可。
首先,我们在Prometheus rules中添加一条容器磁盘占用超过15G便触发告警的规则,具体规则如下:
- alert: K8SContainerDiakPressure
expr: (container_fs_usage_bytes{image!=""}) > 16106127360
for: 1m
labels:
service: kubernetes
severity: warning
source: prometheus_dev
alert_type: container
microservice: bistag
operation: bistag
annotations:
summary: "K8S container `{{$labels.container_label_io_kubernetes_pod_namespace}}/{{$labels.kubernetes_container_name}}` 占用超过15GB"
description: "K8S container `{{$labels.container_label_io_kubernetes_pod_namespace}}/{{$labels.kubernetes_container_name}}` 在近1m内,占用超过15GB"
操作过程:
//添加规则后,再次创建Deployment,使规则生效
kubectl apply -f prometheus-rules.cm.yaml
观察Prometheus告警:
图示,说明:
①:Prometheus中的K8sContainerDiskPressure变为红色(已触发告警)。
②:图中标记,正是满足触发条件的容器磁盘的使用量。
③:由于pod触发Prometheus的告警rules,所以导致Prometheus发出告警,Prometheus告警表达式:
expr: (container_fs_usage_bytes{image!=""}) > 1.610612736e+10
综上,验证通过。
————————————————
版权声明:本文为CSDN博主「我家有羊羊喔」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42997214/article/details/83418535
posted on 2023-07-19 21:27 luzhouxiaoshuai 阅读(1112) 评论(0) 编辑 收藏 举报