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.
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
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
/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
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/