Index Template은 인덱스를 생성할 때 사용되는 설정 템플릿입니다. 새로운 인덱스가 생성될 때 매번 정의하는 번거러움을 인덱스 템플릿 설정을 통하여 해결할 수 있습니다. 인덱스 템플릿을 선언을 통해 자동적으로 새롭게 생성되는 인덱스에 설정을 적용하여 일관된 인덱스 구조와 매핑을 유지하고 반복적인 작업을 줄이는 데 사용됩니다.

 

Index Template 생성

실습으로 my-log라는 Index Template을 생성하여 데이터 필드가 잘 적용되는지 확인하도록 하겠습니다.

 

인덱스 생성 시 설정 파라미터에 대한 정보

https://opensearch.org/docs/1.2/opensearch/rest-api/index-apis/create-index/

 

Create index

Create index Introduced 1.0

opensearch.org

PUT _index_template/my-log
{
    "index_patterns": [
        "my-log-*"
    ],
    "template": {
        "settings": {
            "number_of_shards": 4,
            "number_of_replicas": 1,
            "refresh_interval": "5s",
            "opendistro.index_state_management.policy_id": "my-ism"
        },
        "mappings": {
            "properties": {
                "cluster": {
                    "type": "keyword"
                },
                "node": {
                    "type": "keyword"
                },
                "level": {
                    "type": "keyword"
                },
                "message": {
                    "type": "text"
                },
                "timestamp": {
                    "type": "long"
                }
            },
            "dynamic_templates": [
                {
                    "default_string": {
                        "match": "default*",
                        "match_mapping_type": "string",
                        "mapping": {
                            "type": "keyword"
                        }
                    }
                },
                {
                    "default_number": {
                        "match": "default*",
                        "match_mapping_type": "long",
                        "mapping": {
                            "type": "integer"
                        }
                    }
                }
            ]
        }
    }
}

index_patterns을 통해 "my-log-"로 시작하는 새롭게 생성된 인덱스에 해당 Template을 적용하도록 지정합니다.

 

number_of_shards 해당 인덱스의 샤드 개수를 설정합니다. Opensearch의 경우 Cluster가 여러 Data Node로 구성되는데 하나의 Data Node에 데이터가 집중되지 않도록 number_of_shards를 설정하여 여러 Data Node에 샤드를 골고루 배치할 수 있습니다.

 

number_of_replicas는 primary shard를 복제한 replica shard의 개수를 설정합니다. 위 설정에서는 1로 설정하여 각각의 primary shard가 복제한 샤드를 한 개씩 구성할 수 있도록 설정하여 HA 구성이 되도록 설정하였습니다.

 

refresh_interval은 간단하게 설명하면 검색할 수 있는 document를 refresh 하는 것을 의미합니다. Opensearch는 데이터가 들어왔다고 바로 검색이 가능한 것이 아니고 데이터가 들어오고 해당 인덱스가 refresh가 되었을 경우 검색이 가능하게 됩니다. refresh_interval을 1s로 설정하였다면 1초마다 refresh 되어 실시간처럼 검색이 가능하게 되지만 indexing 성능에 영향을 미칠 수 있습니다. 만약 본인의 환경이 실시간을 중요하게 여기지 않고 indexing 성능을 우선으로 한다면 refresh_interval값을 크게 가져가는 것을 추천합니다. 보다 자세한 정보를 원하신다면 "Lucene"에 대해 알아보는 것을 추천합니다.

 

opendistro.index_state_management.policy_id 설정은 ISM Policy 정책을 지정하는 것입니다. ISM은 Index state Management로 인덱스의 Lifecycle을 관리해 주는 역할을 수행합니다. 아래 링크에 정리해 두었으니 자세한 내용을 링크에서 확인해 주세요

https://stdhsw.tistory.com/entry/Opensearch-ISMIndex-State-Management

 

mappings.properties 설정은 데이터의 field의 타입을 지정합니다. string 타입에는 대표적으로 keyword, text 타입이 있는데 keyword는 Aggregation과 같이 통계를 내거나 반듯이 같은 값을 검색하는 데 사용되며 text의 경우 Analyzer를 통해 데이터를 분석하는 데 사용됩니다. 그 밖에 많은 field type이 존재하는데 자세한 내용은 Opensearch document를 확인해 주세요

https://opensearch.org/docs/latest/field-types/supported-field-types/index/

 

Supported field types

Supported field types

opensearch.org

mappings.dynamic_templates 설정은 properties로 지정하지 않은 field의 데이터가 들어올 경우 해당 데이터의 필드 타입을 지정합니다. dynamic_templates 은 어떠한 데이터 필드가 들어올지 명확하지 않거나 동일한 이름 형식의 필드가 너무 많을 경우 사용합니다. 위에서 설정된 default_string의 경우 필드의 이름이 default로 시작되며 데이터 형식이 string일 경우 필드의 타입을 keyword로 지정하는 설정이며 default_number의 경우 default로 시작하여 데이터 형식이 number일 경우 필드의 타입을 integer로 설정합니다.

 

Index Template 확인하기

방금 생성한 my-log Template을 확인합니다.

GET _index_template/my-log

 

테스트 해보기

지정된 Template이 잘 적용되는지 bulk를 이용하여 실제 데이터를 넣어 확인합니다. (참고로 bulk는 HTTP Body의 가장 마지막 라인에 enter를 한번 더 넣어줘야지 Error가 발생하지 않습니다.)

POST _bulk
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-1", "level": "debug", "message": "[debug] data send successful", "timestamp": 1688992028}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-1", "level": "debug", "message": "[debug] data send successful", "timestamp": 1688992038}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-1", "level": "debug", "message": "[debug] data send successful", "timestamp": 1688992048}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-2", "level": "debug", "message": "[debug] data send successful", "timestamp": 1688992029}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-2", "level": "debug", "message": "[debug] data send successful", "timestamp": 1688992030}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-2", "level": "debug", "message": "[debug] data send successful", "timestamp": 1688992031}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-2", "level": "debug", "message": "[debug] data send successful", "timestamp": 1688992033}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-1", "level": "err", "message": "[err] failed data send", "timestamp": 1688992048}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-1", "level": "warn", "message": "[warn] json format is not valid", "timestamp": 1688992041}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-1", "level": "err", "message": "[err] failed data send", "timestamp": 1688992042}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-2", "level": "debug", "message": "[debug] data send successful", "timestamp": 1688992031, "default-text": "APP Test"}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-2", "level": "debug", "message": "[debug] data send successful", "timestamp": 1688992033, "default-text": "APP Test"}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-1", "level": "err", "message": "[err] failed data send", "timestamp": 1688992048, "default-text": "APP Test"}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-1", "level": "warn", "message": "[warn] json format is not valid", "timestamp": 1688992041, "default-number": 111111}
{ "index": { "_index": "my-log-2023-07-10"} }
{ "cluster": "my-test-cluster", "node": "worker-1", "level": "err", "message": "[err] failed data send", "timestamp": 1688992042, "default-number": 222222}

 

정상적으로 데이터가 들어갔는지 확인해 봅니다.

POST my-log-2023-07-10/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match_all": {}
        }
      ]
    }
  },
  "from": 0,
  "size": 20
}

 

마지막으로 저장된 데이터와 해당 데이터의 필드 타입이 어떻게 설정되었는지 확인합니다.

GET my-log-2023-07-10/

결과는 다음과 같습니다.

{
    "my-log-2023-07-10": {
        "aliases": {},
        "mappings": {
            "dynamic_templates": [
                {
                    "default_string": {
                        "match": "default*",
                        "match_mapping_type": "string",
                        "mapping": {
                            "type": "keyword"
                        }
                    }
                },
                {
                    "default_number": {
                        "match": "default*",
                        "match_mapping_type": "long",
                        "mapping": {
                            "type": "integer"
                        }
                    }
                }
            ],
            "properties": {
                "cluster": {
                    "type": "keyword"
                },
                "default-number": {
                    "type": "integer"
                },
                "default-text": {
                    "type": "keyword"
                },
                "level": {
                    "type": "keyword"
                },
                "message": {
                    "type": "text"
                },
                "node": {
                    "type": "keyword"
                },
                "timestamp": {
                    "type": "long"
                }
            }
        },
        "settings": {
            "index": {
                "opendistro": {
                    "index_state_management": {
                        "policy_id": "my-ism"
                    }
                },
                "refresh_interval": "5s",
                "number_of_shards": "4",
                "provided_name": "my-log-2023-07-10",
                "creation_date": "1688992258343",
                "number_of_replicas": "1",
                "uuid": "n24SvkagRl2OI0NcHb5SXw",
                "version": {
                    "created": "136297827"
                }
            }
        }
    }
}

template으로 지정한 필드의 경우 정상적으로 필드의 타입이 적용된 것을 확인할 수 있습니다. 그리고 default-number와 default-text의 경우 직접적으로 지정하지는 않았지만 dynamic_templates 설정을 통하여 자동적으로 문자열 타입은 keyword로 지정되고 숫자 타입은 integer로 설정된 것을 확인할 수 있습니다.

 

+ Recent posts