O-2.1: OTEL Collector DaemonSet (filelog receiver) - 收集所有 K3s 節點 Pod stdout/stderr → SigNoz ClickHouse - CRI log parser (Go time layout for +08:00 timezone) - filter processor 排除 kube-system debug noise - observability namespace PSA privileged (log 目錄需 root) - 資源限制: 50m-200m CPU / 64-128Mi Memory O-2.2: kubernetes-event-exporter - K8s Event → 結構化 JSON Log → SigNoz - Warning/Error 全量保留, Normal 過濾高頻事件 - 解決: Event 預設僅保留 ~1hr 的致命盲區 O-3: Prometheus remote_write 配置模板 - 白名單: ~50 關鍵 metric series (node/container/kube/api/db) - 目標: 90 天長期儲存於 SigNoz ClickHouse 已部署驗證: 3 Pod Running, 0 error, filelog 正常監控所有 namespace Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
158 lines
4.6 KiB
YAML
158 lines
4.6 KiB
YAML
# =============================================================================
|
||
# Kubernetes Event Exporter - Phase O-2.2
|
||
# =============================================================================
|
||
# 建立者: Claude Code (首席架構師)
|
||
# 日期: 2026-04-02 (台北時間)
|
||
# 用途: 將 K8s Event 轉為結構化 Log 送往 SigNoz,保留 30 天
|
||
# 解決: K8s Event 預設僅保留 ~1 小時的致命盲區
|
||
# =============================================================================
|
||
---
|
||
apiVersion: v1
|
||
kind: ServiceAccount
|
||
metadata:
|
||
name: event-exporter
|
||
namespace: observability
|
||
---
|
||
apiVersion: rbac.authorization.k8s.io/v1
|
||
kind: ClusterRole
|
||
metadata:
|
||
name: event-exporter
|
||
rules:
|
||
- apiGroups: [""]
|
||
resources: ["events"]
|
||
verbs: ["get", "watch", "list"]
|
||
- apiGroups: [""]
|
||
resources: ["namespaces"]
|
||
verbs: ["get", "watch", "list"]
|
||
---
|
||
apiVersion: rbac.authorization.k8s.io/v1
|
||
kind: ClusterRoleBinding
|
||
metadata:
|
||
name: event-exporter
|
||
roleRef:
|
||
apiGroup: rbac.authorization.k8s.io
|
||
kind: ClusterRole
|
||
name: event-exporter
|
||
subjects:
|
||
- kind: ServiceAccount
|
||
name: event-exporter
|
||
namespace: observability
|
||
---
|
||
apiVersion: v1
|
||
kind: ConfigMap
|
||
metadata:
|
||
name: event-exporter-config
|
||
namespace: observability
|
||
data:
|
||
config.yaml: |
|
||
# Phase O-2.2: K8s Event → SigNoz (OTLP HTTP)
|
||
logLevel: info
|
||
logFormat: json
|
||
route:
|
||
routes:
|
||
# Warning 和 Error 事件: 全量保留 (RCA 關鍵資料)
|
||
- match:
|
||
- receiver: signoz-warning
|
||
drop:
|
||
- type: "Normal"
|
||
reason: "Scheduled"
|
||
- type: "Normal"
|
||
reason: "Pulling"
|
||
- type: "Normal"
|
||
reason: "Pulled"
|
||
- type: "Normal"
|
||
reason: "Created"
|
||
- type: "Normal"
|
||
reason: "Started"
|
||
# Normal 事件中的關鍵類型: 選擇性保留
|
||
- match:
|
||
- receiver: signoz-normal
|
||
drop:
|
||
- type: "Warning"
|
||
receivers:
|
||
- name: signoz-warning
|
||
webhook:
|
||
endpoint: http://192.168.0.188:24318/v1/logs
|
||
headers:
|
||
Content-Type: application/json
|
||
layout:
|
||
severity: "{{ .Type }}"
|
||
body: "{{ .Message }}"
|
||
attributes:
|
||
k8s.event.reason: "{{ .Reason }}"
|
||
k8s.event.type: "{{ .Type }}"
|
||
k8s.event.action: "{{ .Action }}"
|
||
k8s.event.count: "{{ .Count }}"
|
||
k8s.namespace.name: "{{ .InvolvedObject.Namespace }}"
|
||
k8s.object.kind: "{{ .InvolvedObject.Kind }}"
|
||
k8s.object.name: "{{ .InvolvedObject.Name }}"
|
||
k8s.event.source.component: "{{ .Source.Component }}"
|
||
k8s.event.source.host: "{{ .Source.Host }}"
|
||
k8s.event.first_timestamp: "{{ .FirstTimestamp }}"
|
||
k8s.event.last_timestamp: "{{ .LastTimestamp }}"
|
||
- name: signoz-normal
|
||
webhook:
|
||
endpoint: http://192.168.0.188:24318/v1/logs
|
||
headers:
|
||
Content-Type: application/json
|
||
layout:
|
||
severity: "Normal"
|
||
body: "{{ .Message }}"
|
||
attributes:
|
||
k8s.event.reason: "{{ .Reason }}"
|
||
k8s.event.type: "{{ .Type }}"
|
||
k8s.namespace.name: "{{ .InvolvedObject.Namespace }}"
|
||
k8s.object.kind: "{{ .InvolvedObject.Kind }}"
|
||
k8s.object.name: "{{ .InvolvedObject.Name }}"
|
||
---
|
||
apiVersion: apps/v1
|
||
kind: Deployment
|
||
metadata:
|
||
name: event-exporter
|
||
namespace: observability
|
||
labels:
|
||
app.kubernetes.io/name: event-exporter
|
||
phase: o-2
|
||
spec:
|
||
replicas: 1
|
||
selector:
|
||
matchLabels:
|
||
app.kubernetes.io/name: event-exporter
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app.kubernetes.io/name: event-exporter
|
||
spec:
|
||
serviceAccountName: event-exporter
|
||
# PSA restricted 合規
|
||
securityContext:
|
||
runAsNonRoot: true
|
||
runAsUser: 65534
|
||
seccompProfile:
|
||
type: RuntimeDefault
|
||
containers:
|
||
- name: event-exporter
|
||
image: ghcr.io/resmoio/kubernetes-event-exporter:v1.7
|
||
args:
|
||
- -conf=/etc/event-exporter/config.yaml
|
||
securityContext:
|
||
allowPrivilegeEscalation: false
|
||
readOnlyRootFilesystem: true
|
||
capabilities:
|
||
drop: ["ALL"]
|
||
resources:
|
||
requests:
|
||
cpu: 20m
|
||
memory: 32Mi
|
||
limits:
|
||
cpu: 100m
|
||
memory: 64Mi
|
||
volumeMounts:
|
||
- name: config
|
||
mountPath: /etc/event-exporter
|
||
readOnly: true
|
||
volumes:
|
||
- name: config
|
||
configMap:
|
||
name: event-exporter-config
|