一、整体架构设计说明

架构拓扑

┌─────────────────────────────────────────────────────────────────────────┐
│                           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

配置项详解

  1. imageRegistry:内网镜像仓库地址,需提前导入所有需要的镜像
  2. retention:监控数据保留时间,根据存储容量调整
  3. storageSpec:Prometheus数据存储配置,使用PVC持久化
  4. serviceMonitorSelector:空选择器表示监控所有ServiceMonitor
  5. additionalScrapeConfigs:额外的抓取配置,如节点指标
  6. 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权限详解

  1. namespaces:获取命名空间信息,用于日志分类
  2. pods:获取Pod信息,用于添加元数据
  3. pods/logs:核心权限,允许读取Pod日志
  4. 只读权限:安全最佳实践,避免权限过大
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

配置文件详解

  1. SERVICE段
    • Flush 5:每5秒刷新缓冲区,平衡性能和数据完整性
    • storage.path:检查点存储,重启后从上次位置继续
  1. INPUT段(tail插件)
    • Path /var/log/containers/*.log:监控K8S容器日志目录
    • DB /var/log/flb_kube.db:记录文件读取位置,实现断点续传
    • Ignore_Older 24h:忽略旧文件,提高启动速度
  1. FILTER段(kubernetes插件)
    • 从K8S API获取Pod元数据(名称、命名空间、标签等)
    • Merge_Log On:将原始日志合并到新字段
    • Labels On:包含Pod标签,便于分类
  1. 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详解

  1. updateStrategy
    • RollingUpdate:滚动更新,确保服务不中断
    • maxUnavailable: 1:一次只更新一个节点
  1. tolerations
    • 允许在控制平面节点运行,确保收集所有节点日志
  1. securityContext
    • runAsNonRoot: true:非root用户运行,提高安全性
    • readOnlyRootFilesystem: true:只读根文件系统
    • 最小权限原则,只添加必要的能力
  1. volumeMounts
    • 只读挂载主机日志目录,避免安全风险
    • 检查点目录可写,用于存储状态
  1. probes
    • 健康检查确保服务可用性
    • HTTP检查端点由Fluent Bit提供
  1. 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

这个详细方案提供了从部署到维护的完整指导,每个配置都有详细说明,可以根据实际业务需求进行调整。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐