Kebutuhan:
– Kubernetes cluster
– helm v3.x
– kubectl
– git

Untuk aplikasi monitoring dan observability ada baiknya untuk menggunakan namespace tertentu agar tidak bercampur dengan aplikasi lainnya. Sebagai contoh kita akan membuat namespace montoring untuk kebutuhan ini

kubectl create namespace monitoring

Deploy Fluentbit dan fluent-operator

Fluent bit dan fluent-operator bisa di install sekaligus menggunakan helm chart dari fluent-operator. Untuk itu akan kita download versi terbaru dari branch main

git clone https://github.com/fluent/fluent-operator.git
cd fluent-operator

lalu install dengan helm

helm install fluent-operator -n monitoring charts/fluent-operator/ --set containerRuntime=containerd

untuk konfigurasi yang bisa diubah bisa dilihat di values.yaml. Ingat untuk mengaktifkan stdout, karena ini sangat membantu untuk debug log

Cek status deployment

$ kubectl get pods -n monitoring
NAME                               READY   STATUS      RESTARTS   AGE
fluent-bit-xscbv                   1/1     Running     0          6s
fluent-operator-7994bb4568-55qlb   1/1     Running     0          6s

Jumlah pod fluent-bit sesuai dengan jumlah node yang anda miliki di Kubernetes.

Konfigurasi Fluentbit

Fluent Bit dibagi menjadi 3 bagian besar, yaitu input, filter dan output. Konfigurasi fluentbit dikontrol melalu Custom Resource Defenition (CRD) yang dibuat sewaktu menginstall fluent-operator. Untuk melihat konfigurasinya gunakan

$ kubectl get crd | grep fluentbit
clusterfilters.fluentbit.fluent.io            2024-01-30T14:33:01Z
clusterfluentbitconfigs.fluentbit.fluent.io   2024-01-30T14:33:01Z
clusterinputs.fluentbit.fluent.io             2024-01-30T14:33:01Z
clusteroutputs.fluentbit.fluent.io            2024-01-30T14:33:01Z
clusterparsers.fluentbit.fluent.io            2024-01-30T14:33:01Z
collectors.fluentbit.fluent.io                2024-01-30T14:33:01Z
filters.fluentbit.fluent.io                   2024-01-30T14:33:01Z
fluentbitconfigs.fluentbit.fluent.io          2024-01-30T14:33:01Z
fluentbits.fluentbit.fluent.io                2024-01-30T14:33:01Z
outputs.fluentbit.fluent.io                   2024-01-30T14:33:01Z
parsers.fluentbit.fluent.io                   2024-01-30T14:33:01Z

masing masing CRD diatas memiliki kegunaan masing-masing.
fluentbit crd explanations
Setiap kita buat atau update CRD tersebut, fluent-operator akan otomatis mereload pod fluent-bit, sehingga semua fluent-bit memiliki konfigurasi yang sama tanpa perlu restart pod.

Untuk melihat masing-masing object gunakan kubectl get CRD, contoh

kubectl get clusterfluentbitconfigs.fluentbit.fluent.io

fluentbit cluster

Untuk melihat konfigurasi lengkap dari Fluent Bit

kubectl get secret/fluent-bit-config -o json -n monitoring  |   jq -r '.data."fluent-bit.conf"' | base64 -d

output perintah diatas

[Service]
    Http_Server    true
    Parsers_File    parsers.conf
[Input]
    Name    systemd
    Path    /var/log/journal
    DB    /fluent-bit/tail/systemd.db
    DB.Sync    Normal
    Tag    service.*
    Systemd_Filter    _SYSTEMD_UNIT=docker.service
    Systemd_Filter    _SYSTEMD_UNIT=kubelet.service
    Strip_Underscores    off
    storage.type    memory
[Input]
    Name    tail
    Path    /var/log/containers/*.log
    Read_from_Head    false
    Refresh_Interval    10
    Skip_Long_Lines    true
    DB    /fluent-bit/tail/pos.db
    DB.Sync    Normal
    Mem_Buf_Limit    100MB
    Parser    docker
    Tag    kube.*
    storage.type    memory
[Filter]
    Name    lua
    Match    kube.*
    script    /fluent-bit/config/containerd.lua
    call    containerd
    time_as_table    true
[Filter]
    Name    kubernetes
    Match    kube.*
    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
    K8S-Logging.Exclude    true
    Labels    false
    Annotations    false
[Filter]
    Name    nest
    Match    kube.*
    Operation    lift
    Nested_under    kubernetes
    Add_prefix    kubernetes_
[Filter]
    Name    modify
    Match    kube.*
    Remove    stream
    Remove    kubernetes_pod_id
    Remove    kubernetes_host
    Remove    kubernetes_container_hash
[Filter]
    Name    nest
    Match    kube.*
    Operation    nest
    Wildcard    kubernetes_*
    Nest_under    kubernetes
    Remove_prefix    kubernetes_
[Filter]
    Name    lua
    Match    service.*
    script    /fluent-bit/config/systemd.lua
    call    add_time
    time_as_table    true
[Output]
    Name    stdout
    Match    *

Cara Kirim Log ke Elasticsearch OpenSearch

Untuk mengirim log ke Elasticsearch atau OpenSearch kita cukup mengkonfigurasi plugin es, konfigurasinya ada di di file values.yaml pada repositori yang kita download diawal.

Plugin es menggunakan username dan password dari secret, untuk itu kita harus membuat secret tersebut terlebih dahulu, untuk membuat secret tersebut username dan passwordnya di encode dengan base64, contoh

$ echo elastic | base64
ZWxhc3RpYwo=
$ echo password | base64
cGFzc3dvcmQK

Copy hasil encode tersebut lalu update pada file elasticsearch-secret.yaml dibawah ini

apiVersion: v1
kind: Secret
metadata:
  name: elasticsearch-secret
  namespace: monitoring
data:
  username: ZWxhc3RpYwo=
  password: cGFzc3dvcmQK

lalu mari kita buat file fluentbit-output-elasticsearch.yaml, yang berisi CRD ClusterOutput untuk konfigurasi plugin es

apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterOutput
metadata:
  annotations:
    meta.helm.sh/release-name: fluent-operator
    meta.helm.sh/release-namespace: monitoring
  labels:
    app.kubernetes.io/managed-by: Helm
    fluentbit.fluent.io/component: logging
    fluentbit.fluent.io/enabled: "true"
  name: fluentbit-config-elasticsearch
spec:
  es:
    bufferSize: 10MB
    host: elasticsearch.jaranguda.com
    port: 443
    httpPassword:
      valueFrom:
        secretKeyRef:
          key: password
          name: elasticsearch-secret
    httpUser:
      valueFrom:
        secretKeyRef:
          key: username
          name: elasticsearch-secret
    index: prod
    replaceDots: true
    suppressTypeName: "true"
    tls:
      verify: false
  match: 'kube.*'

deploy kedua file tersebut

kubectl apply -f elasticsearch-secret.yaml -n monitoring
kubectl apply -f fluentbit-output-elasticsearch.yaml -n monitoring

Cek kembali file konfiguras fluentbit

kubectl get secret/fluent-bit-config -o json -n monitoring  |   jq -r '.data."fluent-bit.conf"' | base64 -d
# output
...
...
[Output]
    Name    es
    Match    *
    Host    elasticsearch.jaranguda.com
    Port    443
    Buffer_Size    10MB
    HTTP_User    elastic
    HTTP_Passwd    password
    Index    prod
    Time_Key    @timestamp
    Generate_ID    true
    Replace_Dots    true
    Suppress_Type_Name    true
    tls    On
    tls.verify    false
...
...

konfigurasi elasticsearch sudah masuk.

Skip Log

Agar logs tidak dikirim ke output, pada contoh diatas Elasticsearch, kita bisa menggunakan beberapa cara

1. Skip Namespace Logs

Untuk skip log dari namespace kita bisa menggunakan Exclude_Path dari INPUT, untuk konfigurasinya ada di clusterinput.fluentbit.fluent.io/tail

kubectl edit clusterinput.fluentbit.fluent.io/tail

tambahkan

excludePath: /var/log/containers/*_kube-system_*.log

exclude namespace fluentbit

/var/log/containers/*_kube-system_*.log data data struktur log tempat kubernetes/docker/container menyimpan file log di node. Bila diperhatikan log dari fluentbit dibawah ini
fluentbit pod logs
kita ambil contoh satu

0] kube.var.log.containers.fluent-operator-7994bb4568-55qlb_monitoring_setenv-912c9e490e3639bc3510117b39ce6fd6f3a43cdf0b89f1a5678516ba41e4480a.log: [[1706622740.083694983, {}], {"log"=>"+ docker info -f '{{.DockerRootDir}}'
", "time"=>"2024-01-30T13:52:20.083694983Z", "kubernetes"=>{"pod_name"=>"fluent-operator-7994bb4568-55qlb", "namespace_name"=>"monitoring", "labels"=>{"app.kubernetes.io/component"=>"operator", "app.kubernetes.io/name"=>"fluent-operator", "pod-template-hash"=>"7994bb4568"}, "container_name"=>"setenv", "docker_id"=>"912c9e490e3639bc3510117b39ce6fd6f3a43cdf0b89f1a5678516ba41e4480a", "container_image"=>"docker:20.10"}}]

Penjelasan dari nama log tersebut
kube.var.log.containers : default
fluent-operator-7994bb4568-55qlb : nama pod
_monitoring_ : namespace
setenv : container, didalam pod bisa ada lebih dari 1 container. Pada fluent-operator ada container setenv dan fluent-operator
912c9e490e3639bc3510117b39ce6fd6f3a43cdf0b89f1a5678516ba41e4480a : Container ID dari docker image
jadi pada konfig fluentbit yang kita buat, kita melewatkan semua logs yang ada dari namespace yang ditandai dengan format _NAMESPACE_, contoh _kube-system_

Cara yang sama bisa digunakan untuk skip log berdasarkan nama pod

excludePath: /var/log/containers/*.fluent-operator*_*.log

ataupun nama container

excludePath: /var/log/containers/*_setenv*.log

dengan excludePath ini kita tidak akan bisa melihat lognya dari output stdout

2. Skip Log dengan grep

Dengan menggunakan grep lebih banyak variasi yang digunakan untuk filter log, contoh skip log dari namespace

apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterFilter
metadata:
  annotations:
    meta.helm.sh/release-name: fluent-operator
    meta.helm.sh/release-namespace: monitoring
  labels:
    app.kubernetes.io/managed-by: Helm
    fluentbit.fluent.io/component: logging
    fluentbit.fluent.io/enabled: "true"
  name: fluentbit-config-namespace
spec:
  match: kube.*
  filters:
  - grep:
    exclude: $kubernetes['pod_name'] fluent-bit

mari kita ambil contoh dari tulisan sebelumnya

match: *
filters:
  grep:
    exclude: log /kerang/

Leave a comment

Your email address will not be published. Required fields are marked *