[K8S监控]-K8S容器pod异常状态监控脚本并推送钉钉告警

1. 监控需求

检测k8s集群中异常状态的pod容器,并通过钉钉告警推送提醒,通过Shell脚本实现。

2. 完整脚本

cat k8s_pod_status_monitor.sh

复制代码
#!/bin/bash
# K8s Pod状态监控钉钉告警脚本
# 作者:LMZF
# 日期:2025-12-15

############################ 配置区域 ############################
# 钉钉机器人webhook地址(必填)
DINGDING_WEBHOOK="https://oapi.dingtalk.com/robot/send?access_token=c8452b88888888888888888888888888888888888888888888888888"

# 钉钉消息中需要包含的关键词(用于安全校验)
DINGDING_KEYWORDS="告警"

# 可选的命名空间过滤(默认检查所有命名空间)
NAMESPACE_FILTER="--all-namespaces"
# NAMESPACE_FILTER="-n default"  # 只检查default命名空间

# 要忽略的命名空间(多个用逗号分隔)
IGNORE_NAMESPACES="kube-system,kube-public"

# 检查间隔(秒)
CHECK_INTERVAL=300

# 日志文件路径
LOG_FILE="/mnt/logs/k8s-pod-monitor.log"

# 集群名称
ClUSTER_NAME='机房测试环境k8s集群'

############################ 函数定义 ############################

# 初始化日志记录
init_log() {
    local log_dir=$(dirname "$LOG_FILE")
    mkdir -p "$log_dir"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 初始化K8s Pod监控脚本" >> "$LOG_FILE"
}

# 记录日志
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}

# 发送钉钉告警
send_dingding_alert() {
    local alert_message="$1"
    local pod_info="$2"

    # 构建钉钉消息格式 [11](@ref)
    local dingding_msg=$(cat << EOF
{
    "msgtype": "markdown",
    "markdown": {
        "title": "K8S Pod状态告警",
        "text": "## ${DINGDING_KEYWORDS} ⚠️\n**告警时间:** $(date '+%Y-%m-%d %H:%M:%S')\n**告警详情:**\n\`\`\`json\n${alert_message}\n\`\`\`\n**异常Pod信息:**\n\`\`\`\n${pod_info}\n\`\`\`\n---\n> 请及时处理"
    },
    "at": {
        "isAtAll": false
    }
}
EOF
    )

    # 发送请求 [10,11](@ref)
    local response=$(curl -s -H "Content-Type: application/json" \
        -d "$dingding_msg" \
        "$DINGDING_WEBHOOK")

    if echo "$response" | grep -q '"errcode":0'; then
        log "钉钉告警发送成功"
        return 0
    else
        log "钉钉告警发送失败: $response"
        return 1
    fi
}

# 检查kubectl配置
check_kubectl_config() {
    if ! command -v /usr/local/bin/kubectl  &> /dev/null; then
        log "错误: kubectl 未找到,请确保已安装并配置"
        exit 1
    fi

    if ! /usr/local/bin/kubectl cluster-info &> /dev/null; then
        log "错误: 无法连接Kubernetes集群,请检查kubectl配置"
        exit 1
    fi

    log "kubectl配置检查通过"
}

# 检查Pod状态
check_pod_status() {
    local abnormal_pods=""
    local pod_count=0

    log "开始检查Pod状态..."

    # 获取Pod状态信息
    while IFS= read -r line; do
        if [ -n "$line" ]; then
            local namespace=$(echo "$line" | awk '{print $1}')
            local pod_name=$(echo "$line" | awk '{print $2}')
            local status=$(echo "$line" | awk '{print $4}')
            local restarts=$(echo "$line" | awk '{print $5}')
            local age=$(echo "$line" | awk '{print $6}')

            # 检查是否在忽略的命名空间中
            if echo ",${IGNORE_NAMESPACES}," | grep -q ",${namespace},"; then
                continue
            fi

            # 检查Pod状态
            #if [ "$status" != "Running" ]; then
            if [ "$status" != "Running" ] && [ "$status" != "Completed" ] ; then
                abnormal_pods="${abnormal_pods}命名空间: $namespace | Pod: $pod_name | 状态: $status | 重启次数: $restarts | 运行时间: $age\n"
                pod_count=$((pod_count + 1))

                # 获取详细事件信息用于告警 
                local events=$(/usr/local/bin/kubectl get events -n "$namespace" --field-selector involvedObject.name="$pod_name" --sort-by='.lastTimestamp' 2>/dev/null | tail -5)
                #abnormal_pods="${abnormal_pods}最近事件:\n$events\n----------------------------------------\n"
            fi
        fi
    done <<< "$(/usr/local/bin/kubectl get pods $NAMESPACE_FILTER --no-headers 2>/dev/null)"

    if [ $pod_count -gt 0 ]; then
        local alert_msg="${ClUSTER_NAME}发现 $pod_count 个Pod状态异常"
        log "$alert_msg"

        # 发送钉钉告警
        send_dingding_alert "$alert_msg" "$abnormal_pods"
    else
        log "所有Pod状态正常"
    fi
}

# 检查Metrics Server是否可用(可选检查)
check_metrics_server() {
    if kubectl top nodes &> /dev/null; then
        log "Metrics Server可用,可以监控资源使用情况"
        return 0
    else
        log "Metrics Server不可用,跳过资源监控"
        return 1
    fi
}

############################ 主程序 ############################

main() {
    # 初始化
    init_log
    log "=== K8s Pod监控脚本启动 ==="

    # 检查配置
    check_kubectl_config
    #check_metrics_server

    # 验证钉钉webhook配置
    if [ -z "$DINGDING_WEBHOOK" ] || [ "$DINGDING_WEBHOOK" = "https://oapi.dingtalk.com/robot/send?access_token=YOUR_ACCESS_TOKEN" ]; then
        log "错误: 请先配置钉钉机器人webhook地址"
        exit 1
    fi

    log "监控程序启动,检查间隔: ${CHECK_INTERVAL}秒"

    # 主循环
    # while true; do
    #     log "开始新一轮检查..."
    check_pod_status
    #    log "本轮检查完成,等待${CHECK_INTERVAL}秒后继续..."
    #    sleep $CHECK_INTERVAL
    #done
}

# 信号处理,优雅退出
# 当脚本运行过程中收到 INT(信号 2) 或 TERM(信号 15) 时,不会立即以默认方式(通常是非零错误码)终止,而是先执行你定义的命令序列,再以状态码0退出。
trap "log '监控脚本被用户中断'; exit 0" INT TERM

# 脚本入口
if [ "$1" = "test" ]; then
    # 测试模式:只运行一次检查
    log "=== 测试模式启动 ==="
    check_kubectl_config
    check_pod_status
    log "=== 测试模式结束 ==="
else
    # 正常模式:持续监控
    main
fi

3. 配置定时任务

根据需求,通过/etc/crontab或crontab -e设置定时任务。脚本中以下几行需注释

复制代码
    # 主循环
    # while true; do
    #     log "开始新一轮检查..."
    check_pod_status
    #    log "本轮检查完成,等待${CHECK_INTERVAL}秒后继续..."
    #    sleep $CHECK_INTERVAL
    #done

若不注释上述几行,可以使用nohup k8s_pod_status_monitor.sh & 执行一次脚本即可。

4. 备注

kubectl尽量使用绝对路径(本文/usr/local/bin/kubectl),避免设置定时任务,执行shell脚本报错。

相关推荐
AllFiles18 分钟前
Kubernetes PVC 扩容全流程实战:从原理到操作详解
后端·kubernetes
放寒假脚后跟v2 小时前
Pod 的 YAML 文件中 exitCode 字段的具体含义、不同取值代表的场景
运维·云原生·容器·kubernetes·k8s
东方佑2 小时前
使用Docker Compose一键部署OnlyOffice:完整指南与配置解析
运维·docker·容器
原神启动12 小时前
K8S(五)—— YAML文件解析
java·容器·kubernetes
lin张2 小时前
k8s(二)项目生命周期管理、发布策略与声明式资源管理
云原生·容器·kubernetes
赵文宇(温玉)2 小时前
Docker的价值、特点、创新与关键技术
运维·docker·容器
Zsr10233 小时前
K8S安装指南与核心操作命令汇总
云原生·容器·kubernetes
孤岛悬城3 小时前
53 k8s基础与安装
云原生·容器·kubernetes
Coder码匠4 小时前
Docker Compose 部署 Spring Boot 应用完全指南
spring boot·docker·容器
可爱又迷人的反派角色“yang”4 小时前
k8s(四)
linux·网络·云原生·容器·kubernetes·云计算