Published on

Distributed Logging: ตอนที่ 3 Promtail ดึง Log จาก Kubernetes

Authors

Distributed Logging: ตอนที่ 3 Promtail ดึง Log จาก Kubernetes

จากตอนที่แล้ว รันด้วย Docker Compose ถ้าเปลี่ยนไปรันใน Kubernetes แล้วใช้ label-based log filtering ใน Promtail สำหรับดึง log ของเฉพาะ Pod/Container ที่ต้องการ จะต้องปรับแต่งหลักๆ ดังนี้


1. เปลี่ยนจาก docker_sd_configs เป็น kubernetes_sd_configs

ใน promtail-config.yml:

scrape_configs:
  - job_name: kubernetes-pods
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_logging]
        regex: promtail
        action: keep

      - source_labels: [__meta_kubernetes_pod_name]
        target_label: pod

      - source_labels: [__meta_kubernetes_namespace]
        target_label: namespace

      - source_labels: [__meta_kubernetes_pod_label_logging_jobname]
        target_label: job
  • ใช้ kubernetes_sd_configs เพื่อดึงข้อมูล Pod จาก Kubernetes API แทน docker_sd_configs
  • ฟิลด์ label จะเปลี่ยนไปเป็นแบบ __meta_kubernetes_pod_label_<labelname>
  • role: pod คือการค้นหา Pod ทั้งหมดใน cluster

2. เพิ่มสิทธิ์ให้ Promtail อ่าน Kubernetes API

  • Promtail ต้องรันใน Kubernetes เป็น DaemonSet (แนะนำ) และต้องมี RBAC สิทธิ์อ่าน Pod metadata
  • ตัวอย่าง ServiceAccount + Role + RoleBinding สำหรับ Promtail:
apiVersion: v1
kind: ServiceAccount
metadata:
  name: promtail
  namespace: monitoring

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: promtail
rules:
  - apiGroups: ['']
    resources: ['pods', 'namespaces']
    verbs: ['get', 'list', 'watch']

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: promtail
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: promtail
subjects:
  - kind: ServiceAccount
    name: promtail
    namespace: monitoring

3. กำหนด label บน Pod / Deployment ที่ต้องการ

เช่น ใน deployment.yaml ของแอป

metadata:
  labels:
    logging: promtail
    logging_jobname: containerlogs

เพื่อให้ Promtail กรอง log ได้ตาม label เหมือนกับใน docker-compose


4. Mount log path และ docker socket (ถ้าจำเป็น)

  • ใน Kubernetes ส่วนใหญ่ใช้ container runtime เช่น containerd หรือ CRI-O ที่เก็บ log ไว้ที่ /var/log/pods หรือ /var/log/containers
  • Promtail ควร mount log directory เหล่านี้ เช่น
volumeMounts:
  - name: varlog
    mountPath: /var/log
  - name: varlibdockercontainers
    mountPath: /var/lib/docker/containers
    readOnly: true
  - name: dockersocket
    mountPath: /var/run/docker.sock
    readOnly: true

volumes:
  - name: varlog
    hostPath:
      path: /var/log
  - name: varlibdockercontainers
    hostPath:
      path: /var/lib/docker/containers
  - name: dockersocket
    hostPath:
      path: /var/run/docker.sock

แต่ถ้าใช้ container runtime อื่นต้องเช็ค path log ที่ถูกต้อง


สรุป

ส่วนDocker ComposeKubernetes
Service Discoverydocker_sd_configskubernetes_sd_configs
Label Selector__meta_docker_container_label_<name>__meta_kubernetes_pod_label_<name>
Log Path/var/lib/docker/containers/var/log/pods, /var/log/containers
สิทธิ์ไม่ต้องใช้ RBACต้องมี RBAC เพื่ออ่าน metadata จาก API
DeploymentCompose serviceDaemonSet

ตัวอย่างไฟล์ promtail.yaml

ตัวอย่าง ไฟล์ promtail.yaml (รวม Namespace, ServiceAccount, RBAC, ConfigMap และ DaemonSet) สำหรับรัน Promtail ใน Kubernetes แบบ best practice พร้อม Label filter อ่านเฉพาะ Pod ที่ติด logging: promtail เหมือนกรณี docker-compose

---
apiVersion: v1
kind: Namespace
metadata:
  name: monitoring

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: promtail
  namespace: monitoring

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: promtail
rules:
  - apiGroups: ['']
    resources: ['pods', 'nodes', 'namespaces']
    verbs: ['get', 'list', 'watch']

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: promtail
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: promtail
subjects:
  - kind: ServiceAccount
    name: promtail
    namespace: monitoring

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: promtail-config
  namespace: monitoring
  labels:
    name: promtail-config
data:
  promtail.yaml: |
    server:
      http_listen_port: 9080
      grpc_listen_port: 0

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

    clients:
      - url: http://loki:3100/loki/api/v1/push

    scrape_configs:
      - job_name: kubernetes-pods
        pipeline_stages:
          - docker: {}
          - json:
              expressions:
                app_name: app_name
          - labels:
              app: app_name

        kubernetes_sd_configs:
          - role: pod

        relabel_configs:
          - source_labels: [__meta_kubernetes_pod_label_logging]
            regex: promtail
            action: keep

          - source_labels: [__meta_kubernetes_pod_name]
            target_label: pod

          - source_labels: [__meta_kubernetes_namespace]
            target_label: namespace

          - source_labels: [__meta_kubernetes_pod_label_logging_jobname]
            target_label: job

          - source_labels: [__meta_kubernetes_pod_node_name]
            target_label: node

        # ใช้ paths container log
        static_configs:
        - targets:
            - localhost
          labels:
            __path__: /var/log/pods/*/*/*.log

---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: promtail
  namespace: monitoring
  labels:
    app: promtail
spec:
  selector:
    matchLabels:
      app: promtail
  template:
    metadata:
      labels:
        app: promtail
    spec:
      serviceAccountName: promtail
      terminationGracePeriodSeconds: 30
      containers:
        - name: promtail
          image: grafana/promtail:latest
          args:
            - -config.file=/etc/promtail/promtail.yaml
          volumeMounts:
            - name: config
              mountPath: /etc/promtail
            - name: positions
              mountPath: /run/promtail
            - name: varlog
              mountPath: /var/log
            - name: varlibdockercontainers
              mountPath: /var/lib/docker/containers
              readOnly: true
      volumes:
        - name: config
          configMap:
            name: promtail-config
        - name: positions
          emptyDir: {}
        - name: varlog
          hostPath:
            path: /var/log
        - name: varlibdockercontainers
          hostPath:
            path: /var/lib/docker/containers