K8s集群运行时异常趋势分析预警实操

K8s集群运行时异常趋势分析预警实操

|--------|------------------------------------------------------------------------------------|
| 项目 | 内容 |
| 适用版本 | Kubernetes v1.28.15 + Prometheus 2.48 + Grafana 10.2 + Loki 2.9 + containerd 1.7.x |
| 核心目标 | 运行时异常实时感知、趋势预测、容量预警、自动化应急响应 |
| 编写日期 | 2026-08-18 |
| 文档版本 | v1.0 |

1. 操作环境与前置准备

1.1 硬件要求

|--------|---------|--------|-----------|-------------------------|
| 角色 | CPU | 内存 | 硬盘 | 说明 |
| Worker | 8核+ | 16GB+ | 200GB SSD | 业务节点 |
| 监控节点 | 8核+ | 16GB+ | 500GB SSD | Prometheus+Grafana+Loki |
| 告警节点 | 4核+ | 8GB+ | 100GB SSD | Alertmanager(可复用监控节点) |

监控节点建议独立部署,避免监控组件与业务争抢资源。大规模集群(50+节点)需独立部署。

1.2 软件版本矩阵

|-----------------------|----------|-----------|
| 组件 | 版本 | 说明 |
| Kubernetes | v1.28.15 | 集群版本 |
| containerd | 1.7.11+ | 容器运行时 |
| Prometheus | 2.48.0+ | 指标存储与告警 |
| Alertmanager | 0.26.0+ | 告警路由通知 |
| Grafana | 10.2.0+ | 可视化看板 |
| Loki | 2.9.0+ | 日志聚合分析 |
| Promtail | 2.9.0+ | 日志采集器 |
| node-exporter | 1.7.0+ | 节点指标采集 |
| kube-state-metrics | 2.10.0+ | K8s资源状态指标 |
| kube-prometheus-stack | 最新 | 一键部署(可选) |

1.3 节点规划

|--------------|---------------|--------|--------------------------------------|
| 主机名 | IP地址 | 角色 | 部署组件 |
| k8s-worker01 | 192.168.10.21 | Worker | 业务Pod + node-exporter |
| k8s-worker02 | 192.168.10.22 | Worker | 业务Pod + node-exporter |
| k8s-worker03 | 192.168.10.23 | Worker | 业务Pod + node-exporter |
| k8s-monitor | 192.168.10.40 | 监控 | Prometheus/Grafana/Loki/Alertmanager |

1.4 存储规划

|--------------|----------|----------|--------------------|
| 数据类型 | 保留周期 | 预估存储 | 存储路径 |
| Loki日志 | 7天 | 200GB+ | /data/loki |
| Alertmanager | 永久 | <1GB | /data/alertmanager |
| Grafana | 永久 | <10GB | /data/grafana |

2. 运行时异常监控体系架构

2.1 异常分类与监控维度

|----------|--------------|--------------------------------|----------|
| 异常类别 | 监控对象 | 关键指标 | 预警级别 |
| 资源耗尽 | CPU/内存/磁盘/网络 | 使用率、趋势斜率、预测值 | P1/P2 |
| Pod异常 | 容器状态 | CrashLoopBackOff、OOMKilled、重启率 | P1/P2 |
| 网络异常 | 连接/丢包/延迟 | conntrack使用率、丢包率、TCP重传 | P1/P2 |
| 存储异常 | 磁盘/IO | 磁盘使用率、IO等待、inode | P1/P2 |
| 调度异常 | 调度器 | 调度失败数、Pending Pod数 | P2 |
| 应用异常 | 业务容器 | 错误率、延迟、5xx比例 | P1/P2 |

2.2 整体架构

┌──────────────────────────────────────────────────────────────────┐
│ K8s Cluster │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Worker1 │ │ Worker2 │ │ Worker3 │ │ Master │ │
│ │node-exp │ │node-exp │ │node-exp │ │kubelet │ │
│ │promtail │ │promtail │ │promtail │ │metrics │ │
│ │cAdvisor │ │cAdvisor │ │cAdvisor │ │ │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
│ └──────────────┼──────────────┼──────────────┘ │
│ │ │ │
│ metrics │ logs │ │
│ ▼ ▼ │
│ ┌──────────────────────────┐ ┌──────────────────┐ │
│ │ Prometheus │ │ Loki │ │
│ │ (指标存储+告警规则) │ │ (日志聚合分析) │ │
│ └──────────┬───────────────┘ └────────┬─────────┘ │
│ │ alerts │ logs │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Alertmanager │ │ Grafana │ │
│ │ (路由/通知/抑制) │◄──────►│ (可视化看板) │ │
│ └────────┬─────────┘ └──────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ 钉钉/企微/邮件 │ │
│ └──────────────────┘ │
└──────────────────────────────────────────────────────────────────┘

2.3 数据流转链路

采集层 存储层 分析层 通知层
───────── ───────── ───────── ─────────
node-exporter → Prometheus → 告警规则引擎 → Alertmanager → 钉钉
kubelet → Prometheus → 趋势预测模型 → Alertmanager → 企微
cAdvisor → Prometheus → 异常检测算法 → Grafana看板 → 邮件
Promtail → Loki → 日志关键字匹配 → 告警联动 → 短信
kube-state → Prometheus → 资源状态分析 → 容量预警

3. 指标监控采集部署

3.1 Prometheus部署

创建命名空间和配置:

kubectl create namespace monitoring

创建 prometheus-config.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: monitoring
data:
prometheus.yml: |
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
cluster: k8s-prod

alerting:
alertmanagers:

  • static_configs:
  • targets:
  • alertmanager.monitoring.svc.cluster.local:9093

rule_files:

  • /etc/prometheus/rules/*.yml

scrape_configs:

Prometheus自身

  • job_name: 'prometheus'
    static_configs:
  • targets: 'localhost:9090'

node-exporter

  • job_name: 'node-exporter'
    kubernetes_sd_configs:
  • role: endpoints
    relabel_configs:
  • source_labels: __meta_kubernetes_service_name
    regex: node-exporter
    action: keep

kubelet

  • job_name: 'kubelet'
    kubernetes_sd_configs:
  • role: node
    scheme: https
    tls_config:
    ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
    relabel_configs:
  • action: labelmap
    regex: _meta_kubernetes_node_label(.+)

cAdvisor (通过kubelet)

  • job_name: 'cadvisor'
    kubernetes_sd_configs:
  • role: node
    scheme: https
    metrics_path: /metrics/cadvisor
    tls_config:
    ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token

kube-state-metrics

  • job_name: 'kube-state-metrics'
    static_configs:
  • targets: 'kube-state-metrics.monitoring.svc.cluster.local:8080'

containerd (通过节点exporter或cRI)

  • job_name: 'containerd'
    static_configs:
  • targets: '192.168.10.21:9091','192.168.10.22:9091','192.168.10.23:9091'

部署Prometheus:

apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
serviceAccountName: prometheus
containers:

  • name: prometheus
    image: harbor.local/monitoring/prometheus:v2.48.0
    args:
  • --config.file=/etc/prometheus/prometheus.yml
  • --storage.tsdb.path=/prometheus
  • --storage.tsdb.retention.time=15d
  • --storage.tsdb.retention.size=100GB
  • --web.enable-lifecycle
    ports:
  • containerPort: 9090
    volumeMounts:
  • name: config
    mountPath: /etc/prometheus
  • name: rules
    mountPath: /etc/prometheus/rules
  • name: storage
    mountPath: /prometheus
    resources:
    requests:
    cpu: "2"
    memory: 4Gi
    limits:
    cpu: "4"
    memory: 8Gi
    volumes:
  • name: config
    configMap:
    name: prometheus-config
  • name: rules
    configMap:
    name: prometheus-rules
  • name: storage
    persistentVolumeClaim:
    claimName: prometheus-pvc

apiVersion: v1
kind: Service
metadata:
name: prometheus
namespace: monitoring
spec:
selector:
app: prometheus
ports:

  • port: 9090
    targetPort: 9090
    type: NodePort

3.2 node-exporter部署

apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: monitoring
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
hostNetwork: true
hostPID: true
containers:

  • name: node-exporter
    image: harbor.local/monitoring/node-exporter:v1.7.0
    args:
  • --path.procfs=/host/proc
  • --path.sysfs=/host/sys
  • --path.rootfs=/host/root
  • --collector.filesystem.mount-points-exclude=^/(dev|proc|sys|var/lib/docker/.+)($|/)
  • --collector.systemd
  • --collector.processes
  • --collector.tcpstat
    ports:
  • containerPort: 9100
    hostPort: 9100
    volumeMounts:
  • name: proc
    mountPath: /host/proc
    readOnly: true
  • name: sys
    mountPath: /host/sys
    readOnly: true
  • name: root
    mountPath: /host/root
    readOnly: true
    volumes:
  • name: proc
    hostPath:
    path: /proc
  • name: sys
    hostPath:
    path: /sys
  • name: root
    hostPath:
    path: /

apiVersion: v1
kind: Service
metadata:
name: node-exporter
namespace: monitoring
spec:
selector:
app: node-exporter
ports:

  • port: 9100
    targetPort: 9100

3.3 cAdvisor与kubelet指标

cAdvisor已集成在kubelet中,通过 /metrics/cadvisor 端点采集。关键指标:

|----------------------------------------|----------|
| 指标名 | 说明 |
| container_memory_working_set_bytes | 容器内存使用 |
| container_network_receive_bytes_total | 容器网络接收 |
| container_network_transmit_bytes_total | 容器网络发送 |
| container_fs_usage_bytes | 容器磁盘使用 |
| container_last_seen | 容器最后活跃时间 |

kubelet关键指标:

|-----------------------------------------|-------------------|
| 指标名 | 说明 |
| kubelet_running_containers | 运行中容器数 |
| kubelet_pod_start_duration_seconds | Pod启动耗时 |
| kubelet_cgroup_manager_duration_seconds | cgroup操作耗时 |
| kubelet_pleg_relist_duration_seconds | PLEG耗时(过高表示运行时异常) |

3.4 containerd指标采集

containerd内置Prometheus指标支持,需开启:

修改containerd配置,开启metrics

/etc/containerd/config.toml

metrics

address = "0.0.0.0:9091"
grpc_histogram = true

重启containerd

systemctl restart containerd

验证指标

curl http://localhost:9091/v1/metrics | head -20

containerd关键指标:

|------------------------------------------|----------|
| 指标名 | 说明 |
| containerd_grpc_request_duration_seconds | gRPC请求耗时 |
| containerd_snapshots_total | 快照数量 |
| containerd_content_total | 内容存储数量 |
| containerd_images_total | 镜像数量 |

3.5 kube-state-metrics部署

apiVersion: apps/v1
kind: Deployment
metadata:
name: kube-state-metrics
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: kube-state-metrics
template:
metadata:
labels:
app: kube-state-metrics
spec:
serviceAccountName: kube-state-metrics
containers:

  • name: kube-state-metrics
    image: harbor.local/monitoring/kube-state-metrics:v2.10.0
    ports:
  • containerPort: 8080
    resources:
    requests:
    cpu: 100m
    memory: 256Mi
    limits:
    cpu: 500m
    memory: 512Mi

apiVersion: v1
kind: Service
metadata:
name: kube-state-metrics
namespace: monitoring
spec:
selector:
app: kube-state-metrics
ports:

  • port: 8080
    targetPort: 8080

4. 日志采集与异常分析

4.1 Loki部署

apiVersion: apps/v1
kind: Deployment
metadata:
name: loki
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: loki
template:
metadata:
labels:
app: loki
spec:
containers:

  • name: loki
    image: harbor.local/monitoring/loki:2.9.0
    args:
  • -config.file=/etc/loki/loki-config.yml
    ports:
  • containerPort: 3100
    volumeMounts:
  • name: config
    mountPath: /etc/loki
  • name: storage
    mountPath: /data/loki
    resources:
    requests:
    cpu: "1"
    memory: 2Gi
    limits:
    cpu: "2"
    memory: 4Gi
    volumes:
  • name: config
    configMap:
    name: loki-config
  • name: storage
    persistentVolumeClaim:
    claimName: loki-pvc

apiVersion: v1
kind: ConfigMap
metadata:
name: loki-config
namespace: monitoring
data:
loki-config.yml: |
auth_enabled: false
server:
http_listen_port: 3100
common:
path_prefix: /data/loki
storage:
filesystem:
chunks_directory: /data/loki/chunks
rules_directory: /data/loki/rules
replication_factor: 1
ring:
instance_addr: 127.0.0.1
kvstore:
store: inmemory
query_range:
results_cache:
cache:
enable_fifocache: true
fifocache:
max_size_items: 1024
validity: 24h
limits_config:
retention_period: 168h
max_query_length: 721h
max_streams_per_user: 0
reject_old_samples: true
reject_old_samples_max_age: 168h
schema_config:
configs:

  • from: 2024-01-01
    store: tsdb
    object_store: filesystem
    schema: v13
    index:
    prefix: index_
    period: 24h

4.2 Promtail日志采集

apiVersion: apps/v1
kind: DaemonSet
metadata:
name: promtail
namespace: monitoring
spec:
selector:
matchLabels:
app: promtail
template:
metadata:
labels:
app: promtail
spec:
serviceAccountName: promtail
containers:

  • name: promtail
    image: harbor.local/monitoring/promtail:2.9.0
    args:
  • -config.file=/etc/promtail/promtail-config.yml
    volumeMounts:
  • name: config
    mountPath: /etc/promtail
  • name: logs
    mountPath: /var/log
    readOnly: true
  • name: containers
    mountPath: /var/log/containers
    readOnly: true
  • name: pods
    mountPath: /var/log/pods
    readOnly: true
  • name: journal
    mountPath: /var/log/journal
    readOnly: true
    volumes:
  • name: config
    configMap:
    name: promtail-config
  • name: logs
    hostPath:
    path: /var/log
  • name: containers
    hostPath:
    path: /var/log/containers
  • name: pods
    hostPath:
    path: /var/log/pods
  • name: journal
    hostPath:
    path: /var/log/journal

apiVersion: v1
kind: ConfigMap
metadata:
name: promtail-config
namespace: monitoring
data:
promtail-config.yml: |
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:

容器日志

  • job_name: kubernetes-pods
    pipeline_stages:
  • docker: {}
    kubernetes_sd_configs:
  • role: pod
    relabel_configs:
  • source_labels: '__meta_kubernetes_pod_node_name'
    target_label: 'node'
  • source_labels: '__meta_kubernetes_namespace'
    target_label: 'namespace'
  • source_labels: '__meta_kubernetes_pod_name'
    target_label: 'pod'
  • source_labels: '__meta_kubernetes_container_name'
    target_label: 'container'
  • replacement: '/var/log/pods/*$1/*.log'
    separator: /
    source_labels:
  • __meta_kubernetes_pod_uid
  • __meta_kubernetes_pod_container_name
    target_label: path

containerd系统日志

  • job_name: containerd-system
    static_configs:
  • targets: localhost
    labels:
    job: containerd
    path: /var/log/messages
    pipeline_stages:
  • match:
    selector: '{job="containerd"} |= "containerd"'
    stages:
  • labels:
    runtime: containerd

kubelet日志

  • job_name: kubelet-journal
    journal:
    json: false
    max_age: 7d
    path: /var/log/journal
    labels:
    job: kubelet
    relabel_configs:
  • source_labels: '__journal__systemd_unit'
    target_label: 'unit'

4.3 运行时日志关键字监控

在Loki中配置告警规则,监控运行时异常关键字:

/etc/loki/rules/fake/runtime-alerts.yml

groups:

  • name: runtime-errors
    rules:

  • alert: ContainerdCriError
    expr: |
    count_over_time({job="containerd"} |= "error" |= "cri" 5m) > 5
    for: 2m
    labels:
    severity: critical
    annotations:
    summary: "containerd CRI错误激增"
    description: "节点{{ $labels.node }} containerd CRI错误5分钟内超过5次"

  • alert: KubeletPlegHigh
    expr: |
    count_over_time({job="kubelet", unit="kubelet.service"} |= "PLEG" |= "unhealthy" 5m) > 0
    for: 1m
    labels:
    severity: critical
    annotations:
    summary: "kubelet PLEG不健康"
    description: "节点{{ $labels.node }} kubelet PLEG异常,可能导致Pod无法调度"

  • alert: OomKilledDetected
    expr: |
    count_over_time({namespace=~".+"} |= "OOMKilled" 10m) > 0
    for: 0m
    labels:
    severity: warning
    annotations:
    summary: "检测到OOMKilled"
    description: "Pod {{ $labels.pod }} 因OOM被杀死"

  • alert: CrashLoopBackOff
    expr: |
    count_over_time({namespace=~".+"} |= "CrashLoopBackOff" 5m) > 0
    for: 1m
    labels:
    severity: warning
    annotations:
    summary: "Pod CrashLoopBackOff"
    description: "Pod {{ $labels.pod }} 进入CrashLoopBackOff状态"

4.4 日志异常模式匹配

常用异常日志模式:

|-------------|---------------------------------------------------|--------|
| 异常模式 | 关键字 | 级别 |
| CRI调用失败 | failed to get sandbox / rpc error | P1 |
| kubelet节点异常 | PLEG is not healthy / runtime operation timed out | P0 |
| 镜像拉取失败 | Failed to pull image / manifest unknown | P2 |
| OOM内存溢出 | OOMKilled / out of memory | P1 |
| 磁盘压力 | disk pressure / image garbage collection | P1 |
| 网络异常 | network plugin cni / failed to setup network | P1 |
| 调度失败 | FailedScheduling / insufficient cpu/memory | P2 |

Loki查询示例:

查询所有运行时错误

{job=~"containerd|kubelet"} |= "error" != "EOF"

按节点统计错误数

sum by (node) (count_over_time({job="containerd"} |= "error" 1h))

趋势对比(同比上周)

sum(count_over_time({namespace="prod"} |= "500" 1h))
/
sum(count_over_time({namespace="prod"} |= "500" 1h offset 168h))

5. 运行时健康监控体系

5.1 containerd健康指标

查看containerd服务状态

systemctl is-active containerd
systemctl show containerd --property=NRestarts,ActiveEnterTimestamp

查看containerd指标

curl -s http://localhost:9091/v1/metrics | grep -E 'grpc_requests|grpc_request_duration'

Prometheus查询

containerd gRPC错误率

rate(containerd_grpc_requests_total{code=~"Internal|Unavailable|Unknown"}5m)

containerd gRPC延迟P99

histogram_quantile(0.99, rate(containerd_grpc_request_duration_seconds_bucket5m))

5.2 kubelet健康监控

kubelet健康检查

curl -sk https://localhost:10250/healthz

应返回 ok

kubelet就绪检查

curl -sk https://localhost:10250/readyz

PLEG耗时(超过3s异常)

curl -sk https://localhost:10250/metrics | grep kubelet_pleg_relist_duration

Prometheus告警表达式

PLEG P99延迟 > 3s

histogram_quantile(0.99, rate(kubelet_pleg_relist_duration_seconds_bucket5m)) > 3

kubelet重启

changes(kubelet_running_pods5m) < 0 and time() - kubelet_node_start_timestamp < 300

5.3 节点资源趋势监控

关键Prometheus查询:

CPU使用率(按节点)

100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}5m)) * 100)

内存使用率

100 * (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes))

磁盘使用率

100 - (100 * node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"})

磁盘IO等待

rate(node_pressure_io_waiting_seconds_total5m)

网络接收速率

rate(node_network_receive_bytes_total{device!~"lo|cali.*|tunl0|vxlan"}5m) * 8

网络发送速率

rate(node_network_transmit_bytes_total{device!~"lo|cali.*|tunl0|vxlan"}5m) * 8

TCP重传率

rate(node_netstat_Tcp_RetransSegs5m) / rate(node_netstat_Tcp_OutSegs5m) * 100

conntrack使用率

node_nf_conntrack_entries / node_nf_conntrack_entries_limit * 100

5.4 Pod异常状态监控

CrashLoopBackOff Pod数

sum(kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff"}) by (namespace, pod)

OOMKilled次数

increase(kube_pod_container_status_last_terminated_reason{reason="OOMKilled"}1h)

Pending Pod数(调度失败)

sum(kube_pod_status_phase{phase="Pending"}) by (namespace)

容器重启率(5分钟内重启>2次)

increase(kube_pod_container_status_restarts_total5m) > 2

Pod不可用

sum(kube_pod_status_phase{phase=~"Failed|Unknown"}) by (namespace, pod)

容器CPU throttling(被限流)

rate(container_cpu_cfs_throttled_seconds_total5m) > 0

5.5 网络异常监控

conntrack使用率 > 80%

node_nf_conntrack_entries / node_nf_conntrack_entries_limit > 0.8

TCP重传率 > 5%

rate(node_netstat_Tcp_RetransSegs5m) / rate(node_netstat_Tcp_OutSegs5m) > 0.05

网卡丢包率

rate(node_network_receive_drop_total5m) > 10
rate(node_network_transmit_drop_total5m) > 10

连接数异常增长

increase(node_netstat_Tcp_CurrEstab10m) > 1000

Calico节点异常

calico Felix健康检查失败数

6. 异常趋势分析模型

6.1 静态阈值告警

最基础的告警方式,适用于明确的资源上限:

  • alert: NodeCpuHigh
    expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}5m)) * 100) > 85
    for: 10m
    labels:
    severity: warning
    annotations:
    summary: "节点CPU使用率超过85%"

  • alert: NodeMemoryCritical
    expr: 100 * (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) > 95
    for: 5m
    labels:
    severity: critical

6.2 动态基线告警

基于历史同期数据计算动态阈值,适用于业务有明显周期性的场景:

当前值 vs 上周同期基线(偏差>50%告警)

(
avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}5m))

avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}5m offset 168h))
)
/
avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}5m offset 168h))
> 0.5

6.3 同比环比趋势分析

环比(当前小时 vs 上一小时)

sum(rate(container_cpu_usage_seconds_total1h))
/
sum(rate(container_cpu_usage_seconds_total1h offset 1h))

同比(当前 vs 上周同时段)

sum(rate(container_network_receive_bytes_total1h))
/
sum(rate(container_network_receive_bytes_total1h offset 168h))

7日移动平均

avg_over_time((sum by(instance) (rate(node_cpu_seconds_total{mode!="idle"}5m)))7d:)

6.4 异常突变检测

使用3-sigma原则检测异常突变:

当前值偏离7日均值超过3倍标准差

(
sum by(instance) (rate(node_cpu_seconds_total{mode!="idle"}5m))

avg_over_time((sum by(instance) (rate(node_cpu_seconds_total{mode!="idle"}5m)))7d:)
)
>
3 * stddev_over_time((sum by(instance) (rate(node_cpu_seconds_total{mode!="idle"}5m)))7d:)

6.5 容量趋势预测

线性回归预测资源耗尽时间:

磁盘使用率趋势预测(预测24小时后使用率)

predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}6h, 24*3600) < 0

内存耗尽预测(预测何时内存不足)

predict_linear(node_memory_MemAvailable_bytes6h, 3600) < 0

conntrack表满预测

predict_linear(node_nf_conntrack_entries1h, 3600) > node_nf_conntrack_entries_limit * 0.95

按当前增长率预测磁盘满的时间(小时)

(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"})
/
(-1 * deriv(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}1h))
/ 3600 < 24

7. 告警规则配置

7.1 运行时异常告警规则

创建 prometheus-rules.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-rules
namespace: monitoring
data:
runtime-alerts.yml: |
groups:

  • name: runtime-health
    rules:

containerd服务异常

  • alert: ContainerdDown
    expr: up{job="containerd"} == 0
    for: 1m
    labels:
    severity: critical
    annotations:
    summary: "containerd服务停止"
    description: "节点{{ $labels.instance }} containerd已停止超过1分钟"

containerd gRPC错误率

  • alert: ContainerdGrpcErrorHigh
    expr: |
    rate(containerd_grpc_requests_total{code=~"Internal|Unavailable|Unknown|DeadlineExceeded"}5m)
    /
    rate(containerd_grpc_requests_total5m) > 0.05
    for: 5m
    labels:
    severity: warning
    annotations:
    summary: "containerd gRPC错误率过高"
    description: "节点{{ $labels.instance }} gRPC错误率超过5%"

containerd gRPC延迟

  • alert: ContainerdGrpcLatencyHigh
    expr: histogram_quantile(0.99, rate(containerd_grpc_request_duration_seconds_bucket5m)) > 2
    for: 5m
    labels:
    severity: warning
    annotations:
    summary: "containerd gRPC延迟过高"
    description: "节点{{ $labels.instance }} P99延迟超过2秒"

kubelet异常

  • alert: KubeletDown
    expr: up{job="kubelet"} == 0
    for: 1m
    labels:
    severity: critical
    annotations:
    summary: "kubelet服务停止"

PLEG异常

  • alert: KubeletPlegHighLatency
    expr: histogram_quantile(0.99, rate(kubelet_pleg_relist_duration_seconds_bucket5m)) > 3
    for: 5m
    labels:
    severity: critical
    annotations:
    summary: "kubelet PLEG延迟过高"
    description: "节点{{ $labels.instance }} PLEG P99延迟超过3秒,Pod可能无法正常调度"

kubelet重启

  • alert: KubeletRestarted
    expr: changes(kubelet_node_start_timestamp15m) > 0
    for: 0m
    labels:
    severity: warning
    annotations:
    summary: "kubelet发生重启"

7.2 资源趋势告警规则

resource-alerts.yml: |
groups:

  • name: resource-trend
    rules:

CPU高

  • alert: NodeCpuUsageHigh
    expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}5m)) * 100) > 85
    for: 10m
    labels:
    severity: warning
    annotations:
    summary: "节点CPU使用率超过85%"
    description: "节点{{ labels.instance }} CPU使用率{{ value }}%"

CPU持续高(趋势)

  • alert: NodeCpuSustainedHigh
    expr: avg_over_time((100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}5m)) * 100))30m:) > 80
    for: 30m
    labels:
    severity: critical
    annotations:
    summary: "节点CPU持续高负载"

内存高

  • alert: NodeMemoryHigh
    expr: 100 * (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) > 90
    for: 10m
    labels:
    severity: warning

磁盘即将满(预测)

  • alert: DiskWillFillIn24h
    expr: predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay",mountpoint="/"}6h, 24*3600) < 0
    for: 1h
    labels:
    severity: critical
    annotations:
    summary: "磁盘预计24小时内写满"
    description: "节点{{ $labels.instance }} 根分区预计24小时内耗尽"

磁盘使用率高

  • alert: NodeDiskHigh
    expr: 100 - (100 * node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) > 85
    for: 10m
    labels:
    severity: warning

内存耗尽预测

  • alert: MemoryWillExhaust
    expr: predict_linear(node_memory_MemAvailable_bytes6h, 3600) < 0
    for: 15m
    labels:
    severity: critical
    annotations:
    summary: "内存预计1小时内耗尽"

7.3 网络异常告警规则

network-alerts.yml: |
groups:

  • name: network-anomaly
    rules:

conntrack使用率

  • alert: ConntrackHigh
    expr: node_nf_conntrack_entries / node_nf_conntrack_entries_limit > 0.8
    for: 5m
    labels:
    severity: warning
    annotations:
    summary: "conntrack使用率超过80%"

conntrack即将满(预测)

  • alert: ConntrackWillFull
    expr: predict_linear(node_nf_conntrack_entries1h, 1800) > node_nf_conntrack_entries_limit * 0.95
    for: 10m
    labels:
    severity: critical

TCP重传率

  • alert: TcpRetransHigh
    expr: rate(node_netstat_Tcp_RetransSegs5m) / rate(node_netstat_Tcp_OutSegs5m) > 0.05
    for: 10m
    labels:
    severity: warning
    annotations:
    summary: "TCP重传率超过5%"

网卡丢包

  • alert: NetworkPacketLoss
    expr: rate(node_network_receive_drop_total5m) > 10 or rate(node_network_transmit_drop_total5m) > 10
    for: 5m
    labels:
    severity: warning

网络带宽跑满

  • alert: NetworkBandwidthFull
    expr: (rate(node_network_receive_bytes_total{device!~"lo|cali.*|tunl0|vxlan"}5m) * 8) > (node_network_speed_bytes{device!~"lo|cali.*|tunl0|vxlan"} * 0.9 * 8)
    for: 10m
    labels:
    severity: warning

7.4 告警分级与抑制

|------------|-----------|----------|----------|
| 级别 | 触发条件 | 响应时间 | 通知方式 |
| P1 Warning | 性能下降、资源预警 | 30分钟 | 钉钉+邮件 |
| P2 Info | 趋势异常、容量预测 | 2小时 | 邮件+看板 |

告警抑制规则(Alertmanager):

inhibit_rules:

P0告警抑制同节点P1/P2告警

  • source_match:
    severity: critical
    target_match:
    severity: warning
    equal: 'instance', 'alertname'

节点宕机抑制该节点所有Pod告警

  • source_match:
    alertname: NodeDown
    target_match_re:
    alertname: 'Pod.*'
    equal: 'instance'

8. Alertmanager告警通知

8.1 Alertmanager部署

apiVersion: apps/v1
kind: Deployment
metadata:
name: alertmanager
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: alertmanager
template:
metadata:
labels:
app: alertmanager
spec:
containers:

  • name: alertmanager
    image: harbor.local/monitoring/alertmanager:v0.26.0
    args:
  • --config.file=/etc/alertmanager/alertmanager.yml
  • --storage.path=/alertmanager
  • --web.external-url=http://alertmanager:9093
    ports:
  • containerPort: 9093
    volumeMounts:
  • name: config
    mountPath: /etc/alertmanager
  • name: storage
    mountPath: /alertmanager
    volumes:
  • name: config
    configMap:
    name: alertmanager-config
  • name: storage
    emptyDir: {}

apiVersion: v1
kind: Service
metadata:
name: alertmanager
namespace: monitoring
spec:
selector:
app: alertmanager
ports:

  • port: 9093
    targetPort: 9093

8.2 告警路由配置

apiVersion: v1
kind: ConfigMap
metadata:
name: alertmanager-config
namespace: monitoring
data:
alertmanager.yml: |
global:
resolve_timeout: 5m

企业微信webhook

wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
wechat_api_secret: '<企业微信Secret>'
wechat_api_corp_id: '<企业ID>'

route:
group_by: 'alertname', 'cluster', 'instance'
group_wait: 10s
group_interval: 5m
repeat_interval: 4h
receiver: 'default'
routes:

P0告警立即通知

  • match:
    severity: critical
    receiver: 'critical-webhook'
    group_wait: 0s
    repeat_interval: 1h

P1告警

  • match:
    severity: warning
    receiver: 'warning-dingtalk'
    repeat_interval: 4h

P2告警

  • match:
    severity: info
    receiver: 'info-email'
    repeat_interval: 12h

receivers:

inhibit_rules:

  • source_match:
    severity: critical
    target_match:
    severity: warning
    equal: 'instance'

8.3 钉钉/企业微信通知

部署Webhook转发服务(支持钉钉和企业微信):

#!/usr/bin/env python3

alertmanager-webhook.py

from flask import Flask, request
import requests
import json

app = Flask(name)

DINGTALK_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=\<token>"
WECHAT_WEBHOOK = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=\<key>"

def send_dingtalk(alert):
severity = alert'labels'.get('severity', 'unknown')
emoji = "🔴" if severity == "critical" else "��" if severity == "warning" else "🔵"
content = f"""{emoji} **{alert'annotations'.get('summary', '告警')}**
> 级别: {severity}
> 节点: {alert'labels'.get('instance', 'N/A')}
> 描述: {alert'annotations'.get('description', 'N/A')}
> 时间: {alert'startsAt'}"""

data = {
"msgtype": "markdown",
"markdown": {"title": "K8s告警", "text": content}
}
requests.post(DINGTALK_WEBHOOK, json=data)

def send_wechat(alert):
severity = alert'labels'.get('severity', 'unknown')
content = f"{severity.upper()} {alert'annotations'.get('summary', '告警')}\n节点: {alert'labels'.get('instance', 'N/A')}\n描述: {alert'annotations'.get('description', 'N/A')}"
data = {"msgtype": "text", "text": {"content": content}}
requests.post(WECHAT_WEBHOOK, json=data)

@app.route('/webhook', methods='POST')
def webhook():
data = request.json
for alert in data.get('alerts', \[\]):
if alert'status' == 'firing':
send_dingtalk(alert)
send_wechat(alert)
return "ok"

@app.route('/critical', methods='POST')
def critical():
data = request.json
for alert in data.get('alerts', \[\]):
if alert'status' == 'firing':
send_dingtalk(alert)
send_wechat(alert)
return "ok"

@app.route('/dingtalk', methods='POST')
def dingtalk():
data = request.json
for alert in data.get('alerts', \[\]):
if alert'status' == 'firing':
send_dingtalk(alert)
return "ok"

if name == 'main':
app.run(host='0.0.0.0', port=8080)

8.4 告警聚合与抑制

同一告警分组聚合(避免告警风暴)

route:
group_by: 'alertname', 'cluster'
group_wait: 30s # 首次告警等待30s,聚合同组告警
group_interval: 5m # 同组新告警间隔5分钟
repeat_interval: 4h # 重复告警间隔4小时

静默规则(维护期间静默)

通过Alertmanager API创建

curl -X POST http://alertmanager:9093/api/v2/silences -d '{

"matchers": {"name":"severity","value":"warning","isRegex":false},

"startsAt": "2026-08-18T22:00:00.000Z",

"endsAt": "2026-08-19T02:00:00.000Z",

"createdBy": "ops",

"comment": "夜间维护窗口"

}'

9. Grafana可视化看板

9.1 Grafana部署与配置

apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
containers:

  • name: grafana
    image: harbor.local/monitoring/grafana:10.2.0
    ports:
  • containerPort: 3000
    env:
  • name: GF_SECURITY_ADMIN_PASSWORD
    value: "Grafana@2026"
  • name: GF_USERS_ALLOW_SIGN_UP
    value: "false"
    volumeMounts:
  • name: storage
    mountPath: /var/lib/grafana
  • name: datasources
    mountPath: /etc/grafana/provisioning/datasources
    resources:
    requests:
    cpu: 500m
    memory: 1Gi
    limits:
    cpu: "2"
    memory: 2Gi
    volumes:
  • name: storage
    persistentVolumeClaim:
    claimName: grafana-pvc
  • name: datasources
    configMap:
    name: grafana-datasources

apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-datasources
namespace: monitoring
data:
datasources.yml: |
apiVersion: 1
datasources:

9.2 运行时总览看板

关键面板配置:

|--------------|-------------------------------------------------------------------------------------------------------------------|----------|
| 面板 | 查询语句 | 图表类型 |
| containerd状态 | up{job="containerd"} | Stat |
| kubelet状态 | up{job="kubelet"} | Stat |
| 集群CPU使用率 | 100 - (avg(rate(node_cpu_seconds_total{mode="idle"}5m)) * 100) | Gauge |
| 集群内存使用率 | 100 * (1 - (sum(node_memory_MemAvailable_bytes) / sum(node_memory_MemTotal_bytes))) | Gauge |
| 集群磁盘使用率 | 100 - (100 * sum(node_filesystem_avail_bytes{mountpoint="/"}) / sum(node_filesystem_size_bytes{mountpoint="/"})) | Gauge |
| Pod总数 | sum(kube_pod_status_phase{phase="Running"}) | Stat |
| 异常Pod数 | `sum(kube_pod_status_phase{phase=~"Failed | Pending |
| 运行时重启数 | increase(kube_pod_container_status_restarts_total1h) | Table |

9.3 趋势分析看板

|-------------|----------------------------------------------------------------------------|-------------|
| 面板 | 查询语句 | 图表类型 |
| 内存趋势(7天) | 100 * (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) | Time series |
| 网络入流量趋势 | `rate(node_network_receive_bytes_total{device!~"lo | .*cali.* |
| 网络出流量趋势 | `rate(node_network_transmit_bytes_total{device!~"lo | .*cali.* |
| conntrack趋势 | node_nf_conntrack_entries / node_nf_conntrack_entries_limit * 100 | Time series |
| TCP连接数趋势 | node_netstat_Tcp_CurrEstab | Time series |
| 磁盘IO趋势 | rate(node_disk_io_time_seconds_total5m) * 100 | Time series |
| 同比对比 | 当前值 / 上周同期值 | Time series |

9.4 异常告警看板

|-----------|-----------------------|
| 面板 | 内容 |
| 告警趋势(24h) | 按级别统计告警数 |
| TOP10告警源 | 按instance/alertname统计 |
| 告警响应时长 | 从firing到resolved的时间差 |
| 告警静默列表 | 当前生效的silence |
| P0告警历史 | critical级别告警记录 |

10. 趋势预测与容量预警

10.1 资源使用趋势预测

CPU使用率线性回归预测(1小时后)

predict_linear(
(100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}5m)) * 100))6h:,
3600
)

内存使用预测(2小时后)

predict_linear(
(100 * (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)))6h:,
7200
)

基于7天数据的趋势预测

predict_linear(
(sum by(instance) (rate(node_cpu_seconds_total{mode!="idle"}1h)))7d:,
86400
)

10.2 磁盘容量预警

节点磁盘监控脚本(配合cron定时执行)

#!/bin/bash
THRESHOLD=80
for node in (kubectl get nodes -o jsonpath='{.items\[\*\].status.addresses\[?(@.type=="InternalIP")\].address}'); do USAGE=(ssh root@{node} "df -h / \| awk 'NR==2{print \\5}' | tr -d '%'")
if ${USAGE} -gt ${THRESHOLD} ; then

计算按当前增速耗尽时间

REMAIN=(ssh root@{node} "df -B1 / | awk 'NR==2{print \4}'") GROWTH=(ssh root@{node} "cat /tmp/disk_growth_rate") HOURS_LEFT=((REMAIN / GROWTH / 3600))
echo "WARN: {node} 磁盘使用率{USAGE}%, 预计${HOURS_LEFT}小时后耗尽"

发送告警...

fi
done

Prometheus磁盘预测告警:

  • alert: DiskPredictionCritical
    expr: |
    predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay",mountpoint="/"}6h, 86400) < 0
    for: 30m
    labels:
    severity: critical
    annotations:
    summary: "磁盘预计24小时内写满"
    description: "节点{{ $labels.instance }} 根分区按当前增速预计24小时内耗尽,请立即清理"

  • alert: DiskPredictionWarning
    expr: |
    predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay",mountpoint="/"}24h, 259200) < 0
    for: 1h
    labels:
    severity: warning
    annotations:
    summary: "磁盘预计3天内写满"

10.3 连接数趋势预警

conntrack表满预测(30分钟内超过95%)

predict_linear(node_nf_conntrack_entries1h, 1800) > node_nf_conntrack_entries_limit * 0.95

TCP连接数异常增长(1小时内增长超过50%)

(
node_netstat_Tcp_CurrEstab

node_netstat_Tcp_CurrEstab offset 1h
)
/
node_netstat_Tcp_CurrEstab offset 1h > 0.5

容器网络连接数趋势

sum by(pod) (rate(container_network_tcp_connections_total5m))

10.4 自动化容量扩缩容建议

基于趋势数据生成扩容建议:

#!/bin/bash

容量评估脚本

echo "========== K8s集群容量评估报告 =========="
echo "生成时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""

1. CPU容量

CPU_TOTAL=(kubectl get nodes -o jsonpath='{.items\[\*\].status.capacity.cpu}' \| tr ' ' '\\n' \| awk '{sum+=1}END{print sum}')
CPU_USED=(kubectl top nodes --no-headers \| awk '{sum+=3}END{print sum}' | tr -d '%')
echo "CPU 总核数: {CPU_TOTAL}, 已用: {CPU_USED}%"

2. 内存容量

MEM_TOTAL=(kubectl get nodes -o jsonpath='{.items\[\*\].status.capacity.memory}' \| tr ' ' '\\n' \| sed 's/Ki//' \| awk '{sum+=1}END{print sum/1024/1024 "Gi"}')
MEM_USED=(kubectl top nodes --no-headers \| awk '{sum+=5}END{print sum}' | tr -d '%')
echo "内存 总量: {MEM_TOTAL}, 已用: {MEM_USED}%"

3. Pod容量

POD_TOTAL=(kubectl get nodes -o jsonpath='{.items\[\*\].status.capacity.pods}' \| tr ' ' '\\n' \| awk '{sum+=1}END{print sum}')
POD_USED=(kubectl get pods -A --no-headers \| wc -l) echo "\[Pod\] 总容量: {POD_TOTAL}, 已用: {POD_USED} (((POD_USED*100/POD_TOTAL))%)"

4. 扩容建议

echo ""
echo "========== 扩容建议 =========="
if ${CPU_USED} -gt 70 ; then
echo "⚠ CPU使用率超过70%,建议新增Worker节点"
fi
if ${MEM_USED} -gt 70 ; then
echo "⚠ 内存使用率超过70%,建议新增Worker节点"
fi
if $((POD_USED\*100/POD_TOTAL)) -gt 75 ; then
echo "⚠ Pod容量使用率超过75%,建议新增Worker节点"
fi
echo "✅ 容量评估完成"

11. 应急响应流程

11.1 告警分级响应矩阵

|--------|---------------------------------|----------|---------|--------------|
| 级别 | 告警类型 | 响应时间 | 处理人 | 升级条件 |
| P1 | CPU/内存>90%、磁盘预测24h满、OOM、PLEG异常 | 30分钟 | 值班SRE | 1小时未解决→技术负责人 |
| P2 | CPU/内存>80%、TCP重传高、调度失败、趋势异常 | 2小时 | SRE团队 | 4小时未解决→技术负责人 |
| P3 | 容量预测、日志异常、性能基线偏离 | 工作日 | SRE团队 | - |

11.2 运行时异常应急处理

containerd停止应急

1. 确认状态

systemctl status containerd
crictl info

2. 查看日志

journalctl -u containerd -n 200 --no-pager

3. 尝试重启

systemctl restart containerd

4. 如重启失败,检查配置

containerd config dump > /dev/null

5. 检查残留进程

ps aux | grep containerd
ss -lntp | grep containerd.sock

6. 紧急恢复(清理残留后重启)

rm -f /run/containerd/containerd.sock
systemctl restart containerd

7. 验证恢复

crictl ps
kubectl get nodes

节点NotReady应急

1. 确认节点状态

kubectl get nodes
kubectl describe node <node-name>

2. 检查kubelet

systemctl status kubelet
journalctl -u kubelet -n 100

3. 检查containerd

systemctl status containerd
crictl info

4. 检查资源

free -h
df -h
dmesg | tail -50

5. 紧急驱逐(如节点无法恢复)

kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data --force

6. 恢复后重新调度

kubectl uncordon <node-name>

11.3 自动化自愈脚本

#!/bin/bash

k8s-node-auto-heal.sh

节点自动健康检查与自愈

LOGFILE="/var/log/k8s-heal.log"

log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') 1" \>\> {LOGFILE}
}

1. containerd健康检查

if ! systemctl is-active containerd > /dev/null; then
log "containerd未运行,尝试重启..."
systemctl restart containerd
sleep 5
if systemctl is-active containerd > /dev/null; then
log "containerd重启成功"
else
log "containerd重启失败,需人工介入"

发送告警...

fi
fi

2. kubelet健康检查

if ! systemctl is-active kubelet > /dev/null; then
log "kubelet未运行,尝试重启..."
systemctl restart kubelet
fi

3. 磁盘空间检查

DISK_USAGE=(df / \| awk 'NR==2{print 5}' | tr -d '%')
if ${DISK_USAGE} -gt 90 ; then
log "磁盘使用率${DISK_USAGE}%,执行清理..."

清理containerd未使用镜像

crictl rmi --prune

清理journal日志

journalctl --vacuum-size=500M

清理/tmp

find /tmp -type f -atime +7 -delete
fi

4. conntrack检查

CT_COUNT=(sysctl -n net.netfilter.nf_conntrack_count) CT_MAX=(sysctl -n net.netfilter.nf_conntrack_max)
if $((CT_COUNT \* 100 / CT_MAX)) -gt 90 ; then
log "conntrack使用率过高,调大上限..."
sysctl -w net.netfilter.nf_conntrack_max=2097152
fi

5. OOM Pod检查

OOM_PODS=(crictl ps -a \| grep OOMKilled \| wc -l) if \[ {OOM_PODS} -gt 0 ]; then
log "检测到${OOM_PODS}个OOMKilled容器"
fi

配置定时执行:

每5分钟执行一次

chmod +x /opt/k8s-node-auto-heal.sh
(crontab -l 2>/dev/null; echo "*/5 * * * * /opt/k8s-node-auto-heal.sh") | crontab -

11.4 事后复盘与规则优化

复盘模板:

【告警复盘报告】
告警名称:
发生时间:
恢复时间:
持续时长:
影响范围:
根本原因:
处理过程:
改进措施:

  1. 短期(立即执行):
  2. 中期(1周内):
  3. 长期(1月内):
    告警规则优化:
  • 阈值调整:
  • 新增告警:
  • 移除误报告警:
相关推荐
吃饱了得干活1 小时前
从经典的三层架构到DDD:一次对“业务逻辑层”的解剖与重构
java·后端·架构
SL_staff1 小时前
中小离散制造如何用工艺路线模板解决‘人走流程丢’——JVS-APS 实践解析
java·设计模式·全栈
微擎应用市场1 小时前
微擎面板 W7Panel:一站式云原生管理平台,让 Kubernetes 触手可及
云原生·容器·kubernetes
我命由我123451 小时前
Android 开发问题:使用 AndroidTreeView 时,自定义视图无法撑满父容器
android·java·java-ee·kotlin·android studio·android-studio·android runtime
秋田君2 小时前
QT_一个UDP通信程序(单播+广播)
开发语言·qt·udp
冷雨夜中漫步2 小时前
DeepSeek Harness:一切皆插件的 AI Agent 框架深度解析
java·人工智能·ai·开源·github
qq_22589174662 小时前
基于Flask的空气质量监测与预测分析系统
开发语言·后端·python·信息可视化·django·flask
三言老师2 小时前
K8s 集群 LocalPV 静态 PV 资源手动创建实操
linux·运维·服务器·kubernetes
lhldsg2 小时前
社区健身系统开发实战:从需求分析到落地部署全流程指南
java·开发语言·小程序·需求分析