容器检测日志不刷新重启pod服务

下面脚本用于检测指定命名空间下以svc-pod-*开头的Pod日志是否停止更新,并在不更新时重启对应Pod。集群服务如果时间戳一直获取不到,可能是日志中​​无时间戳​​、​​时间戳格式不匹配​​或​​日志获取方式问题​​导致。以下是针对性的排查步骤和优化脚本,帮助解决问题。

  • 确认日志中是否包含时间戳
 kubectl logs -n namespace svc-pod-xxxxxx --tail=20

优化脚本:兼容无时间戳/时间戳格式不确定场景​

#!/bin/bash

# 配置参数
NAMESPACE="namespace"
WAIT_TIME=10          # 检测间隔(秒)
LOG_CMP_LINES=50      # 对比日志的行数(取最后N行对比)
MAX_LOG_AGE=30        # 日志无更新的最大允许时间(秒,仅当有时间戳时生效)
TIMEZONE="Asia/Shanghai"  # 服务器时区(与日志时间戳时区一致)

# 临时设置时区(确保date命令按指定时区解析)
export TZ="$TIMEZONE"

# 获取所有符合通配符的Pod名称(svc-pod-*)
pods=$(kubectl get pods -n "$NAMESPACE" -o jsonpath='{.items[*].metadata.name}' 2>/dev/null | tr ' ' '\n' | grep '^svc-pod-')

# 无目标Pod时退出
if [ -z "$pods" ]; then
    echo "No pods matching 'svc-pod-*' found in namespace: $NAMESPACE"
    exit 0
fi

# 遍历每个Pod检测
for pod in $pods; do
    echo "===== Checking pod: $pod ====="

    # 检查Pod状态是否为Running(非Running状态跳过)
    pod_status=$(kubectl get pod -n "$NAMESPACE" "$pod" -o jsonpath='{.status.phase}' 2>/dev/null)
    if [ "$pod_status" != "Running" ]; then
        echo "Pod status is $pod_status (not Running), skip."
        continue
    fi

    # --------------------------
    # 步骤1:尝试提取日志时间戳(优先)
    # --------------------------
    log_has_timestamp=false
    last_log_line=$(kubectl logs -n "$NAMESPACE" "$pod" --tail=20 2>/dev/null)  # 获取最后20行日志(避免缓冲)
    if [ -n "$last_log_line" ]; then
        # 尝试匹配常见时间戳格式(可根据实际日志调整正则)
        # 示例1:[2025-08-21 11:22:12] 或 [2025-08-21T11:22:12+08:00]
        timestamp_regex='\[[0-9]{4}-[0-9]{2}-[0-9]{2}(T| )[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?([+-][0-9]{2}:[0-9]{2}|Z)?\]'
        # 示例2:08/21/2025 11:22:12
        # timestamp_regex='\[[0-9]{2}/[0-9]{2}/[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}\]'

        # 提取时间戳字符串(取最后一个匹配项)
        last_log_time_str=$(echo "$last_log_line" | grep -oE "$timestamp_regex" | tail -n 1 | tr -d '[]')
        if [ -n "$last_log_time_str" ]; then
            log_has_timestamp=true
            # 转换时间戳为秒级(兼容含毫秒/时区的格式)
            last_epoch=$(date -d "$(echo "$last_log_time_str" | sed 's/\.[0-9]\+//g; s/[+-][0-9]\{2\}:[0-9]\{2\}//g')" +%s 2>/dev/null)
            if [ -z "$last_epoch" ]; then
                echo "Warning: Failed to parse timestamp '$last_log_time_str', fallback to content check."
                log_has_timestamp=false
            else
                current_epoch=$(date +%s)
                time_diff=$((current_epoch - last_epoch))
                echo "Last log timestamp: $last_log_time_str (age: ${time_diff}s)"
            fi
        fi
    fi

    # --------------------------
    # 步骤2:根据是否获取到时间戳选择检测方式
    # --------------------------
    if [ "$log_has_timestamp" = true ]; then
        # 方式1:基于时间戳检测(日志有时间戳但解析成功)
        if [ "$time_diff" -gt "$MAX_LOG_AGE" ]; then
            echo "Pod logs not updated for ${time_diff}s (exceed ${MAX_LOG_AGE}s), restart: $pod"
            kubectl delete pod -n "$NAMESPACE" "$pod" --grace-period=0 --force
            continue
        else
            echo "Pod logs updated recently (${time_diff}s ago)."
            continue
        fi
    else
        # 方式2:基于日志内容变化检测(无时间戳或解析失败)
        echo "No valid timestamp found in logs, fallback to content change check."

        # 获取初始日志的最后N行(增加--tail避免缓冲)
        initial_logs=$(kubectl logs -n "$NAMESPACE" "$pod" --tail="$LOG_CMP_LINES" 2>/dev/null)
        if [ -z "$initial_logs" ]; then
            echo "Pod has no logs, restart: $pod"
            kubectl delete pod -n "$NAMESPACE" "$pod" --grace-period=0 --force
            continue
        fi

        # 等待一段时间(让日志有机会更新)
        echo "Waiting $WAIT_TIME seconds for log update..."
        sleep "$WAIT_TIME"

        # 获取等待后的日志最后N行
        current_logs=$(kubectl logs -n "$NAMESPACE" "$pod" --tail="$LOG_CMP_LINES" 2>/dev/null)
        if [ -z "$current_logs" ]; then
            echo "Pod has no new logs, restart: $pod"
            kubectl delete pod -n "$NAMESPACE" "$pod" --grace-period=0 --force
            continue
        fi

        # 对比日志是否有变化(忽略末尾空行)
        if [ "$(echo "$initial_logs" | sed '/^$/d')" = "$(echo "$current_logs" | sed '/^$/d')" ]; then
            echo "Pod logs not updated (last $LOG_CMP_LINES lines same), restart: $pod"
            kubectl delete pod -n "$NAMESPACE" "$pod" --grace-period=0 --force
        else
            echo "Pod logs updated normally."
        fi
    fi
done

echo "===== Detection completed ====="

确保执行脚本的环境已配置kubectl且能正常访问Kubernetes集群。
脚本需有足够权限(如cluster-admin或对应角色的get pods、delete pods权限)

使用方式:

  1. 保存脚本为check_pod_logs.sh。
  2. 赋予执行权限:chmod +x check_pod_logs.sh。
  3. 执行脚本:./check_pod_logs.sh。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三朝看客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值