k8s资源监控与日志收集方案详细分解
·
一、整体架构设计说明
架构拓扑
┌─────────────────────────────────────────────────────────────────────────┐
│ Kubernetes 集群 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Node 1 Node 2 Node N │
│ ┌─────────────────┐ ┌─────────────────┐ ┌───────────┐ │
│ │ │ │ │ │ │ │
│ │ Pod A │ │ Pod X │ │ Pod Z │ │
│ │ Pod B │ │ Pod Y │ │ │ │
│ │ ... │ │ ... │ │ │ │
│ │ │ │ │ │ │ │
│ ├─────────────────┤ ├─────────────────┤ ├───────────┤ │
│ │ 监控代理层 │ │ 监控代理层 │ │ 监控代理层 │ │
│ │ • kubelet │ │ • kubelet │ │ • kubelet │ │
│ │ • cadvisor │ │ • cadvisor │ │ • cadvisor│ │
│ │ • node-exporter│ │ • node-exporter│ │ • node-exporter │
│ │ • Fluent Bit │ │ • Fluent Bit │ │ • Fluent Bit │
│ └────────┬────────┘ └────────┬────────┘ └─────┬─────┘ │
│ │ │ │ │
│ └──────────────┬───────────────┘ │ │
│ │ │ │
└──────────────────────────┼────────────────────────────────────────────┼──────┘
│ │
监控数据流向 日志文件流向
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ │ │ │
│ Prometheus │ │ Node本地磁盘 │
│ │ │ /var/log/ │
│ 集群级收集 │ │ k8s-logs/ │
│ │ │ │
└──────┬──────┘ └─────────────┘
│
┌──────▼──────┐
│ │
│ Grafana │
│ 展示层 │
│ │
└─────────────┘
二、资源监控方案详细分解
组件职责说明
1. Prometheus Operator
- 作用:简化Prometheus在K8S中的部署和管理
- 功能:
-
- 自动生成Prometheus配置
- 管理Prometheus实例的生命周期
- 通过CRD定义监控目标
2. kube-prometheus-stack 包含的组件:
包含组件:
• Prometheus Operator - 管理Prometheus实例
• Prometheus - 指标收集和存储
• Alertmanager - 告警管理(可禁用)
• Grafana - 数据可视化
• kube-state-metrics - 转换K8S对象状态为指标
• node-exporter - 收集节点指标
• 各种ServiceMonitor - 自动发现监控目标
详细配置说明
Step 1: 创建监控命名空间
kubectl create namespace monitoring
作用:资源隔离,便于管理和权限控制
Step 2: 准备定制化values.yaml
# prometheus-values-detailed.yaml
# 全局镜像配置(针对内网环境)
global:
# 内网镜像仓库地址,需提前导入镜像
imageRegistry: "registry.internal.company.com"
# 拉取镜像的凭证,如果私有仓库需要认证
imagePullSecrets: ["regcred"]
# 镜像拉取策略
imagePullPolicy: "IfNotPresent"
# Prometheus Operator配置
prometheusOperator:
# 启用服务监控自动发现
serviceMonitorSelectorNilUsesHelmValues: false
serviceMonitorSelector: {}
serviceMonitorNamespaceSelector: {}
# 启用Pod监控自动发现
podMonitorSelectorNilUsesHelmValues: false
podMonitorSelector: {}
podMonitorNamespaceSelector: {}
# 资源限制
resources:
requests:
memory: "200Mi"
cpu: "100m"
limits:
memory: "400Mi"
cpu: "200m"
# Prometheus主配置
prometheus:
enabled: true
# Prometheus实例配置
prometheusSpec:
# 数据保留时间(根据存储空间调整)
retention: "10d"
# 抓取间隔
scrapeInterval: "30s"
evaluationInterval: "30s"
# 资源限制(根据集群规模调整)
resources:
requests:
memory: "400Mi"
cpu: "200m"
limits:
memory: "2Gi"
cpu: "1000m"
# 存储配置
storageSpec:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "standard" # 根据实际存储类调整
resources:
requests:
storage: "50Gi" # 监控数据存储大小
# 服务发现配置
serviceMonitorSelectorNilUsesHelmValues: false
serviceMonitorSelector: {}
# 规则配置
ruleSelectorNilUsesHelmValues: false
ruleSelector: {}
# 额外的抓取配置
additionalScrapeConfigs:
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:9100'
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
# 安全上下文
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
# kube-state-metrics配置
kube-state-metrics:
# 资源限制
resources:
requests:
memory: "32Mi"
cpu: "10m"
limits:
memory: "128Mi"
cpu: "100m"
# 自动发现命名空间
namespaceSelector:
any: true
# 收集的指标
metricLabelsAllowlist:
- pods=[app,component,instance,job,name,namespace,phase,pod,uid]
- deployments=[namespace,deployment]
- nodes=[node]
- statefulsets=[namespace,statefulset]
# node-exporter配置(每个节点部署)
nodeExporter:
enabled: true
# 资源限制
resources:
requests:
memory: "30Mi"
cpu: "10m"
limits:
memory: "50Mi"
cpu: "200m"
# 采集的指标
extraArgs:
- "--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|run|var/lib/docker/.+)($|/)"
- "--collector.netclass.ignored-devices=^(veth.*|[a-f0-9]{15})$"
- "--collector.netdev.device-exclude=^(veth.*|[a-f0-9]{15})$"
# Grafana配置
grafana:
enabled: true
# 管理员凭据
adminUser: "admin"
adminPassword: "admin123" # 生产环境务必修改
# 持久化存储
persistence:
enabled: true
type: "pvc"
size: "10Gi"
storageClassName: "standard"
accessModes:
- "ReadWriteOnce"
# 预配置数据源和面板
sidecar:
datasources:
enabled: true
label: "grafana_datasource"
dashboards:
enabled: true
label: "grafana_dashboard"
# 内置数据源配置
additionalDataSources:
- name: "Prometheus"
type: "prometheus"
url: "http://prometheus-operated.monitoring.svc.cluster.local:9090"
access: "proxy"
isDefault: true
# 资源限制
resources:
requests:
memory: "100Mi"
cpu: "100m"
limits:
memory: "200Mi"
cpu: "500m"
# Alertmanager配置(根据需求禁用)
alertmanager:
enabled: false # 不需要告警,所以禁用
# 其他配置
coreDns:
enabled: true
kubeControllerManager:
enabled: true
kubeEtcd:
enabled: true
kubeProxy:
enabled: true
kubeScheduler:
enabled: true
配置项详解:
- imageRegistry:内网镜像仓库地址,需提前导入所有需要的镜像
- retention:监控数据保留时间,根据存储容量调整
- storageSpec:Prometheus数据存储配置,使用PVC持久化
- serviceMonitorSelector:空选择器表示监控所有ServiceMonitor
- additionalScrapeConfigs:额外的抓取配置,如节点指标
- metricLabelsAllowlist:控制收集哪些K8S对象标签,减少数据量
Step 3: 安装监控栈
# 方式1:使用Helm直接安装(如有内网Helm仓库)
helm install prometheus-stack prometheus-community/kube-prometheus-stack \
-n monitoring \
-f prometheus-values-detailed.yaml \
--version 45.0.0
# 方式2:离线安装(推荐)
# 1. 在外网环境下载chart
helm pull prometheus-community/kube-prometheus-stack --version 45.0.0
# 2. 解压并修改镜像地址
tar -xzf kube-prometheus-stack-45.0.0.tgz
# 编辑values.yaml中的镜像地址
# 3. 导入镜像到内网仓库(需要提前准备)
# 镜像列表(示例):
# quay.io/prometheus-operator/prometheus-operator:v0.68.0
# quay.io/prometheus/prometheus:v2.45.0
# quay.io/prometheus/node-exporter:v1.6.0
# k8s.gcr.io/kube-state-metrics/kube-state-metrics:v2.9.2
# grafana/grafana:9.5.3
# 4. 在内网安装
helm install prometheus-stack ./kube-prometheus-stack \
-n monitoring \
-f prometheus-values-detailed.yaml
Step 4: 验证监控安装
# 检查所有组件状态
kubectl get pods -n monitoring -w
# 检查Pod状态详情
kubectl describe pods -n monitoring -l app.kubernetes.io/name=kube-prometheus-stack
# 检查持久化卷
kubectl get pvc -n monitoring
# 临时访问Prometheus UI(测试用)
kubectl port-forward -n monitoring svc/prometheus-operated 9090:9090
# 访问 http://localhost:9090/targets 查看抓取目标
# 临时访问Grafana
kubectl port-forward -n monitoring svc/prometheus-stack-grafana 3000:80
# 访问 http://localhost:3000 用户名/密码:admin/admin123
预置监控指标说明
1. Pod资源监控
# CPU使用率
rate(container_cpu_usage_seconds_total{container!="",container!="POD"}[5m]) * 100
# 内存使用量
container_memory_working_set_bytes{container!="",container!="POD"}
# CPU限制使用率
sum(rate(container_cpu_usage_seconds_total{container!="",container!="POD"}[5m])) by (pod, namespace) /
sum(kube_pod_container_resource_limits_cpu_cores) by (pod, namespace) * 100
# 内存限制使用率
container_memory_working_set_bytes{container!="",container!="POD"} /
kube_pod_container_resource_limits_memory_bytes * 100
2. Node资源监控
# 节点CPU使用率
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# 节点内存使用率
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100
# 节点磁盘使用率
(node_filesystem_size_bytes{fstype!=""} - node_filesystem_free_bytes{fstype!=""}) /
node_filesystem_size_bytes{fstype!=""} * 100
三、日志收集方案详细分解
日志收集架构原理
日志流动路径:
1. 应用容器 → stdout/stderr
2. Docker/containerd → /var/lib/docker/containers/{container-id}/{container-id}-json.log
3. Kubelet符号链接 → /var/log/containers/{pod-name}_{namespace}_{container-name}-{container-id}.log
4. Fluent Bit监控 → 读取日志文件,添加元数据
5. 本地磁盘 → /var/log/k8s-logs/{timestamp}-{pod}-{container}.log
详细配置说明
Step 1: 创建日志命名空间和RBAC
# 1-fluent-bit-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: logging
labels:
name: logging
---
# 2-fluent-bit-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: fluent-bit
namespace: logging
labels:
k8s-app: fluent-bit-logging
---
# 3-fluent-bit-clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fluent-bit-read
labels:
k8s-app: fluent-bit-logging
rules:
- apiGroups: [""]
resources:
- namespaces
- pods
- pods/logs # 关键权限:读取Pod日志
verbs: ["get", "list", "watch"] # 只需要读权限
- apiGroups: ["apps"]
resources:
- daemonsets
- deployments
- statefulsets
verbs: ["get", "list"]
---
# 4-fluent-bit-clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: fluent-bit-read
labels:
k8s-app: fluent-bit-logging
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: fluent-bit-read
subjects:
- kind: ServiceAccount
name: fluent-bit
namespace: logging
RBAC权限详解:
- namespaces:获取命名空间信息,用于日志分类
- pods:获取Pod信息,用于添加元数据
- pods/logs:核心权限,允许读取Pod日志
- 只读权限:安全最佳实践,避免权限过大
Step 2: 创建Fluent Bit配置ConfigMap
# 5-fluent-bit-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-config
namespace: logging
labels:
k8s-app: fluent-bit-logging
data:
# ==================== 主配置文件 ====================
fluent-bit.conf: |
[SERVICE]
Flush 5 # 每5秒刷新输出缓冲区
Log_Level info # 日志级别:error, warn, info, debug, trace
Daemon off # 容器中运行,非守护进程
Parsers_File parsers.conf # 解析器配置文件
HTTP_Server On # 开启HTTP服务,用于健康检查和指标
HTTP_Listen 0.0.0.0
HTTP_Port 2020
storage.path /var/log/flb-storage/ # 检查点存储位置
storage.sync normal
storage.checksum off
storage.backlog.mem_limit 5M
@INCLUDE input-kubernetes.conf # 输入配置:从哪里收集日志
@INCLUDE filter-kubernetes.conf # 过滤配置:如何处理日志
@INCLUDE output-file.conf # 输出配置:日志输出到哪里
# ==================== 输入配置 ====================
input-kubernetes.conf: |
[INPUT]
Name tail # 使用tail插件,监控文件变化
Tag kube.* # 标签前缀,用于路由
Path /var/log/containers/*.log # 监控K8S容器日志目录
Parser docker # 使用docker解析器
DB /var/log/flb_kube.db # 检查点数据库,记录读取位置
DB.Sync Normal # 同步模式
Mem_Buf_Limit 5MB # 内存缓冲区限制
Skip_Long_Lines On # 跳过超长行,避免内存溢出
Refresh_Interval 10 # 刷新文件列表间隔(秒)
Rotate_Wait 30 # 日志轮转等待时间
Ignore_Older 24h # 忽略超过24小时的旧文件
# 多行日志处理(如果应用日志是多行的)
# Multiline On
# Parser_Firstline multiline_regex
# ==================== 过滤配置 ====================
filter-kubernetes.conf: |
[FILTER]
Name kubernetes # Kubernetes元数据过滤器
Match kube.* # 匹配所有kube标签的日志
Kube_URL https://kubernetes.default.svc:443 # K8S API地址
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
Kube_Tag_Prefix kube.var.log.containers. # 标签前缀
Merge_Log On # 合并日志字段
Merge_Log_Key log_processed # 合并后的字段名
Keep_Log Off # 不保留原始日志
K8S-Logging.Parser On
K8S-Logging.Exclude Off
Labels On # 包含Pod标签
Annotations Off # 不包含注解(减少数据量)
Use_Kubelet Off # 不使用kubelet API
Buffer_Size 0 # 缓冲区大小(0为禁用)
# 添加节点信息
[FILTER]
Name modify
Match *
Add node_name ${NODE_NAME}
Add host_ip ${HOST_IP}
Add cluster_name my-k8s-cluster
# 可选:根据命名空间添加标签
[FILTER]
Name nest
Match *
Operation nest
Wildcard kubernetes.namespace_name
Nest_Under kubernetes
Remove_Prefix kubernetes.
# 可选:时间戳格式化
[FILTER]
Name modify
Match *
Rename time @timestamp
# ==================== 输出配置 ====================
output-file.conf: |
[OUTPUT]
Name file # 输出到文件
Match * # 匹配所有日志
Path /var/log/k8s-logs/ # 输出目录
Format template # 使用模板格式
Template {time}-{kubernetes['namespace_name']}-{kubernetes['pod_name']}-{kubernetes['container_name']}.log
# 文件名格式:时间戳-命名空间-Pod名-容器名.log
Retry_Limit False # 无限重试
Sync Full # 每次写入都同步到磁盘
# 文件输出格式
# { "timestamp": "$time", "log": "$log", "kubernetes": "$kubernetes", "node": "$node_name" }
# ==================== 解析器配置 ====================
parsers.conf: |
# Docker默认JSON格式解析器
[PARSER]
Name docker
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%LZ
Time_Keep On
Decode_Field_As escaped_utf8 log do_next
Decode_Field_As json log
# 可选:多行日志解析(如Java堆栈跟踪)
[PARSER]
Name multiline_regex
Format regex
Regex /^(?<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}) (?<log>.*)/
Time_Key time
Time_Format %Y-%m-%d %H:%M:%S.%L
# CRI-O容器运行时解析器
[PARSER]
Name cri
Format regex
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<log>.*)$
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
配置文件详解:
- SERVICE段:
-
Flush 5:每5秒刷新缓冲区,平衡性能和数据完整性storage.path:检查点存储,重启后从上次位置继续
- INPUT段(tail插件):
-
Path /var/log/containers/*.log:监控K8S容器日志目录DB /var/log/flb_kube.db:记录文件读取位置,实现断点续传Ignore_Older 24h:忽略旧文件,提高启动速度
- FILTER段(kubernetes插件):
-
- 从K8S API获取Pod元数据(名称、命名空间、标签等)
Merge_Log On:将原始日志合并到新字段Labels On:包含Pod标签,便于分类
- OUTPUT段(file插件):
-
Template:自定义文件名格式,包含Pod和容器信息Sync Full:确保数据写入磁盘
Step 3: 创建DaemonSet部署Fluent Bit
# 6-fluent-bit-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluent-bit
namespace: logging
labels:
k8s-app: fluent-bit-logging
version: v2.1.9
spec:
selector:
matchLabels:
k8s-app: fluent-bit-logging
version: v2.1.9
updateStrategy:
type: RollingUpdate # 滚动更新策略
rollingUpdate:
maxUnavailable: 1 # 更新时最多不可用Pod数
minReadySeconds: 10 # Pod就绪后等待时间
template:
metadata:
labels:
k8s-app: fluent-bit-logging
version: v2.1.9
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "2020"
prometheus.io/path: "/api/v1/metrics/prometheus"
spec:
# 服务账户(之前创建)
serviceAccountName: fluent-bit
# 优先级,确保在节点资源紧张时不被驱逐
priorityClassName: "system-node-critical"
# 容忍度,确保在所有节点运行(包括控制平面)
tolerations:
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: "CriticalAddonsOnly"
operator: "Exists"
# 节点选择器(可选,限制在某些节点运行)
# nodeSelector:
# logging: "enabled"
# 亲和性(可选,分散在不同节点)
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: k8s-app
operator: In
values:
- fluent-bit-logging
topologyKey: kubernetes.io/hostname
containers:
- name: fluent-bit
image: registry.internal.company.com/fluent/fluent-bit:2.1.9
imagePullPolicy: IfNotPresent
# 环境变量
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: FLUENT_BIT_INTERVAL
value: "5"
# 资源限制
resources:
requests:
memory: "50Mi"
cpu: "10m"
limits:
memory: "200Mi"
cpu: "500m"
# 安全上下文
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
add:
- CHOWN
- DAC_OVERRIDE
- FOWNER
- SETGID
- SETUID
# 卷挂载
volumeMounts:
# 1. 主机日志目录(核心)
- name: varlog
mountPath: /var/log
readOnly: true # 只读挂载,更安全
# 2. Docker容器日志目录
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
# 3. 配置文件
- name: fluent-bit-config
mountPath: /fluent-bit/etc/
# 4. 检查点存储
- name: flb-storage
mountPath: /var/log/flb-storage/
# 5. K8S令牌(用于API访问)
- name: fluent-bit-token
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
readOnly: true
# 6. 时区配置(可选)
- name: localtime
mountPath: /etc/localtime
readOnly: true
# 健康检查
livenessProbe:
httpGet:
path: /api/v1/health
port: 2020
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /api/v1/health
port: 2020
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
# 生命周期钩子(优雅停止)
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10"]
# 初始化容器(可选,用于目录权限设置)
initContainers:
- name: init-log-dir
image: busybox:latest
command: ["sh", "-c", "mkdir -p /var/log/k8s-logs && chmod 755 /var/log/k8s-logs"]
securityContext:
runAsUser: 0
volumeMounts:
- name: varlog
mountPath: /var/log
# 卷定义
volumes:
# 1. 主机日志目录
- name: varlog
hostPath:
path: /var/log
type: Directory
# 2. Docker容器日志
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
type: Directory
# 3. CRI-O容器日志(如果使用CRI-O)
# - name: varlibcriocontainers
# hostPath:
# path: /var/log/containers
# type: Directory
# 4. 配置文件
- name: fluent-bit-config
configMap:
name: fluent-bit-config
# 5. 检查点存储
- name: flb-storage
hostPath:
path: /var/log/flb-storage
type: DirectoryOrCreate
# 6. K8S服务账户令牌
- name: fluent-bit-token
projected:
sources:
- serviceAccountToken:
audience: fluent-bit
expirationSeconds: 3600
path: token
# 7. 时区
- name: localtime
hostPath:
path: /etc/localtime
type: File
# 重启策略
restartPolicy: Always
terminationGracePeriodSeconds: 60
DaemonSet详解:
- updateStrategy:
-
RollingUpdate:滚动更新,确保服务不中断maxUnavailable: 1:一次只更新一个节点
- tolerations:
-
- 允许在控制平面节点运行,确保收集所有节点日志
- securityContext:
-
runAsNonRoot: true:非root用户运行,提高安全性readOnlyRootFilesystem: true:只读根文件系统- 最小权限原则,只添加必要的能力
- volumeMounts:
-
- 只读挂载主机日志目录,避免安全风险
- 检查点目录可写,用于存储状态
- probes:
-
- 健康检查确保服务可用性
- HTTP检查端点由Fluent Bit提供
- initContainers:
-
- 初始化日志目录,确保权限正确
Step 4: 创建Node上的日志管理配置
# 7-node-log-setup.sh(在每个Node上执行)
#!/bin/bash
# 1. 创建日志存储目录
LOG_DIR="/var/log/k8s-logs"
mkdir -p $LOG_DIR
chmod 755 $LOG_DIR
# 2. 设置目录所有权(如果使用非root用户运行Fluent Bit)
# chown -R 1000:1000 $LOG_DIR
# 3. 创建logrotate配置
cat > /etc/logrotate.d/k8s-pod-logs << 'EOF'
# Kubernetes Pod日志轮转配置
/var/log/k8s-logs/*.log {
# 轮转频率:daily(每日)、weekly(每周)、monthly(每月)
daily
# 保留多少份旧日志
rotate 30
# 压缩旧日志(gzip)
compress
# 延迟压缩(下一次轮转时压缩)
delaycompress
# 如果日志文件不存在也不报错
missingok
# 如果日志为空,不轮转
notifempty
# 创建新日志文件的权限
create 0644 root root
# 使用日期作为轮转文件后缀
dateext
# 日期格式
dateformat -%Y%m%d
# 共享脚本,只运行一次
sharedscripts
# 轮转后执行的脚本
postrotate
# 可以在这里通知Fluent Bit重新打开文件
# 但Fluent Bit会自动检测文件变化
# 清理超过60天的压缩日志
find /var/log/k8s-logs/ -name "*.log.*.gz" -mtime +60 -delete
# 可选:发送信号到Fluent Bit容器
# CONTAINER_ID=$(docker ps | grep fluent-bit | awk '{print $1}')
# docker kill -s USR1 $CONTAINER_ID 2>/dev/null || true
endscript
}
# Fluent Bit检查点文件轮转
/var/log/flb-storage/*.db {
weekly
rotate 4
compress
delaycompress
missingok
notifempty
create 0600 root root
}
EOF
# 4. 测试logrotate配置
logrotate -d /etc/logrotate.d/k8s-pod-logs
# 5. 创建每日清理任务(可选)
cat > /etc/cron.daily/clean-k8s-logs << 'EOF'
#!/bin/bash
# 清理90天前的日志文件
find /var/log/k8s-logs/ -name "*.log" -mtime +90 -delete
find /var/log/k8s-logs/ -name "*.log.*.gz" -mtime +180 -delete
EOF
chmod +x /etc/cron.daily/clean-k8s-logs
# 6. 检查磁盘空间(建议添加监控)
# df -h /var/log
echo "Node日志配置完成"
Step 5: 部署所有组件
# 按顺序应用所有配置
kubectl apply -f 1-fluent-bit-namespace.yaml
kubectl apply -f 2-fluent-bit-serviceaccount.yaml
kubectl apply -f 3-fluent-bit-clusterrole.yaml
kubectl apply -f 4-fluent-bit-clusterrolebinding.yaml
kubectl apply -f 5-fluent-bit-configmap.yaml
kubectl apply -f 6-fluent-bit-daemonset.yaml
# 验证部署
kubectl get daemonset -n logging
kubectl get pods -n logging -o wide
kubectl describe daemonset fluent-bit -n logging
# 查看Fluent Bit日志
kubectl logs -n logging -l k8s-app=fluent-bit-logging --tail=50
# 检查配置文件是否正确挂载
kubectl exec -n logging -it $(kubectl get pod -n logging -l k8s-app=fluent-bit-logging -o jsonpath='{.items[0].metadata.name}') -- cat /fluent-bit/etc/fluent-bit.conf
Step 6: 验证日志收集
# 1. 创建测试Pod
cat > test-pod.yaml << 'EOF'
apiVersion: v1
kind: Pod
metadata:
name: log-test-pod
labels:
app: log-test
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
- name: log-generator
image: busybox
command: ["sh", "-c"]
args:
- |
counter=0
while true; do
echo "Test log message $counter at $(date)" >> /proc/1/fd/1
counter=$((counter+1))
sleep 5
done
EOF
kubectl apply -f test-pod.yaml
# 2. 查看Pod所在节点
kubectl get pod log-test-pod -o wide
# 3. 登录到对应节点查看日志文件
# 假设Pod在node-1上
ssh node-1 "ls -la /var/log/k8s-logs/ | head -10"
ssh node-1 "tail -f /var/log/k8s-logs/*log-test-pod*.log"
# 4. 检查Fluent Bit指标
kubectl port-forward -n logging svc/fluent-bit 2020:2020
# 访问 http://localhost:2020/api/v1/metrics
# 5. 清理测试Pod
kubectl delete pod log-test-pod
四、监控与日志链路详细说明
数据流动全链路
监控数据流:
1. 数据产生层:
└── 容器应用 → 产生CPU、内存等指标
2. 数据暴露层:
├── cAdvisor(内置在kubelet)→ 收集容器指标,暴露/metrics端点
├── node-exporter(DaemonSet)→ 收集节点指标,暴露9100端口
└── kube-state-metrics(Deployment)→ 收集K8S对象状态,暴露8080端口
3. 服务发现层:
├── ServiceMonitor(CRD)→ 定义如何发现和抓取指标
└── Prometheus Operator → 动态更新Prometheus配置
4. 数据收集层:
└── Prometheus Server → 定期抓取指标,存储在TSDB中
5. 数据展示层:
└── Grafana → 查询Prometheus数据,可视化展示
日志数据流:
1. 日志产生:
└── 应用容器 → 输出到stdout/stderr
2. 日志收集(节点级):
├── Docker/containerd → 写入/var/lib/docker/containers/
├── Kubelet → 创建符号链接到/var/log/containers/
└── Fluent Bit(DaemonSet)→ 监控目录变化,读取新日志
3. 日志处理:
├── 解析:使用docker解析器处理JSON格式
├── 丰富:添加K8S元数据(Pod名、命名空间、标签等)
├── 过滤:可选的处理和过滤
└── 输出:格式化后写入本地文件
4. 日志存储:
└── 本地磁盘 → /var/log/k8s-logs/目录
5. 日志维护:
├── logrotate → 自动轮转和压缩旧日志
└── cron任务 → 定期清理过期日志
关键配置文件作用总结
Prometheus Stack配置文件:
|
配置文件 |
主要作用 |
关键参数 |
|
values.yaml |
Helm Chart配置总入口 |
镜像仓库、资源限制、存储配置 |
|
prometheusSpec |
Prometheus实例配置 |
retention(保留时间)、storageSpec(存储) |
|
serviceMonitorSelector |
服务发现范围 |
{}表示监控所有命名空间 |
|
additionalScrapeConfigs |
额外抓取配置 |
节点指标抓取规则 |
Fluent Bit配置文件:
|
配置文件 |
主要作用 |
关键参数 |
|
fluent-bit.conf |
主配置入口 |
Flush间隔、日志级别、HTTP服务 |
|
input-kubernetes.conf |
日志输入配置 |
Path(监控目录)、DB(检查点) |
|
filter-kubernetes.conf |
元数据过滤配置 |
Kube_URL(API地址)、Merge_Log(合并日志) |
|
output-file.conf |
日志输出配置 |
Path(输出目录)、Template(文件名模板) |
|
parsers.conf |
日志解析配置 |
docker解析器(处理JSON格式) |
五、动态扩缩容处理机制
Pod扩缩容处理:
当Pod数量变化时:
1. Pod创建:
- Kubelet创建容器 → 生成日志文件
- 符号链接到/var/log/containers/
- Fluent Bit通过inotify检测到新文件
- 开始跟踪并收集日志
2. Pod删除:
- 容器停止 → 日志文件不再更新
- Fluent Bit检测到文件inode变化
- 关闭文件句柄,停止收集
- 日志文件被kubelet清理
Node扩缩容处理:
当Node数量变化时:
1. Node加入:
- DaemonSet控制器检测到新Node
- 调度Fluent Bit Pod到新Node
- Pod启动,开始收集该Node上所有容器日志
- 自动发现现有和新创建的Pod日志
2. Node移除:
- DaemonSet控制器检测Node不可用
- Fluent Bit Pod被标记为终止
- 优雅停止,完成最后的日志刷新
- 日志文件保留在Node磁盘上(如果磁盘未格式化)
检查点机制(断点续传):
# Fluent Bit检查点文件位置
/var/log/flb-storage/
├── flb_kube.db # 记录每个日志文件的读取位置
└── flb_kube.db-shm # SQLite共享内存文件
# 作用:
# 1. 记录每个日志文件的读取偏移量
# 2. Fluent Bit重启后从上次位置继续读取
# 3. 避免重复收集或丢失日志
六、维护和排障指南
日常维护命令:
# 1. 查看监控组件状态
kubectl get pods -n monitoring
kubectl logs -n monitoring prometheus-prometheus-stack-prometheus-0 -c prometheus
# 2. 查看日志收集状态
kubectl get pods -n logging -o wide
kubectl logs -n logging -l k8s-app=fluent-bit-logging --tail=20
# 3. 检查磁盘使用
kubectl exec -n logging fluent-bit-xxxx -- df -h /var/log
# 4. 查看Prometheus抓取目标
kubectl port-forward -n monitoring svc/prometheus-operated 9090:9090
# 浏览器访问:http://localhost:9090/targets
# 5. 查看Fluent Bit指标
kubectl port-forward -n logging svc/fluent-bit 2020:2020
# 浏览器访问:http://localhost:2020/api/v1/metrics
常见问题排查:
问题1:Prometheus无法抓取指标
# 检查ServiceMonitor
kubectl get servicemonitor -n monitoring
# 检查Pod的/metrics端点
kubectl exec -it <pod-name> -- wget -qO- http://localhost:9090/metrics
# 检查网络策略
kubectl get networkpolicy -n monitoring
问题2:Fluent Bit无法收集日志
# 1. 检查Pod权限
kubectl auth can-i get pods --as=system:serviceaccount:logging:fluent-bit
# 2. 检查日志文件是否存在
kubectl exec -n logging fluent-bit-xxxx -- ls -la /var/log/containers/
# 3. 检查配置文件
kubectl exec -n logging fluent-bit-xxxx -- cat /fluent-bit/etc/fluent-bit.conf
# 4. 检查API连接
kubectl exec -n logging fluent-bit-xxxx -- curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://kubernetes.default.svc:443/api/v1/namespaces
# 5. 开启调试日志
# 修改ConfigMap,设置Log_Level为debug
问题3:磁盘空间不足
# 1. 检查各节点磁盘使用
for node in $(kubectl get nodes -o name | cut -d'/' -f2); do
echo "=== $node ==="
ssh $node "df -h /var/log"
done
# 2. 清理旧日志
# 调整logrotate配置,减少保留天数
# 或手动清理:find /var/log/k8s-logs/ -name "*.log" -mtime +30 -delete
# 3. 调整Prometheus数据保留时间
# 修改values.yaml中的retention参数
七、性能优化建议
监控优化:
# 1. 调整抓取间隔
prometheusSpec:
scrapeInterval: "60s" # 从30s调整为60s,减少负载
evaluationInterval: "60s"
# 2. 限制收集的指标
kube-state-metrics:
metricLabelsAllowlist:
# 只收集必要的标签,减少数据量
# 3. 启用指标压缩
prometheusSpec:
enableCompression: true
日志收集优化:
# 1. 调整缓冲区大小
Mem_Buf_Limit 10MB # 根据内存情况调整
# 2. 调整刷新间隔
Flush 10 # 从5秒调整为10秒,减少IO
# 3. 选择性收集日志
# 通过Pod标签过滤
[FILTER]
Name grep
Match *
Exclude kubernetes.labels.app in (debug, test)
# 4. 使用更高效的压缩
compress gzip
八、安全加固
1. 网络策略:
# network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitoring
namespace: monitoring
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- protocol: TCP
port: 9090 # Prometheus
- protocol: TCP
port: 3000 # Grafana
2. 服务账户限制:
# 限制Fluent Bit的权限,只允许读取日志
rules:
- apiGroups: [""]
resources:
- pods
- pods/logs
verbs: ["get", "list", "watch"]
# 不再需要namespaces权限,如果不需要按命名空间过滤
3. 审计日志:
# 启用Kubernetes审计日志
# 在kube-apiserver配置中添加:
--audit-log-path=/var/log/kubernetes/audit.log
--audit-log-maxage=30
--audit-log-maxbackup=10
--audit-log-maxsize=100
九、备份和恢复
监控数据备份:
# 1. 备份Prometheus数据
# Prometheus数据存储在PVC中,可以定期备份PVC快照
# 2. 备份Grafana配置
# Grafana配置存储在ConfigMap中
kubectl get configmap -n monitoring -l grafana_dashboard -o yaml > grafana-dashboards-backup.yaml
kubectl get configmap -n monitoring -l grafana_datasource -o yaml > grafana-datasources-backup.yaml
日志数据备份(如果需要):
# 创建日志备份任务
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: log-backup
namespace: logging
spec:
schedule: "0 1 * * *" # 每天凌晨1点
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: alpine
command:
- /bin/sh
- -c
- |
# 备份到NFS或其他共享存储
BACKUP_DIR="/backup/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR
cp -r /var/log/k8s-logs/* $BACKUP_DIR/ || true
echo "Backup completed at $(date)"
volumeMounts:
- name: host-log
mountPath: /var/log/k8s-logs
- name: backup-volume
mountPath: /backup
restartPolicy: OnFailure
volumes:
- name: host-log
hostPath:
path: /var/log/k8s-logs
- name: backup-volume
nfs:
server: nfs-server.internal
path: /backup/k8s-logs
这个详细方案提供了从部署到维护的完整指导,每个配置都有详细说明,可以根据实际业务需求进行调整。
更多推荐

所有评论(0)