概述 本文介绍一个轻量级的 Kubernetes 资源监控脚本,定期检测节点和 Pod 的 CPU、内存使用情况,超过阈值时通过企业微信 Webhook 发送告警通知。
核心功能:
🔍 节点资源监控(CPU/内存) 📦 Pod 资源监控(CPU/内存) 📢 企业微信告警推送 ⚙️ 阈值可配置 🔄 定时任务执行 适用场景:
轻量级资源监控 快速告警通知 开发测试环境 补充监控方案 脚本完整代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 #!/usr/bin/env bash webhookurl=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY_HERE if [ -z "$1 " ]; then echo "Usage: $0 <namespace>" exit 1 else nameSpace=$1 fi cpuVPT=85 memVPT=85 podCpuVPT=500 podMemVPT=500 overVPTNodes=() overVPTPods=() nodeViewMsg="" podViewMsg="" nodeMsg="### <font color='warning'>机器资源警告: </font>\n > node: <font color='info'>" '$NODE_NAME' "</font>\n > cpu: <font color='comment'>" '$NODE_CPU' "</font>\n > 内存: <font color='comment'>" '$NODE_MEM' "</font>" podMsg="### <font color='warning'>Pod资源警告: </font>\n > namespace: <font color='info'>" '$NAME_SPACE' "</font>\n > pod: <font color='info'>" '$POD_NAME' "</font>\n > cpu: <font color='comment'>" '$POD_CPU' "</font>\n > 内存: <font color='comment'>" '$POD_MEM' "</font>" nodesStatus=$(kubectl top nodes | awk '{if (NR>1){print $1,$3,$5}}' | tr "\r\n" "|" | tr " " "," ) nodesStatus=(${nodesStatus//|/ } ) for ((i = 0 ; i < ${#nodesStatus[@]} ; i++)); do node=${nodesStatus[i]//%/} node=(${node//,/ } ) if [[ "${node[1]} " =~ ^[0-9]+$ ]] && [[ "${node[2]} " =~ ^[0-9]+$ ]]; then if [ "${node[1]} " -ge ${cpuVPT} ] || [ "${node[2]} " -ge ${memVPT} ]; then overVPTNodes+=(${nodesStatus[i]} ) fi fi done podsStatus=$(kubectl top pod -n "${nameSpace} " | awk '{if (NR>1){print $1,$2,$3}}' | tr "\r\n" "|" | tr " " "," ) podsStatus=(${podsStatus//|/ } ) for ((i = 0 ; i < ${#podsStatus[@]} ; i++)); do pod=${podsStatus[i]//m/} pod=${pod//Mi/} pod=(${pod//,/ } ) if [ "${pod[1]} " -ge ${podCpuVPT} ] || [ "${pod[2]} " -ge ${podMemVPT} ]; then echo "当前 Pod 资源已超过阈值 -- ${pod[0]} " overVPTPods+=(${podsStatus[i]} ) fi done for ((i = 0 ; i < ${#overVPTNodes[@]} ; i++)); do node=${overVPTNodes[i]} nodes=(${node//,/ } ) nodeViewMsg=$nodeViewMsg "\n\n" $(echo ${nodeMsg} | \ sed "s/\$NODE_NAME/${nodes[0]} /g" | \ sed "s/\$NODE_CPU/${nodes[1]} /g" | \ sed "s/\$NODE_MEM/${nodes[2]} /g" ) done for ((i = 0 ; i < ${#overVPTPods[@]} ; i++)); do pod=${overVPTPods[i]} pods=(${pod//,/ } ) podViewMsg=$podViewMsg "\n\n" $(echo ${podMsg} | \ sed "s/\$NAME_SPACE/${nameSpace} /g" | \ sed "s/\$POD_NAME/${pods[0]} /g" | \ sed "s/\$POD_CPU/${pods[1]} /g" | \ sed "s/\$POD_MEM/${pods[2]} /g" ) done podViewMsg=${podViewMsg:0:4000} if [[ -n $nodeViewMsg ]]; then curl --location --request POST "${webhookurl} " \ --header 'Content-Type: application/json' \ --data '{ "msgtype":"markdown", "markdown":{ "content":"' "${nodeViewMsg} " '" } }' fi if [[ -n $podViewMsg ]]; then curl --location --request POST "${webhookurl} " \ --header 'Content-Type: application/json' \ --data '{ "msgtype":"markdown", "markdown":{ "content":"' "${podViewMsg} " '" } }' fi
使用说明 前置条件 1. 安装 kubectl
1 2 3 4 5 kubectl version --client kubectl get nodes
2. 获取企业微信 Webhook URL
1 2 3 4 1. 登录企业微信管理后台 2. 进入「应用与小程序」→「自建」 3. 创建机器人,获取 Webhook URL 4. 格式:https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY
配置脚本 1. 保存脚本
1 2 3 4 vi /opt/scripts/k8s-monitor.sh
2. 修改配置
1 2 3 4 5 6 7 8 webhookurl=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_REAL_KEY cpuVPT=85 memVPT=85 podCpuVPT=500 podMemVPT=500
3. 添加执行权限
1 chmod +x /opt/scripts/k8s-monitor.sh
手动执行 1 2 3 4 5 6 7 8 /opt/scripts/k8s-monitor.sh default /opt/scripts/k8s-monitor.sh production bash -x /opt/scripts/k8s-monitor.sh default
定时任务配置 方案1:使用 Crontab
1 2 3 4 5 6 7 8 9 10 11 crontab -e */5 * * * * /opt/scripts/k8s-monitor.sh default >> /var/log/k8s-monitor.log 2>&1 */10 * * * * /opt/scripts/k8s-monitor.sh production >> /var/log/k8s-monitor-prod.log 2>&1 crontab -l
方案2:使用 Kubernetes CronJob
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 apiVersion: batch/v1 kind: CronJob metadata: name: k8s-monitor namespace: kube-system spec: schedule: "*/5 * * * *" jobTemplate: spec: template: spec: serviceAccountName: k8s-monitor-sa containers: - name: monitor image: bitnami/kubectl:latest command: - /bin/sh - -c - | # 脚本内容(省略,与上面相同) restartPolicy: OnFailure --- apiVersion: v1 kind: ServiceAccount metadata: name: k8s-monitor-sa namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: k8s-monitor-role rules: - apiGroups: ["" ] resources: ["nodes" , "pods" ] verbs: ["get" , "list" ] - apiGroups: ["metrics.k8s.io" ] resources: ["nodes" , "pods" ] verbs: ["get" , "list" ] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: k8s-monitor-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: k8s-monitor-role subjects: - kind: ServiceAccount name: k8s-monitor-sa namespace: kube-system
告警示例 节点告警 企业微信消息效果:
1 2 3 4 5 6 7 8 9 ### 机器资源警告: > node: k3s-node1 > cpu: 92% > 内存: 88% ### 机器资源警告: > node: k3s-node2 > cpu: 86% > 内存: 75%
Pod 告警 1 2 3 4 5 6 7 8 9 10 11 ### Pod资源警告: > namespace: production > pod: nginx-deployment-abc123 > cpu: 850m > 内存: 1024Mi ### Pod资源警告: > namespace: production > pod: mysql-statefulset-0 > cpu: 450m > 内存: 2048Mi
脚本解析 核心逻辑 1. 数据获取
1 2 3 4 5 6 kubectl top nodes | awk '{if (NR>1){print $1,$3,$5}}'
2. 数据转换
3. 阈值判断
1 2 3 4 5 6 7 if [[ "${node[1]} " =~ ^[0-9]+$ ]]; then if [ "${node[1]} " -ge ${cpuVPT} ]; then fi fi
4. 消息构建
1 2 3 4 5 echo ${nodeMsg} | \ sed "s/\$NODE_NAME/${nodes[0]} /g" | \ sed "s/\$NODE_CPU/${nodes[1]} /g" | \ sed "s/\$NODE_MEM/${nodes[2]} /g"
关键技巧 数组操作:
1 2 3 4 5 6 7 array+=(element) for ((i = 0 ; i < ${#array[@]} ; i++)); do echo ${array[i]} done
字符串处理:
1 2 3 4 5 6 7 string=${string//%/} string=${string//m/} string=${string//Mi/} arr=(${string//,/ } )
正则匹配:
1 2 3 4 if [[ "$var " =~ ^[0-9]+$ ]]; then echo "是数字" fi
优化建议 功能增强 1. 添加日志记录
1 2 3 4 5 6 7 LOG_FILE="/var/log/k8s-monitor.log" echo "[$(date '+%Y-%m-%d %H:%M:%S') ] 开始监控" >> ${LOG_FILE} echo "[$(date '+%Y-%m-%d %H:%M:%S') ] 节点超阈值: ${#overVPTNodes[@]} " >> ${LOG_FILE} echo "[$(date '+%Y-%m-%d %H:%M:%S') ] Pod超阈值: ${#overVPTPods[@]} " >> ${LOG_FILE}
2. 添加错误处理
1 2 3 4 5 6 7 nodesStatus=$(kubectl top nodes 2>&1) if [ $? -ne 0 ]; then echo "Error: kubectl top nodes failed" echo "$nodesStatus " exit 1 fi
3. 支持多命名空间
1 2 3 4 5 6 7 namespaces=("default" "production" "staging" ) for ns in "${namespaces[@]} " ; do echo "Monitoring namespace: $ns " done
4. 告警去重
1 2 3 4 5 6 7 8 9 10 11 ALERT_FILE="/tmp/k8s-alerts.txt" if grep -q "${node[0]} " ${ALERT_FILE} ; then continue fi echo "${node[0]} $(date +%s) " >> ${ALERT_FILE}
5. 清理过期告警记录
1 2 3 4 5 6 7 8 9 current_time=$(date +%s) while IFS= read -r line; do alert_time=$(echo $line | awk '{print $2}' ) if [ $((current_time - alert_time)) -lt 3600 ]; then echo $line >> ${ALERT_FILE} .tmp fi done < ${ALERT_FILE} mv ${ALERT_FILE} .tmp ${ALERT_FILE}
性能优化 1. 减少 kubectl 调用
1 2 3 4 5 6 kubectl top nodes > /tmp/nodes.txt kubectl top pods -n ${nameSpace} > /tmp/pods.txt nodesStatus=$(cat /tmp/nodes.txt | awk ...)
2. 并行处理
1 2 3 4 5 for ns in "${namespaces[@]} " ; do monitor_namespace $ns & done wait
最佳实践 生产环境建议 建议 说明 ✅ 阈值调整 根据实际情况调整阈值 ✅ 日志轮转 配置日志轮转,避免占满磁盘 ✅ 错误处理 添加完善的错误处理逻辑 ✅ 告警去重 避免重复告警骚扰 ✅ 定期清理 清理临时文件和过期告警
监控方案对比 方案 优点 缺点 适用场景 本脚本 轻量、快速部署 功能有限 开发/测试环境 Prometheus + Grafana 功能强大、可视化 部署复杂 生产环境 云厂商监控 托管服务、免运维 成本较高 云上环境
注意事项 限制与不足:
1 2 3 4 5 ⚠️ 仅监控资源使用,不监控服务健康 ⚠️ 告警消息长度限制(4000字符) ⚠️ 依赖 kubectl top(需要 metrics-server) ⚠️ 无告警历史记录和统计 ⚠️ 无告警升级和降级机制
改进方向:
1 2 3 4 5 ✅ 集成更专业的监控系统 ✅ 添加更多监控维度 ✅ 实现告警管理功能 ✅ 提供可视化界面 ✅ 支持更多通知渠道
总结 适用场景:
1 2 3 4 ✅ 快速搭建轻量级监控 ✅ 开发测试环境告警 ✅ 补充现有监控方案 ✅ 学习 Shell 脚本编程
核心价值:
🚀 快速部署,5分钟上线 💰 零成本,纯脚本实现 🔧 易维护,代码简单清晰 📢 及时告警,企业微信推送 最终建议:
本脚本适合作为临时或补充方案。生产环境建议使用 Prometheus + Grafana + Alertmanager 等成熟监控系统。