Fluentd daemonset 고도화

이제 fluentd의 다양한 plugin들을 사용하여 로그들을 파싱하고 고도화해보도록 하자.

containerd, CRI-O에서의 log파싱

kubernetes에서는 docker지원을 공식 중단했다. 이유는 간단한데, 공식 CRI를 docker에서 미지원했기 때문이다.

이때 바뀌게 되는 부분이 하나 있는데, 바로 log format이다. 기존의 docker에서 지원하는 log format은 다음과 같은 json형식이다.

{"log":"INFO:     \"GET /healthcheck HTTP/1.1\" 200 OK\n","stream":"stdout","time":"2023-12-07T06:56:33.076295527Z"}

따라서, fluentd를 사용할 때 source부분의 parse plugin으로 json을 사용하는 것이다.

<source>  
  @type tail
  @id in_tail_container_logs
  path "/var/log/pods/*/*/*.log"
  pos_file "/var/log/fluentd-containers.log.pos"
  read_from_head true
  tag "**"
  format json
  time_format %Y-%m-%dT%H:%M:%S.%NZ
  <parse>
    time_format %Y-%m-%dT%H:%M:%S.%NZ
    @type json
    time_type string
  </parse>
</source>

json으로 된 log data는 fluentd에서 기가막히게 parsing하지만, 안타깝게도 containerd, cri-o에서의 log format은 json이 아니다.

2023-12-07T06:56:33.076295527Z stdout F INFO:     "GET /healthcheck HTTP/1.1" 200 OK

정리하면 다음과 같다.

<time> <stream> <logtag> <log>

F이후로는 모두 log이다. <time>, <stream>, <logta>, <log> 사이는 모두 빈 칸이 하나씩이다. 따라서, 위의 docker에서 parsing하던 json으로 해당 log를 parsing하면 다음의 에러만 반복될 것이다.

ParserError error="pattern not matched with data"

따라서, 다음과 같이 regular expression을 사용해주도록 하자.

<source>
  @type tail
  @id in_tail_container_logs
  path "/var/log/pods/*/*/*.log"
  pos_file "/var/log/fluentd-e2term-pod.log.pos"
  read_from_head true
  tag "**"
  <parse>
    @type multi_format
    <pattern>
      format regexp
      time_key time
      time_format %Y-%m-%dT%H:%M:%S.%N%Z
      expression /^(?<time>.+) (?<stream>stdout|stderr) (?<logtag>.)? (?<log>.*)/
    </pattern>
  </parse>
</source>

위의 regular expression으로 crio, containerd의 log를 parsing하면 된다. record로 time, stream, logtag, log가 저장된다. 다행인 것은 time의 format이 docker일 때와 동일하기 때문에 이전과 동일한 time_format을 쓰면 된다.

결과로 다음과 record가 만들어지게 된다.

{
    "time": "2023-12-07T06:56:33.076295527Z",
    "stream": "stdout",
    "logtag": "F",
    "log": "INFO:     \"GET /healthcheck HTTP/1.1\" 200 OK"
}

log를 통해서 record만들기

log를 파싱하여 원하는 형식으로 record를 만들어주는 것이 좋다. 그래야 elasticsearch에서 검색하기가 좋기 때문이다.

log가 json으로 되어있다면 아주 happy한 경우이다. 다음과 같은 filter만 만들어주면 되기 때문이다.

<filter **>
  @type parser
  key_name log
  <parse>
    @type json
    json_parser json
  </parse>
  replace_invalid_sequence true
  emit_invalid_record_to_error false
  reserve_data true
</filter>

record key로 logjson으로 parsing하겠다는 것이다. 그러나 모든 pod의 log가 json으로 되어있지 않을 수 있으므로 emit_invalid_record_to_errorfalse로 두어서 parsing이 안되더라도 error로 남기지 않도록 한다. 또한, reserve_datatrue로 하여, log를 parsing 후에도 원본을 record에 남기도록 한다.

만약, log가 공백과 같은 특별한 구분자를 통해 형식화되었다면 regular expression을 사용하는 것이 좋다. 가령 다음의 log형식을 갖는다고 하자.

2023-12-07T06:56:33.076295527Z    INFO    original:96    Failed to read files.    

위의 log를 형식화하면 다음과 같다.

<time>\t<level>\t<caller>\t<log>

다음과 같이 filter를 통해서 regular expression으로 log를 parsing할 수 있다.

<filter **>
  @type parser
  key_name log
  <parse>
    @type regexp
    expression /^(?<time>.+)\t(?<level>.+)\t(?<caller>.+)\t(?<log>.*)/
    time_format %Y-%m-%dT%H:%M:%S.%N%Z
  </parse>
</filter>

record결과로 다음과 같이 나오게 된다.

{
    "time": "2023-12-07T06:56:33.076295527Z",
    "level": "INFO",
    "caller": "original:96",
    "log": "Failed to read files."
}

만약, 특정 record field를 추가하거나, 삭제하고 싶다면 record_transformer를 사용하면 된다.

<filter **>
  @type record_transformer
  enable_ruby
  remove_keys $.content.time
  <record>
    tag ${tag}
  </record>
</filter>

다음의 경우에는 record의 field로 content.time을 삭제하고, tag field를 만들어 놓는다. tag field값은 fluentd에서 사용하는 tag가 되는 것이다.

주의: 조심해할 것 중 하나는 parsing을 한 다음에 record에 특정 field를 삭제, 추가, 변경하는 것이 좋다. 만약 특정 field를 추가, 삭제, 변경한 다음에 parsing이 이루어지면, 변동사항은 남지않고 parsing된 결과가 덮어써지게 되는 수가 있다. 가령 위에서 tag를 추가한다음 log를 parsing하면 tag field가 사라지게 된다.

elasticsearch ILM, rollover 적용

이제 배포해서 사용하면 문제없이 구동될 것 같지만, 한 가지 문제가 남아있다. 바로 rollover이다. rollover가 무엇이냐하면, 현재 log를 받고 있는 elasticsearch index를 김밥마냥 말아(roll)버린다음에 저장하고, 새로운 index를 만들어 log들을 받겠다는 것이다.

[2023/12/06] pod logs -> fluentd -> elasticsearch -> index: server-000001
[2023/12/07] pod logs -> fluentd -> elasticsearch -> index: server-000002 (rollover: server-000001)

rollover된 index는 그냥 놔두거나 삭제할 수 있다. 일반적으로 data engineering에서 이러한 작업을 retention이라고 한다.

이렇게 rollover를 하는 이유는 아주 간단한데, 계속해서 index를 만들어 log를 저장하기에는 하드디스크의 자원이 한정적이기 때문이다.

elasticsearch에서 rollover는 직접 API를 사용해 요청을 보낼 수 있지만, 공식적으로는 ILM(index lifecycle management)를 적용해서 rollover가 자동으로 이루어지도록 추천하고 있다.

ILM은 index를 hot-warm-cold-frozen-delete 페이즈로 구분하여 관리하고 지정한 기간이 지나면 phase를 전황시키고 지정한 작업을 수행하도록 한다.

가령, 다음과 같이 설정할 수 있다. index가 처음 생성되면 hot phase로 넘어가고 하루 단위 또는 4GB의 index가 넘어가면 rollover시키도록 한다. rollover로 넘어간 index는 hot에서 warm phase로 넘아가도록 하고 warm phase에서는 읽기 전용으로 바꾸도록 한다. 생성한 지 7일이 지나면 cold phase로 넘어가도록 하며, cold phase로 넘어간 index는 저장만 하는 node로 이동시키도록 한다. 생성된 지 30일이 지난 index는 delete phase로 가도록 하며, delete phase로 전환된 index는 snapshot으로 백업되며 완료 후 삭제하도록 한다. (단, snapshot 저장은 유료 엔터프라이즈에서만 가능하다.)

각 phase의 컨셉을 정리하면 다음과 같다.

  1. hot: 현재 업데이트가 수행되며, 읽기, 쓰기 작업이 가능
  2. warm: 더 이상 업데이트가 수행되지 않으며 읽기만 가능
  3. cold: 더 이상 업데이트가 수행되지 않으며 읽기는 가능하지만 검색이 자주 일어나지 않음
  4. frozen: 더 이상 업데이트가 수행되지 않으며 검색이 거의 일어나지 않음
  5. delete: 삭제할 단계

위의 phase는 공식 홈페이지에서 제안하는 phase일 뿐이지, 각 phase를 개인마다 다르게 관리해도 문제될 것은 없다.

이 phase로 넘어가는 단계의 조건는 시간과 용량이다. 가령 hot phase에서 6분 후에 delete phase로 보내거나, hot phase에서 10G가 넘어가면 delete phase로 넘기자는 것이다.

그런데 이 ILM에서 조심해야할 것이 있는데, 바로 ILM을 API를 통해 직접 index에 하나하나 적용시켜줄 수도 있지만 일반적으로 index-template를 할당해서 index-template의 pattern을 따르는 index만 ILM을 따르도록 할 수 있다.

|----------Index-------|
| server-1, server-2   | <---------index template(index pattern) <--------- ILM(rollover)
|----------------------|

index-templateindex의 pattern위주니까 index의 이름들이 server*라는 pattern을 따르고, server* index pattern을 가지는 index-templateILM을 할당해주면 자동으로 server-1, server-2들이 모두 rollover되겠지?? 싶지만 안된다.

안되는 이유에는 몇 가지 이유가 있다.
1. index의 이름은 마지막에 -{숫자}로 끝나야 한다. 가령 server-1-000001 이렇게 끝나야 한다. 만약 해당 규칙을 안따르면 illegal_argument_exception: index name does not match pattern '^.*-\d+$'가 발생한다.
2. rolloverindex이름이 아니라, alias로 결정된다. 따라서, index-templateindex pattern을 따르고 있는 index들이라도 aliasindex template에서 지정한 rollover_alias이어야 한다. 주의할 것은 index-template에서도 aliases를 설정할 수 있는데, 해당 부분의 alias이름이 rollover_alias이름과 동일하면 안된다.

정리하면 다음과 같다.

index template(index pattern: server*, rollover_alias: server) <--------- ILM(rollover)
                        |
                        ↓
|---------------------Index------------------------|
| server-1(alias: server), server-2(alias: park)   | 
|--------------------------------------------------|

위의 예시와 같이 index templatepattern으로 server*를 가지고 있어서 server-1, server-2 index가 모두 적용된 것을 알 수 있다. 그리고 index templateILM과 연결되어있는데, ILM에서 rollover를 수행한다고 하자.

문제는 server-1, server-2 모두 index template의 pattern을 따르지만, rollover_aliasserver만 해당하기 때문에 server-1aliasserver라 적용되는 반면 server-2aliaspark이라서 반영되지 않는다.

따라서, index마다 alias를 rollover ILM이 달린 index templaterollover_alias로 설정해주어야 한다는 것이다.

그런데, 이걸 어떻게 fluentd에서 할 수 있는가?? 라고 한다면 막막하다. 이를 위해서 어느 2020년 용자가 issue를 만들고 contribution을 해주었다. https://github.com/uken/fluent-plugin-elasticsearch/issues/752

결론만 만들자면 자동으로 ILM을 만들고 index-template를 만들며, index에 rollover_alias와 동일한 alias를 달아준다. 이 덕분에 자동으로 rollver가 동작하도록 한다는 것이다.

fluentdelasticsearch plugin을 사용하면 되는데, docs만 봤다가는 적어도 일주일간 눈물의 삽질을 해야한다. 다음의 예시를 보고, 만들면 된다.

<match **>
  @type elasticsearch
  host $HOST_IP
  port $HOST_PORT
  log_es_400_reason true
  logstash_format true
  logstash_prefix server
  type_name fluentd
  application_name server
  template_name index-template
  template_file /fluentd/etc/index_template.json
  enable_ilm true
  ilm_policy_id retention-3m
  ilm_policy {"policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_age":"3m","max_size":"5gb"}}},"delete":{"min_age":"3m","actions":{"delete":{}}}}}}
  ilm_policy_overwrite false
</match>

뭔가 복잡하지만 ILM에 관련된 부분만 차례대로 보면 다음과 같다.
1. enable_ilm: default가 false인데 true로 바꾸지 않으면 구동되지 않는다.
2. ilm_policy_id: 생성할 ILM이름이다.
3. ilm_policy: ILM policy이다. elasticsearch에서 적용하는 ILM json형식과 동일하다. 참고로, 위의 예시는 rollover가 잘되는 지를 확인하기 위해 3분마다 rollover가 이루어지고 rollover된 index는 3분 뒤에 삭제된다는 의미이다.
4. ilm_policy_overwrite: 이름이 동일한 경우, overwrite할 것인지를 묻는다. 만약 false일 때, 이름이 동일한 ILM이 있다면 기존의 ILM을 적용하고 새로 만들지 않는다.
5. template_name: 생성할 index-template이름이다. 그러나 동작하지 않는 것으로 보이지만, 없으면 안만들어질 수도 있다. docs에는 기존에 template_name으로 index-template가 있다면 이를 적용한다고 하지만, 실제로 해봤는데 잘안된다...
6. template_file: 생성할 index-template의 정의가 있는 path이다.. elasticsearch와 동일한 정의를 가지는데, 그닥 중요한 부분은 없다. rollover_alias알아서 만들어주고 생성될 index와의 맵핑도 자동으로 해준다. 단, 없으면 rollover적용이 안된다

kibana에서 template를 만들 때는 다음과 같다.

{
  "template": {
    "settings": {
      "index": {
        "lifecycle": {
          "name": "template",
          "rollover_alias": "retention"
        }
      }
    },
    "aliases": {},
    "mappings": {}
  }
}

그런데 굳이 이렇게까지 만들 필요는 없다. elasticsearch plugin에서 자동으로 lim도 만들어주고 그 정보를 이용해서 templaterollover_alias, name등을 다 설정해준다.

index_template.json의 정의는 다음과 같았다.

{
  "index_patterns": [
      "logstash-default*"
  ],
  "settings": {
      "index": {
          "number_of_replicas": "1"
      }
  }
}

해당 index_template.jsonfluentd pod의 /etc/fluentd/index_template.json에 제공해야하므로 ConfigMap에 추가하고 Volume에 추가해야한다.

따라서 최종 daemonset은 다음과 같다.

  • fluentd-elasticsearch-deamonset.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: fluentd
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: fluentd-config
  namespace: fluentd
data:
  index_template.json: |-
    {
      "settings": {
          "index": {
              "number_of_replicas": "1"
          }
      }
    }
  fluent.conf: |-
    <source>
      @type tail
      @id in_tail_container_logs
      path "/var/log/pods/*/*/*.log"
      pos_file "/var/log/fluentd-log.pos"
      read_from_head true
      tag "**"
      <parse>
        @type multi_format
        <pattern>
          format regexp
          time_key time
          time_format %Y-%m-%dT%H:%M:%S.%N%Z
          expression /^(?<time>.+) (?<stream>stdout|stderr) (?<logtag>.)? (?<log>.*)/
        </pattern>
      </parse>
    </source>

    <filter **>
      @type parser
      key_name log
      <parse>
        @type json
        json_parser json
      </parse>
      replace_invalid_sequence true
      emit_invalid_record_to_error false
      reserve_data true
    </filter>

    <match **>
      @type elasticsearch
      host ${ELASTICSEARCH_HOST_IP}
      port ${ELASTICSEARCH_HOST_REST_PORT}
      log_es_400_reason true
      logstash_format true
      logstash_prefix ${LOGSTASH_INDEX_PREFIX}
      type_name fluentd
      application_name ${APP_NAME}
      template_name index_template
      template_file /fluentd/etc/index_template.json
      enable_ilm true
      ilm_policy_id retention-3m
      ilm_policy {"policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_age":"3m","max_size":"5gb"}}},"delete":{"min_age":"3m","actions":{"delete":{}}}}}}
      ilm_policy_overwrite false
    </match>
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: fluentd
  namespace: fluentd

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: fluentd
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - namespaces
  verbs:
  - get
  - list
  - watch

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: fluentd
roleRef:
  kind: ClusterRole
  name: fluentd
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: fluentd
  namespace: fluentd
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: fluentd
  labels:
    k8s-app: fluentd-logging
    version: v1
spec:
  selector:
    matchLabels:
      k8s-app: fluentd-logging
      version: v1
  template:
    metadata:
      labels:
        k8s-app: fluentd-logging
        version: v1
    spec:
      serviceAccount: fluentd
      serviceAccountName: fluentd
      tolerations:
      - key: node-role.kubernetes.io/control-plane
        effect: NoSchedule
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:v1-debian-elasticsearch
        env:
          - name: K8S_NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          #- name:  FLUENT_ELASTICSEARCH_HOST
          #  value: "xx.xx.xx.xxx"
          #- name:  FLUENT_ELASTICSEARCH_PORT
          #  value: "xxxxx"
          #- name: FLUENT_ELASTICSEARCH_SCHEME
          #  value: "http"
          # Option to configure elasticsearch plugin with self signed certs
          # ================================================================
          - name: FLUENT_ELASTICSEARCH_SSL_VERIFY
            value: "true"
          # Option to configure elasticsearch plugin with tls
          # ================================================================
          - name: FLUENT_ELASTICSEARCH_SSL_VERSION
            value: "TLSv1_2"
          # X-Pack Authentication
          # =====================
          - name: FLUENT_ELASTICSEARCH_USER
            value: "elastic"
          - name: FLUENT_ELASTICSEARCH_PASSWORD
            value: "changeme"
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: dockercontainerlogdirectory2
          mountPath: /var/lib/docker/containers
          readOnly: true
        # When actual pod logs in /var/log/pods, the following lines should be used.
        - name: dockercontainerlogdirectory
          mountPath: /var/log/pods
          readOnly: true
        - name: config
          mountPath: /fluentd/etc/fluent.conf
          subPath: fluent.conf
        - name: config
          mountPath: /fluentd/etc/index_template.json
          subPath: index_template.json
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      # When actual pod logs in /var/lib/docker/containers, the following lines should be used.
      # - name: dockercontainerlogdirectory
      #   hostPath:
      #     path: /var/lib/docker/containers
      # When actual pod logs in /var/log/pods, the following lines should be used.
      - name: dockercontainerlogdirectory
        hostPath:
          path: /var/log/pods
      - name: dockercontainerlogdirectory2
        hostPath:
          path: /var/lib/docker/containers
      - name: config
        configMap:
          name: fluentd-config

입력이 필요한 부분은 ConfigMap에서 환경변수로 표시해두었으니 추가해주도록 하자. ex) ${ELASTICSEARCH_HOST_IP}, ${ELASTICSEARCH_HOST_REST_PORT}

위 deamonset을 만든다음에 3분마다 kibanaindex management tab에 가서 rollover되고 오래된 데이터는 삭제되는지 확인해주도록 하자. 단, elasticsearchILM poll은 default가 10분이다. 따라서, 결과를 바로바로 확인하고 싶다면 다음과 같이 poll_interval을 10초로 바꿀 수 있다.

PUT /_cluster/settings
{
  "transient" : {
    "indices.lifecycle.poll_interval" : "10s"
  }
}

필자는 ${LOGSTASH_INDEX_PREFIX}park이라는 index를 만들었고, fluentd에서 다음과 같이 자동으로 다음과 같이 만들어지는 것을 볼 수 있다.

GET _cat/indices

...
yellow open park--2023.12.08-000001       GV-NrXxuQsW9L-z3j5n3HQ 1 1 233     0 98.2kb 98.2kb
...

참고로, elasticsearch plugin에 application_name을 설정하면 park-${application_name}-2023.12.08이 된다. 필자는 application_name: ""으로 설정해서 park--2023.12.08이 된 것이다.

park만 주었는데도, ilmtemplate덕분에 park--{날짜}-000001이라는 index가 나오는 것이다. 다음으로 _alias를 확인해보도록 하자.

GET park--2023.12.08-000001

{
  "park--2023.12.08-000001" : {
    "aliases" : {
      "park-2023.12.08" : {
        "is_write_index" : true
      }
    },
    ...
    "settings" : {
      "index" : {
        "lifecycle" : {
          "name" : "retention-3m",
          "rollover_alias" : "park-2023.12.08"
        },
        "routing" : {
          "allocation" : {
            "include" : {
              "_tier_preference" : "data_content"
            }
          }
        },
        "number_of_shards" : "1",
        "provided_name" : "<park--2023.12.08-000001>",
        "creation_date" : "1702001064437",
        "number_of_replicas" : "1",
        "uuid" : "GV-NrXxuQsW9L-z3j5n3HQ",
        "version" : {
          "created" : "7171499"
        }
      }
    }
  }
}

index park--2023.12.08-000001park-2023.12.08이라는 alias가 자동으로 할당된 것을 볼 수 있다. rollover_aliaspark-2023.12.08로 잘 붙어있는 것을 볼 수 있다. 그렇다면 park--2023.12.08-000001에는 index-templateilm이 잘 붙어있는 지 확인해보도록 하자.

GET park--2023.12.08-000001/_ilm/explain

응답으로 다음이 나온다.

{
  "indices" : {
    "park--2023.12.08-000001" : {
      "index" : "park--2023.12.08-000001",
      "managed" : true,
      "policy" : "retention-3m",
      "lifecycle_date_millis" : 1702001064437,
      "age" : "6m",
      "phase" : "hot",
      "phase_time_millis" : 1702001064512,
      "action" : "rollover",
      "action_time_millis" : 1702001064512,
      "step" : "check-rollover-ready",
      "step_time_millis" : 1702001064512,
      "phase_execution" : {
        "policy" : "retention-3m",
        "phase_definition" : {
          "min_age" : "0ms",
          "actions" : {
            "rollover" : {
              "max_size" : "5gb",
              "max_age" : "3m"
            }
          }
        },
        "version" : 1,
        "modified_date_in_millis" : 1702001064488
      }
    }
  }
}

retention-3m ILM이 잘 걸린 것이 확인된다.

마지막으로 index-template를 확인하여, rollover_aliaspark--2023.12.08-000001 index의 aliaspark-2023.12.08과 동일한 지 확인해야한다. index-template의 이름은 kibana에서 index management -> index template칸으로 가면 park-2023.12.08라는 index template가 만들어진 것을 볼 수 있다.

GET _template/park-2023.12.08

...
{
  "park-2023.12.08" : {
    "order" : 53,
    "index_patterns" : [
      "park--2023.12.08-*"
    ],
    "settings" : {
      "index" : {
        "lifecycle" : {
          "name" : "retention-3m",
          "rollover_alias" : "park-2023.12.08"
        },
        "number_of_replicas" : "1"
      }
    },
    "mappings" : { },
    "aliases" : { }
  }
}

park-2023.12.08 index-template가 index pattern으로 fluentd에서 data를 쏘고 있는 index로 보내고 있는 것을 확인할 수 있고, licycle부분에 ILM로 retention-3m이 연결된 것을 볼 수 있다. 마지막으로 rollover_aliaspark-2023.12.08으로, park--2023.12.08-000001 index의 rollover alias와 동일한 것을 확인할 수 있다.

이제 rollover가 성립되는 조건은 모두 만족하였다. 실제로 rollover가 되는 지 안되는 지 확인해보도록 하자. 필자의 경우 3분 후에 rollover되고 3분 후에 rollover된 index를 삭제하도록 하였다. 실제로 시간이 지나면 다음과 같이 index가 만들어진다.

park--2023.12.08-000001
park--2023.12.08-000002

park--2023.12.08-000001이 rollover되고 park--2023.12.08-000002에 새로운 데이터가 쓰이고 있을 것이다. 확인해보도록하자.

GET park--2023.12.08-000001

{
  "park--2023.12.08-000001" : {
    "aliases" : {
      "park-2023.12.08" : {
        "is_write_index" : false
      }
    },
    ...}
}

aliaspark-2023.12.08is_write_index부분이 false인 것을 확인할 수 있다. 해당 index에 write되고 있는 data가 없다는 것이다. 반면에 park--2023.12.08-000002를 확인하면 log가 들어오고 있기 때문에 is_write_indextrue가 된다.

GET park--2023.12.08-000002

{
  "park--2023.12.08-000002" : {
    "aliases" : {
      "park-2023.12.08" : {
        "is_write_index" : true
      }
    },
    ...}
}

시간이 왕창 지나면 다음과 같이 이전에 rollover된 index들은 사라지게 된다.

park--2023.12.08-000010
park--2023.12.08-000011
park--2023.12.08-000012

참고로, 다음의 기능은 날짜가 바뀌면 다음과 같이 날짜가 바뀌는대로 새로운 index-template를 만들고 index를 rollover한다.

park--2023.12.09-000023
park--2023.12.09-000024
park--2023.12.09-000025

index-templatepark-2023.12.09가 만들어지고 aliaspark-2023.12.09가 된다.

이것으로 fluentd에 대한 내용은 끝이다. 그 밖에 plugin들에 대한 내용은 일부 다룰 수는 있겠지만, docs를 참고하는 편이 좋으며 직접하는 것을 추천한다.

0개의 댓글

Powered by GraphCDN, the GraphQL CDN