여기서는 fluent-bit deamonset 설정하면서 만난 문제점을 간단히 공유하고자 합니다.
fluent-bit deamonset 설정
GitHub – fluent/fluent-bit-kubernetes-logging: Fluent Bit Kubernetes Daemonset
위 리포지토리를 참고해서 fluentbit 을 설치합니다.
rbac 설정
먼저 RBAC for fluentbit 을 설정합니다.0
kubectl create -f https://raw.githubusercontent.com/fluent/fluent-bit-kubernetes-logging/master/fluent-bit-service-account.yaml
$ kubectl create -f https://raw.githubusercontent.com/fluent/fluent-bit-kubernetes-logging/master/fluent-bit-role.yaml
$ kubectl create -f https://raw.githubusercontent.com/fluent/fluent-bit-kubernetes-logging/master/fluent-bit-role-binding.yaml
원하는 logging system 선택(elastic search)
로그를 보내고 싶은 저장소를 선택합니다. 여기서는 elasticsearch
.
- Fluent bit configmap 생성
kubectl create -f https://raw.githubusercontent.com/fluent/fluent-bit-kubernetes-logging/master/output/elasticsearch/fluent-bit-configmap.yaml
- Fluent bit elastic search Daemonset 생성
0FLUENT_ELASTICSEARCH_HOST 와 FLUENT_ELASTICSEARCH_HOST 값을 각자의 시스템에 맞게 변경하고 배포합니다.
kubectl create -f https://raw.githubusercontent.com/fluent/fluent-bit-kubernetes-logging/master/output/elasticsearch/fluent-bit-ds.yaml
그리고 각 데몬셋의 로그를 확인합니다.!!
그러면 elasticsearch에 로그를 보낼 때마다 에러 발생….
에러
apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-config
namespace: logging
labels:
k8s-app: fluent-bit
data:
# Configuration files: server, input, filters and output
# ======================================================
fluent-bit.conf: |
[SERVICE]
Flush 1
Log_Level info
Daemon off
Parsers_File parsers.conf
HTTP_Server On
HTTP_Listen 0.0.0.0
HTTP_Port 2020
@INCLUDE input-kubernetes.conf
@INCLUDE filter-kubernetes.conf
@INCLUDE output-elasticsearch.conf
input-kubernetes.conf: |
[INPUT]
Name tail
Tag kube.*
Path /var/log/containers/*.log
Parser docker
DB /var/log/flb_kube.db
Mem_Buf_Limit 5MB
Skip_Long_Lines On
Refresh_Interval 10
filter-kubernetes.conf: |
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc.cluster.local:443
Merge_Log On
K8S-Logging.Parser On
output-elasticsearch.conf: |
[OUTPUT]
Name es
Match *
Host ${FLUENT_ELASTICSEARCH_HOST}
Port ${FLUENT_ELASTICSEARCH_PORT}
Logstash_Format On
Retry_Limit False
parsers.conf: |
[PARSER]
Name apache
Format regex
Regex ^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$
Time_Key time
Time_Format %d/%b/%Y:%H:%M:%S %z
[PARSER]
Name apache2
Format regex
Regex ^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$
Time_Key time
Time_Format %d/%b/%Y:%H:%M:%S %z
[PARSER]
Name apache_error
Format regex
Regex ^\[[^ ]* (?<time>[^\]]*)\] \[(?<level>[^\]]*)\](?: \[pid (?<pid>[^\]]*)\])?( \[client (?<client>[^\]]*)\])? (?<message>.*)$
[PARSER]
Name nginx
Format regex
Regex ^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$
Time_Key time
Time_Format %d/%b/%Y:%H:%M:%S %z
[PARSER]
Name json
Format json
Time_Key time
Time_Format %d/%b/%Y:%H:%M:%S %z
[PARSER]
Name docker
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L
Time_Keep On
# Command | Decoder | Field | Optional Action
# =============|==================|=================
Decode_Field_As escaped log
[PARSER]
Name syslog
Format regex
Regex ^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$
Time_Key time
Time_Format %b %d %H:%M:%S
위에가 fluent bit의 기본 config 내용입니다.
기본적으로 kubernetes 에 pod 를 run 한다는 의미는 docker container 를 실행한다는 의미입니다.
그 말인 즉, docker log 는 항상 발생한다는 이야기…
제가 본 에러는 elasticsearch 의 timestamp 와
PARSER 부분의 docker 설정에서 parsing 되는 timestamp와의 충돌에서 생기는 문제였습니다.
[PARSER]
Name docker
...
Time_Keep Off
...
위 부분의 Time_Keep을 On 에서 Off 로 변경해주고 다시 Daemonset을 실행합니다.
kubectl apply -f fluent-bit-configmap.yaml
kubectl delete -f fluent-bit-ds.yaml
kubectl apply -f fluent-bit-ds.yaml
이제 정상적으로 ES로 로그가 보내지는 것을 확인합니다.
실행 확인
pod의 로그를 봐서 fluent-bit 의 정상 동작 여부를 확인해도 되지만,
참고로 prometheus 가 kubernetes cluster 에 이미 설정되어 있다면,
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "2020"
prometheus.io/path: /api/v1/metrics/prometheus
데몬셋의 위의 annotations 설정으로 prometheus가 자동으로 fluent-bit 타켓을 찾아서 fluent-bit 의 메트릭을 수집합니다.
따라서, prometheus dashboard 에서 fluentbit_output_errors_total
이 메트릭을 확인하면 error 가 나고 있는지 아닌지 간단히 확인 가능합니다.