[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脚本报错。

相关推荐
mobº9 小时前
K8s 集群部署微服务 - DevOps(二)
微服务·kubernetes·devops
王老师青少年编程9 小时前
csp信奥赛C++标准模板库STL(3):list的使用详解
c++·容器·stl·list·标准模板库·csp·信奥赛
一条懒鱼66610 小时前
k8s-网络
网络·容器·kubernetes
跟‘码’死磕10 小时前
springboot集成钉钉群内发送消息
java·spring boot·钉钉
silence25010 小时前
k8s集群证书过期--手动更新证书
kubernetes
huahailing102410 小时前
docker 部署 rustfs
运维·docker·容器
运维栈记10 小时前
CKA题目分享-第八篇-StatefulSets与Headless Services
kubernetes·cka
永不停歇的蜗牛11 小时前
K8S中Namespace(ns)、Pod、Service和ConfigMap(cm)四种重要的资源对象的关系
容器·贪心算法·kubernetes
sg_knight11 小时前
Docker Engine 升级指南:保障容器安全的关键步骤
java·spring boot·安全·spring·spring cloud·docker·容器
运维栈记11 小时前
CKA题目分享-第七篇-Gateway API与Pod Admission
kubernetes·cka