Kubernetes 日志与监控架构
概述
在 Kubernetes 集群中,日志和监控是保障服务可用性和排查问题的重要基础设施。本文档深入剖析 Kubernetes 的日志收集机制、监控体系以及相关的最佳实践。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| ┌─────────────────────────────────────────────────────────────────────────┐ │ Kubernetes 日志与监控架构图 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 应用层 │ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ │ │ App A │ │ App B │ │ App C │ │ ... │ │ │ │ │ │ stdout │ │ stdout │ │ file │ │ ... │ │ │ │ │ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ │ │ │ │ │ │ │ │ └───────┼────────────┼────────────┼────────────┼────────────────────┘ │ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 容器运行时层 │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ │ │ journald │ │ json-log │ │ file │ │ │ │ │ │ (Pod) │ │ (Pod) │ │ (Pod) │ │ │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 节点层 │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ │ │ kubelet │ │ Fluent Bit │ │ cAdvisor │ │ │ │ │ │ (日志聚合) │ │ (日志收集) │ │ (指标采集) │ │ │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 集群层 │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ │ │ Loki/ │ │ Prometheus │ │ Alert- │ │ │ │ │ │ Elasticsearch│ │ Stack │ │ manager │ │ │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────┘
|
1. 容器日志机制
1.1 容器日志类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| ┌─────────────────────────────────────────────────────────────────────────┐ │ 容器日志类型 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ stdout/stderr (标准输出/错误) │ │ │ │ ──────────────────────────────────────────────────────────── │ │ │ │ │ │ │ │ containerd: /var/log/pods/<namespace>_<pod>_<uid>/<container>/ │ │ │ │ └── *.log │ │ │ │ │ │ │ │ json-file 驱动 (Docker): /var/lib/docker/containers/<id>/ │ │ │ │ └── <id>-json.log │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 应用程序文件日志 │ │ │ │ ──────────────────────────────────────────────────────────── │ │ │ │ │ │ │ │ 写入容器内的文件: │ │ │ │ - 挂载 Volume 保存 │ │ │ │ - HostPath 挂载到宿主机 │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ journald 日志 (系统服务) │ │ │ │ ──────────────────────────────────────────────────────────── │ │ │ │ │ │ │ │ kubelet、docker、containerd 等系统服务日志 │ │ │ │ journalctl -u kubelet -f │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────┘
|
1.2 kubelet 日志管理
1 2 3 4 5 6 7 8 9 10 11
|
func getContainerLogsPath(podUID, containerName, restartCount int) string { return filepath.Join(podLogsRootDirectory, podUID, containerName, fmt.Sprintf("%d.log", restartCount)) }
|
1.3 日志驱动配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
{ "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "5", "compress": "true" } }
[plugins."io.containerd.grpc.v1.cri"] [plugins."io.containerd.grpc.v1.cri".containerd] default_runtime_name = "runc" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] LogDriver = "json-file" [plugins."io.containerd.grpc.v1.cri".containerd.default_runtime_runc.options] LogPath = "/var/log/container/" LogSizeMax = 100000000
|
2. 日志收集方案
2.1 节点级日志收集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| ┌─────────────────────────────────────────────────────────────────────────┐ │ 节点级日志收集架构 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ Node │ │ ┌───────────────────────────────────────────────────────────────┐ │ │ │ │ │ │ │ /var/log/pods/ /var/log/containers/ │ │ │ │ ┌───────────┐ ┌───────────┐ │ │ │ │ │ nginx │ │ nginx.log │ │ │ │ │ │ └── *.log │ ─────────► │ │ │ │ │ │ └───────────┘ └─────┬─────┘ │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ ┌───────────────┐ │ │ │ │ │ Fluent Bit │ │ │ │ │ │ (DaemonSet) │ │ │ │ │ └───────┬───────┘ │ │ │ │ │ │ │ │ │ ┌──────────────────────┼──────────────────────┐ │ │ │ │ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ │ │ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐│ │ │ │ │ Loki │ │ Elasticsearch │ │ S3 ││ │ │ │ │ │ │ │ │ ││ │ │ │ └───────────────┘ └───────────────┘ └───────────────┘│ │ │ │ │ │ │ └───────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────┘
|
2.2 Fluent Bit 部署配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| apiVersion: v1 kind: ServiceAccount metadata: name: fluent-bit namespace: logging --- apiVersion: apps/v1 kind: DaemonSet metadata: name: fluent-bit namespace: logging spec: selector: matchLabels: name: fluent-bit template: metadata: labels: name: fluent-bit spec: serviceAccountName: fluent-bit containers: - name: fluent-bit image: fluent/fluent-bit:2.0.0 ports: - containerPort: 2020 volumeMounts: - name: varlog mountPath: /var/log - name: varlogpods mountPath: /var/log/pods readOnly: true - name: config mountPath: /fluent-bit/etc resources: limits: memory: 100Mi cpu: 100m volumes: - name: varlog hostPath: path: /var/log - name: varlogpods hostPath: path: /var/log/pods - name: config configMap: name: fluent-bit-config ---
apiVersion: v1 kind: ConfigMap metadata: name: fluent-bit-config namespace: logging data: fluent-bit.conf: | [SERVICE] Flush 5 Log_Level info Daemon off
[INPUT] Name tail Path /var/log/containers/*.log Parser docker Tag kube.containers.* Refresh_Interval 5
[FILTER] Name kubernetes Match kube.containers.* Kube_URL https://kubernetes.default.svc:443 Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
[OUTPUT] Name loki Match * Host loki.logging.svc.cluster.local Port 3100 TenantID {{.TenantID}}
|
2.3 应用日志最佳实践
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| apiVersion: v1 kind: Pod metadata: name: myapp spec: containers: - name: myapp image: myapp:latest command: ["myapp", "--log-format=json"] resources: limits: memory: "128Mi" cpu: "100m" volumeMounts: - name: app-logs mountPath: /var/log/myapp volumes: - name: app-logs emptyDir: {} ---
{ "timestamp": "2024-01-15T10:30:00Z", "level": "INFO", "message": "Request processed", "request_id": "abc-123", "user_id": "user-1", "duration_ms": 150, "service": "myapp", "version": "v1.2.3" }
|
3. 监控体系
3.1 Prometheus 架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| ┌─────────────────────────────────────────────────────────────────────────┐ │ Prometheus 监控架构 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ Prometheus Server │ │ │ │ │ │ │ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │ │ │ │ Scrape │ │ Storage │ │ HTTP │ │ Alert │ │ │ │ │ │ Manager │ │ (TSDB) │ │ Server │ │ Manager │ │ │ │ │ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │ │ │ │ │ │ │ │ │ │ │ │ └──────────────┬┴──────────────┴──────────────┘ │ │ │ │ ▼ │ │ │ │ ┌───────────────┐ │ │ │ │ │ Prometheus │ │ │ │ │ │ TSDB │ │ │ │ │ │ /prometheus │ │ │ │ │ └───────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ┌─────────────────────┼─────────────────────┐ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │ │ kube- │ │ Node │ │ App │ │ │ │ apiserver │ │ Exporter │ │ Metrics │ │ │ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │ │ │ │ │ │ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │ │ kubelet │ │ cAdvisor │ │ Sidecar │ │ │ │ + cAdvisor│ │ │ │ Exporter │ │ │ └───────────┘ └───────────┘ └───────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────┘
|
3.2 Prometheus Operator 部署
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: name: k8s namespace: monitoring spec: replicas: 2 retention: 15d serviceAccountName: prometheus serviceMonitorSelector: matchLabels: team: k8s ruleSelector: matchLabels: role: alert-rules resources: requests: memory: 400Mi storage: volumeClaimTemplate: spec: storageClassName: ssd resources: requests: storage: 10Gi ---
apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: myapp namespace: monitoring labels: team: k8s spec: selector: matchLabels: app: myapp endpoints: - port: metrics interval: 15s path: /metrics namespaceSelector: matchNames: - production
|
3.3 指标类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| # Prometheus 指标类型
# 1. Counter - 只能递增的计数器 # 用途:请求数、错误数、完成任务数 http_requests_total{method="GET", status="200"}
# 2. Gauge - 可以任意增减的值 # 用途:CPU 使用率、内存使用量、连接数 container_cpu_usage_seconds_total{container="nginx"}
# 3. Histogram - 直方图,统计分布 # 用途:请求延迟、响应大小 http_request_duration_seconds_bucket{le="0.1"} http_request_duration_seconds_bucket{le="0.5"} http_request_duration_seconds_bucket{le="1.0"}
# 4. Summary - 分位数,统计延迟 # 用途:延迟的 50/90/99 分位数 http_request_duration_seconds{quantile="0.9"}
# 常用 PromQL 查询 # CPU 使用率 rate(container_cpu_usage_seconds_total{name="nginx"}[5m]) # 内存使用量 container_memory_working_set_bytes{name="nginx"} # 请求 QPS rate(http_requests_total{service="myapp"}[5m]) # 错误率 rate(http_requests_total{service="myapp", status=~"5.."}[5m])
|
4. Kubernetes 核心指标
4.1 kube-state-metrics
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| apiVersion: apps/v1 kind: Deployment metadata: name: kube-state-metrics namespace: monitoring spec: selector: matchLabels: k8s-app: kube-state-metrics template: metadata: labels: k8s-app: kube-state-metrics spec: containers: - name: kube-state-metrics image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.9.0 ports: - name: http containerPort: 8080 ---
kube_pod_info{pod="nginx-7fb96c846b-abc12", namespace="default", pod_ip="10.244.1.5"} kube_pod_status_phase{phase="Running"} kube_pod_container_status_restarts_total kube_pod_container_resource_requests{resource="cpu"} kube_pod_container_resource_limits{resource="memory"}
kube_deployment_spec_replicas kube_deployment_status_replicas_available kube_deployment_status_replicas_unavailable
kube_node_info{node="node-1", zone="us-east-1a"} kube_node_status_allocatable{resource="cpu"} kube_node_status_capacity{resource="memory"} kube_node_status_condition{condition="Ready"}
|
4.2 Node Exporter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| 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 containers: - name: node-exporter image: prom/node-exporter:v1.6.0 ports: - containerPort: 9100 hostPort: 9100 command: - /bin/node_exporter - --path.procfs=/host/proc - --path.sysfs=/host/sys - --path.rootfs=/host volumeMounts: - name: proc mountPath: /host/proc readOnly: true - name: sys mountPath: /host/sys readOnly: true volumes: - name: proc hostPath: path: /proc - name: sys hostPath: path: /sys ---
node_cpu_seconds_total{mode="user|idle|system|irq|softirq"} node_load1 / node_load5 / node_load15
node_memory_MemTotal_bytes node_memory_MemAvailable_bytes node_memory_MemCached_bytes node_memory_MemBuffers_bytes
node_disk_io_time_seconds_total{device="sda"} node_disk_read_bytes_total{device="sda"} node_disk_written_bytes_total{device="sda"} node_filesystem_avail_bytes{mountpoint="/"}
node_network_receive_bytes_total{device="eth0"} node_network_transmit_bytes_total{device="eth0"}
|
4.3 cAdvisor 指标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
container_cpu_usage_seconds_total container_cpu_cfs_throttled_seconds_total container_cpu_system_seconds_total
container_memory_working_set_bytes container_memory_rss_bytes container_memory_cache_bytes container_memory_swap_bytes
container_network_receive_bytes_total container_network_receive_packets_dropped_total container_network_transmit_bytes_total container_network_transmit_packets_dropped_total
container_fs_reads_bytes_total container_fs_writes_bytes_total container_fs_usage_bytes
|
5. 告警系统
5.1 Alertmanager 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| apiVersion: monitoring.coreos.com/v1 kind: Alertmanager metadata: name: main namespace: monitoring spec: replicas: 2 configSecret: alertmanager-config --- apiVersion: v1 kind: Secret metadata: name: alertmanager-config namespace: monitoring type: Opaque stringData: alertmanager.yml: | global: resolve_timeout: 5m smtp_smarthost: 'smtp.example.com:587' smtp_from: 'alertmanager@example.com'
route: group_by: ['alertname', 'severity'] group_wait: 30s group_interval: 5m repeat_interval: 4h receiver: 'default-receiver' routes: - match: severity: critical receiver: 'critical-receiver' group_wait: 10s
receivers: - name: 'default-receiver' email_configs: - to: 'team@example.com'
- name: 'critical-receiver' slack_configs: - api_url: 'https://hooks.slack.com/services/xxx' channel: '#alerts-critical' pagerduty_configs: - service_key: 'xxx'
|
5.2 告警规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: k8s-alerts namespace: monitoring labels: role: alert-rules spec: groups: - name: kubernetes-apps interval: 30s rules: - alert: PodHighCpuUsage expr: | sum(rate(container_cpu_usage_seconds_total{container!=""}[5m])) by (namespace, pod) / sum(container_spec_cpu_quota{container!=""}/container_spec_cpu_period{container!=""}) by (namespace, pod) > 0.8 for: 10m labels: severity: warning annotations: summary: "Pod CPU 使用率超过 80%" description: "Pod {{ $labels.namespace }}/{{ $labels.pod }} CPU 使用率超过 80%"
- alert: PodMemoryUsageHigh expr: | sum(container_memory_working_set_bytes{container!=""}) by (namespace, pod) / sum(container_spec_memory_limit_bytes{container!=""}) by (namespace, pod) > 0.9 for: 5m labels: severity: warning annotations: summary: "Pod 内存使用率超过 90%" description: "Pod {{ $labels.namespace }}/{{ $labels.pod }} 内存使用率超过 90%"
- alert: PodContainerRestarting expr: increase(kube_pod_container_status_restarts_total[1h]) > 5 for: 2m labels: severity: warning annotations: summary: "Pod 容器重启次数过多" description: "Pod {{ $labels.namespace }}/{{ $labels.pod }} 在过去 1 小时内重启超过 5 次"
- alert: DeploymentReplicasUnavailable expr: | kube_deployment_status_replicas_available{deployment=~".+"} < kube_deployment_spec_replicas{deployment=~".+"} for: 10m labels: severity: warning annotations: summary: "Deployment 副本不可用" description: "Deployment {{ $labels.namespace }}/{{ $labels.deployment }} 有 {{ $value }} 个副本不可用"
- name: kubernetes-resources interval: 30s rules: - alert: NodeNotReady expr: kube_node_status_condition{condition="Ready",status="true"} == 0 for: 5m labels: severity: critical annotations: summary: "节点 NotReady" description: "节点 {{ $labels.node }} 状态为 NotReady"
- alert: NodeHighMemoryUsage expr: | (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) > 0.9 for: 5m labels: severity: warning annotations: summary: "节点内存压力" description: "节点 {{ $labels.node }} 内存使用率超过 90%"
- alert: NodeHighDiskUsage expr: | (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) < 0.1 for: 5m labels: severity: warning annotations: summary: "节点磁盘空间不足" description: "节点 {{ $labels.node }} 根分区可用空间低于 10%"
|
6. 可视化与仪表板
6.1 Grafana Dashboard
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| apiVersion: apps/v1 kind: Deployment metadata: name: grafana namespace: monitoring spec: selector: matchLabels: app: grafana template: metadata: labels: app: grafana spec: containers: - name: grafana image: grafana/grafana:10.0.0 ports: - name: http containerPort: 3000 env: - name: GF_SECURITY_ADMIN_USER value: admin - name: GF_SECURITY_ADMIN_PASSWORD valueFrom: secretKeyRef: name: grafana-secret key: password volumeMounts: - name: grafana-storage mountPath: /var/lib/grafana - name: grafana-dashboards mountPath: /etc/grafana/provisioning/dashboards resources: requests: cpu: 100m memory: 200Mi volumes: - name: grafana-storage persistentVolumeClaim: claimName: grafana-pvc - name: grafana-dashboards configMap: name: grafana-dashboards ---
{ "dashboard": { "title": "Kubernetes Cluster Overview", "panels": [ { "title": "CPU Usage", "type": "graph", "targets": [ { "expr": "sum(rate(container_cpu_usage_seconds_total[5m])) by (namespace)", "legendFormat": "{{namespace}}" } ] }, { "title": "Memory Usage", "type": "graph", "targets": [ { "expr": "sum(container_memory_working_set_bytes) by (namespace) / 1024 / 1024", "legendFormat": "{{namespace}} - MB" } ] }, { "title": "Pod Count", "type": "stat", "targets": [ { "expr": "sum(kube_pod_info) by (namespace)", "legendFormat": "{{namespace}}" } ] } ] } }
|
6.2 Kubernetes Dashboard
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| apiVersion: v1 kind: Secret metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard-csrf namespace: kubernetes-dashboard type: Opaque --- apiVersion: apps/v1 kind: Deployment metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kubernetes-dashboard spec: replicas: 1 selector: matchLabels: k8s-app: kubernetes-dashboard template: metadata: labels: k8s-app: kubernetes-dashboard spec: containers: - name: kubernetes-dashboard image: kubernetesui/dashboard:v2.7.0 ports: - containerPort: 8443 protocol: TCP args: - --auto-generate-certificates - --namespace=kubernetes-dashboard volumeMounts: - name: kubernetes-dashboard-certs mountPath: /certs resources: limits: cpu: 250m memory: 256Mi volumes: - name: kubernetes-dashboard-certs secret: secretName: kubernetes-dashboard-certs
|
7. 关键源码路径
| 组件 |
路径 |
| kubelet 日志 |
pkg/kubelet/kuberuntime/logs/ |
| cAdvisor |
pkg/kubelet/cadvisor/ |
| kube-state-metrics |
staging/src/k8s.io/kube-state-metrics/ |
| Metrics Server |
staging/src/k8s.io/metrics/ |
| Prometheus |
github.com/prometheus/prometheus |
| Alertmanager |
github.com/prometheus/alertmanager |
面试题
基础题
1. Kubernetes 有哪些日志存储方式?
- 容器日志到 stdout/stderr:由容器运行时保存到文件
- 应用文件日志:写入挂载的 Volume
- journald:系统服务日志
- Kubernetes 事件:记录到 etcd
2. 如何查看 Pod 的日志?
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| kubectl logs <pod-name>
kubectl logs -f <pod-name>
kubectl logs <pod-name> -c <container-name>
kubectl logs --previous <pod-name>
kubectl logs <pod-name> --all-containers=true
|
3. Prometheus 的四种指标类型是什么?
- Counter:只能递增的计数器
- Gauge:可任意增减的值
- Histogram:直方图,统计分布
- Summary:分位数统计
4. kube-state-metrics 的作用是什么?
kube-state-metrics 暴露 Kubernetes 对象的指标:
- Pod/Deployment/StatefulSet 状态
- Node 资源容量和状态
- PVC 绑定状态
- Service 信息
5. cAdvisor 采集哪些指标?
- 容器 CPU 使用率
- 容器内存使用量
- 容器网络流量
- 容器文件系统使用
- 容器进程数
中级题
6. 如何搭建一个完整的 Kubernetes 监控体系?
- 部署 Prometheus Operator:使用 CRD 管理 Prometheus
- 部署 node-exporter:采集节点指标
- 部署 kube-state-metrics:采集 Kubernetes 对象状态
- 配置 ServiceMonitor:自动发现监控目标
- 部署 Alertmanager:处理告警
- 部署 Grafana:可视化展示
7. 如何排查 Pod 日志收集问题?
- 检查 Pod 是否正常输出日志
- 检查日志文件是否存在
- 检查 Fluent Bit/Fluentd 配置
- 检查网络连通性
- 检查后端存储是否正常
8. 如何设置合理的告警规则?
- 基于 SLO 设置:如错误率、延迟分位数
- 渐进式告警:先 warning 再 critical
- 避免告警风暴:使用 grouping 和抑制
- 设置合理的 for:避免瞬时抖动
- 定期审查:移除无效告警
9. 如何优化日志存储成本?
- 日志压缩:开启 gzip 压缩
- 分层存储:热数据存 SSD,冷数据存对象存储
- 日志保留策略:设置合理的保留周期
- 采样:高流量应用采样存储
- 去重:避免重复日志
10. Prometheus 与 Kubernetes 如何集成?
- 服务发现:通过 kube-apiserver 发现 Pod、Service、Endpoints
- RBAC:Prometheus 需要读取 Kubernetes 资源的权限
- 指标标签:自动添加 namespace、pod、container 等标签
- Relabeling:重写和过滤指标标签
高级题
11. 如何实现多集群监控?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: name: federation-global spec: serviceMonitorSelector: matchLabels: team: federation endpoints: - tlsConfig: caFile: /etc/prometheus/certs/ca.crt certFile: /etc/prometheus/certs/cert.crt keyFile: /etc/prometheus/certs/key.key staticConfigs: - targets: - prometheus.cluster1:9090 - prometheus.cluster2:9090
remoteWrite: - url: https://central-prometheus/api/v1/write bearerTokenFile: /var/run/secrets/prometheus/token
|
12. 如何实现应用级别的自定义指标?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
|
import "github.com/prometheus/client_golang/prometheus" import "github.com/prometheus/client_golang/prometheus/promhttp"
var ( httpRequestsTotal = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total number of HTTP requests", }, []string{"method", "status", "endpoint"}, )
httpRequestDuration = prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: "http_request_duration_seconds", Help: "HTTP request latency distribution", Buckets: []float64{0.01, 0.05, 0.1, 0.5, 1, 5}, }, []string{"method", "endpoint"}, )
activeRequests = prometheus.NewGauge( prometheus.GaugeOpts{ Name: "http_active_requests", Help: "Number of active HTTP requests", }, ) )
func init() { prometheus.MustRegister(httpRequestsTotal) prometheus.MustRegister(httpRequestDuration) prometheus.MustRegister(activeRequests) }
func handleRequest(w http.ResponseWriter, r *http.Request) { timer := prometheus.NewTimer(httpRequestDuration.WithLabelValues(r.Method)) defer timer.ObserveDuration()
activeRequests.Inc() defer activeRequests.Dec()
httpRequestsTotal.WithLabelValues(r.Method, "200").Inc() }
func main() { http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":8080", nil) }
|
13. 如何设计 SLO 和 SLI?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
apiVersion: sloth.dev/v1 kind: SLO metadata: name: myapp-availability spec: service: myapp sli: plugin: id: prometheus/availability options: total_metric: http_requests_total error_metric: http_requests_total{status=~"5.."} objectives: - ratio: 0.999 window: 30d
---
|
场景题
14. 如何排查 Kubernetes 集群性能问题?
- 检查节点状态:
kubectl top nodes
- 检查 Pod 资源:
kubectl top pods
- 查看组件指标:Prometheus 查询 kube-apiserver、kubelet、etcd 指标
- 检查网络:是否有网络延迟或丢包
- 分析瓶颈:CPU、内存、磁盘 IO、网络
- 检查日志:组件日志中是否有异常
15. 如何设置合理的资源请求和限制?
- 参考历史数据:使用 Prometheus 观察实际使用量
- 设置缓冲:请求设置 P70,限制设置 P95
- 考虑峰值:业务高峰期可能有突发流量
- 监控利用率:保持 70-80% 的资源利用率
- 使用 VPA:Vertical Pod Autoscaler 自动调整
16. 如何实现日志的多租户隔离?
- 日志标签隔离:每个租户有独立的 label
- Loki 多租户模式:开启 authentication
- Grafana 多组织:隔离不同租户的 Dashboard
- Storage 隔离:不同租户使用不同的存储后端
- RBAC 控制:限制访问日志查询接口