k8s部署loki3.6.10监控pod日志

运维小白 43 阅读 云原生

部署loki(如果grafana跟loki在一个集群,将service改成ClusterIP)

# 1. Namespace
apiVersion: v1
kind: Namespace
metadata:
  name: loki
  labels:
    app.kubernetes.io/name: loki

---
# 2. Loki ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: loki-config
  namespace: loki
  labels:
    app.kubernetes.io/name: loki
data:
  loki.yaml: |
    auth_enabled: false

    server:
      http_listen_port: 3100
      grpc_listen_port: 9096
      log_level: info

    common:
      instance_addr: 0.0.0.0
      path_prefix: /loki
      storage:
        filesystem:
          chunks_directory: /loki/chunks
          rules_directory: /loki/rules
      replication_factor: 1
      ring:
        kvstore:
          store: inmemory

    query_range:
      results_cache:
        cache:
          embedded_cache:
            enabled: true
            max_size_mb: 100

    limits_config:
      # 每个租户的日志摄入速率限制
      ingestion_rate_mb: 10
      ingestion_burst_size_mb: 20
      # 每个查询返回的最大条目数
      max_entries_limit_per_query: 5000
      # 日志保留期
      retention_period: 168h

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

    storage_config:
      tsdb_shipper:
        active_index_directory: /loki/tsdb-index
        cache_location: /loki/tsdb-cache

    compactor:
      working_directory: /loki/compactor
      compaction_interval: 10m
      retention_enabled: true
      retention_delete_delay: 2h
      delete_request_store: filesystem

    analytics:
      reporting_enabled: false

---
# 3. PersistentVolumeClaim (持久化存储)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: loki-data
  namespace: loki
  labels:
    app.kubernetes.io/name: loki
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5000Gi
  # 如需指定 StorageClass,取消下面注释
  storageClassName: nfs

---
# 4. Loki StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: loki
  namespace: loki
  labels:
    app.kubernetes.io/name: loki
    app.kubernetes.io/version: "3.6.10"
spec:
  replicas: 1
  serviceName: loki-headless
  selector:
    matchLabels:
      app.kubernetes.io/name: loki
  template:
    metadata:
      labels:
        app.kubernetes.io/name: loki
      annotations:
        checksum/config: "loki-config-v1"
    spec:
      securityContext:
        fsGroup: 10001
        runAsGroup: 10001
        runAsUser: 10001
        runAsNonRoot: true
      containers:
        - name: loki
          image: grafana/loki:3.6.10
          args:
            - -config.file=/etc/loki/loki.yaml
            - -target=all
          ports:
            - name: http
              containerPort: 3100
              protocol: TCP
            - name: grpc
              containerPort: 9096
              protocol: TCP
          readinessProbe:
            httpGet:
              path: /ready
              port: http
            initialDelaySeconds: 30
            periodSeconds: 10
            timeoutSeconds: 5
          livenessProbe:
            httpGet:
              path: /ready
              port: http
            initialDelaySeconds: 60
            periodSeconds: 30
            timeoutSeconds: 5
          resources:
            requests:
              cpu: 250m
              memory: 512Mi
            limits:
              cpu: "2"
              memory: 2Gi
          volumeMounts:
            - name: config
              mountPath: /etc/loki
            - name: data
              mountPath: /loki
      volumes:
        - name: config
          configMap:
            name: loki-config
        - name: data
          persistentVolumeClaim:
            claimName: loki-data

---
# 5. Loki Headless Service (for StatefulSet)
apiVersion: v1
kind: Service
metadata:
  name: loki-headless
  namespace: loki
  labels:
    app.kubernetes.io/name: loki
spec:
  type: ClusterIP
  clusterIP: None
  ports:
    - name: http
      port: 3100
      targetPort: http
      protocol: TCP
  selector:
    app.kubernetes.io/name: loki

---
# 6. Loki Service (供 Grafana 和 Promtail 连接)
apiVersion: v1
kind: Service
metadata:
  name: loki
  namespace: loki
  labels:
    app.kubernetes.io/name: loki
spec:
  type: NodePort
  ports:
    - name: http
      port: 3100
      targetPort: http
      protocol: TCP
      nodePort: 30100
    - name: grpc
      port: 9096
      targetPort: grpc
      protocol: TCP
  selector:
    app.kubernetes.io/name: loki

部署promtail

apiVersion: v1
kind: ServiceAccount
metadata:
  name: promtail
  namespace: loki
  labels:
    app.kubernetes.io/name: promtail

---
# 2. ClusterRole (读取 Pod 日志和元数据)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: promtail
  labels:
    app.kubernetes.io/name: promtail
rules:
  - apiGroups: [""]
    resources:
      - nodes
      - nodes/proxy
      - services
      - endpoints
      - pods
    verbs: ["get", "watch", "list"]

---
# 3. ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: promtail
  labels:
    app.kubernetes.io/name: promtail
subjects:
  - kind: ServiceAccount
    name: promtail
    namespace: loki
roleRef:
  kind: ClusterRole
  name: promtail
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: promtail-config
  namespace: loki
  labels:
    app.kubernetes.io/name: promtail
data:
  promtail.yaml: |
    server:
      http_listen_port: 9080
      grpc_listen_port: 0
      log_level: info

    positions:
      filename: /run/promtail/positions.yaml

    clients:
      - url: http://loki.loki.svc.cluster.local:3100/loki/api/v1/push
        batchwait: 1s
        batchsize: 1048576

    scrape_configs:
      # Job 1: 采集本节点所有 Pod 日志(排除系统组件)
      - job_name: kubernetes-pods-all
        kubernetes_sd_configs:
          - role: pod
        pipeline_stages:
          - cri: {}
          - drop:
              older_than: 168h
              drop_counter_reason: too_old
        relabel_configs:
          - source_labels: [__meta_kubernetes_pod_node_name]
            action: keep
            regex: ${HOSTNAME}
          - source_labels: [__meta_kubernetes_namespace]
            action: drop
            regex: (kube-system|loki)
          - source_labels: [__meta_kubernetes_pod_name]
            target_label: pod
          - source_labels: [__meta_kubernetes_namespace]
            target_label: namespace
          - source_labels: [__meta_kubernetes_pod_container_name]
            target_label: container
          - source_labels: [__meta_kubernetes_pod_label_app_kubernetes_io_name]
            target_label: app
          - source_labels: [__meta_kubernetes_pod_node_name]
            target_label: node
          - replacement: /var/log/pods/*$1/*.log
            separator: /
            source_labels:
              - __meta_kubernetes_pod_uid
              - __meta_kubernetes_pod_container_name
            target_label: __path__

---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: promtail
  namespace: loki
  labels:
    app.kubernetes.io/name: promtail
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: promtail
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app.kubernetes.io/name: promtail
    spec:
      serviceAccountName: promtail
      tolerations:
        - effect: NoSchedule
          key: node-role.kubernetes.io/master
          operator: Exists
        - effect: NoSchedule
          key: node-role.kubernetes.io/control-plane
          operator: Exists
      containers:
        - name: promtail
          image: grafana/promtail:3.6.10
          args:
            - -config.file=/etc/promtail/promtail.yaml
            - -config.expand-env=true
          ports:
            - name: http
              containerPort: 9080
              protocol: TCP
          readinessProbe:
            httpGet:
              path: /ready
              port: http
            initialDelaySeconds: 30
            periodSeconds: 10
            failureThreshold: 6
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 512Mi
          volumeMounts:
            - name: config
              mountPath: /etc/promtail
            - name: run
              mountPath: /run/promtail
            - name: pods-logs
              mountPath: /var/log/pods
              readOnly: true
          env:
            - name: HOSTNAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
      volumes:
        - name: config
          configMap:
            name: promtail-config
        - name: run
          hostPath:
            path: /run/promtail
            type: DirectoryOrCreate
        - name: pods-logs
          hostPath:
            path: /var/log/pods
            type: Directory