Incident Library

IL-0579 Classi · 2026-11-11 (게시일)databaseaws

Elasticsearch 6.8 에서 OpenSearch 1.3 으로 옮긴 뒤 포트폴리오 검색의 응답 시간이 간헐적으로 1초 가까이 튀었다

Classi 는 포트폴리오 기능에 학생이 학교생활 중 기록한 데이터를 쌓고, 이를 검색하려고 Amazon OpenSearch Service 를 쓴다. 검색 엔진을 Elasticsearch 6.8 에서 OpenSearch 1.3 으로 옮기면서 Ruby 클라이언트를 elasticsearch-model 과 elasticsearch-rails 에서 opensearch-ruby 로, 인스턴스 타입을 m5.large.search 에서 AWS Graviton 기반의 m7g.large.search 로 함께 바꿨다. 문서 3,000만 건 이상은 기존 Elasticsearch 도메인의 스냅샷을 새 OpenSearch 도메인에 복원해 옮겼다.

옮긴 뒤 검색 처리의 최대 응답 시간이 이전의 100ms 정도에서 1초 안팎까지 간헐적으로 튀었다. 팀은 Slow Log 와 Profile API 로 쿼리 처리를 보고, HTTP 클라이언트 설정과 GC 를 확인하고, curl 로 직접 검색해 봤지만 원인을 찾지 못했다. 언제 느려지는지를 살피다가 문서를 갱신한 뒤의 검색이 늦어진다는 가설을 세웠고, refresh_interval 을 명시해 3s 로 설정하자 지연이 크게 줄었다. 1s 로 명시해도 개선이 유지되어 운영 환경에도 1s 로 명시해 설정했고, 그 뒤 간헐적인 지연이 사라졌다.

원인은 Search Idle 이었다. Elasticsearch 6.x 까지는 refresh_interval 을 정하지 않아도 1초마다 Refresh 가 돌았다. Elasticsearch 7.0 에서 들어온 Search Idle 은 refresh_interval 이 명시되지 않으면 일정 시간 검색되지 않은 샤드를 Idle 상태로 두고 백그라운드 Refresh 를 멈춘다. Elasticsearch 7.10 을 바탕으로 한 OpenSearch 도 이 동작을 물려받았고, index.search.idle.after 의 기본값은 30s 다. Idle 상태의 샤드에 검색이 들어왔을 때 Refresh 가 필요하면 첫 검색은 Refresh 가 끝날 때까지 기다린다. refresh_interval 을 명시하면 샤드가 이 제어에서 빠져 정한 간격으로 Refresh 된다.

심각도
–
영향 범위
Search for the Portfolio feature: maximum search latency intermittently about 1 second instead of about 100ms
영향 사용자
–
지역
–
감지까지
–
복구까지
–

증상

OpenSearch 1.3 으로 옮긴 뒤 동작을 확인하던 중 팀은 검색 응답이 가끔 크게 늦어지는 것을 알아챘다. 평소에는 응답이 정상으로 돌아왔고, 일정한 빈도로 응답 시간이 크게 튀었다.

Datadog APM 에서 검색 처리의 최대 응답 시간을 옮기기 전후로 비교했다. Elasticsearch 6.8 을 쓰던 기간에는 대체로 100ms 정도였고, OpenSearch 1.3 으로 옮긴 뒤에는 1초 안팎까지 올라가는 경우가 간헐적으로 생겼다. 평소의 응답 시간이 전체적으로 나빠진 것은 아니었다.

쿼리 자체가 느린지 먼저 의심했다. Slow Log 의 기준값을 0ms 로 두고 모든 쿼리를 기록해 애플리케이션에서 늦어진 시각과 맞춰 봤지만, 그 지연에 해당하는 쿼리 처리 시간은 보이지 않았다.

Search API 의 profile=true 로 처리 내역을 봤다. 늦어진 한 요청에서 애플리케이션이 잰 처리 시간은 867.5ms, OpenSearch 응답의 took 은 839ms 였지만, 샤드별 쿼리 처리 시간은 모두 1ms 미만이었다.

다음으로 애플리케이션과 OpenSearch 사이의 통신을 의심했다. Keep-Alive 와 idle_timeout 설정, Faraday 의 HTTP Adapter 를 바꿔 보고 OpenSearch 쪽 GC 도 확인했지만, 어느 것도 응답 시간과 뚜렷한 관련이 없었다. curl 로 Search API 를 직접 불렀을 때 같은 쿼리를 연달아 실행하면 첫 번째만 늦은 경우가 있었지만 재현되지 않았다.

팀은 어디가 느린지가 아니라 언제 느려지는지를 보기로 하고 검색과 갱신을 되풀이했다. 문서를 추가하거나 갱신한 뒤에 검색하면 응답 시간이 커질 수 있다는 가설이 나왔다.

증상 지연 시간 증가

원인

촉발
포트폴리오 기능의 검색 엔진을 Elasticsearch 6.8 에서 Amazon OpenSearch Service 의 OpenSearch 1.3 으로 옮겼다.

감지

OpenSearch 1.3 으로 옮긴 뒤 동작을 확인하던 중 팀이 검색 응답이 가끔 크게 늦어지는 것을 알아챘다. Datadog APM 에서 검색 처리의 최대 응답 시간을 옮기기 전후로 비교해 간헐적인 지연을 확인했다.

조치

후속 조치

–

교훈

OpenSearch 응답의 took 이 커져 있었으므로 더 일찍 OpenSearch 쪽으로 조사 범위를 좁힐 수 있었다고 팀은 돌아봤다. Slow Log 와 Profile API 만으로는 원인을 찾지 못했고, 어디가 느린지에서 언제 느려지는지로 관점을 바꾼 것이 개선의 계기였다. 버전에 따라 같은 설정 값이라도 동작이 다르므로 기본 동작까지 확인해야 한다고 정리했다.

출처

관련 사례

–

내 클러스터에도 있는지 확인하기

kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이 사례와 같은 상태를 점검합니다. 이 사례의 구성 요소: Elasticsearch 와 OpenSearch. 점검 항목의 근거는 이 사례 같은 공개 보고서입니다.

AI 도구와 스크립트용

API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.