메모리 사용 줄이기

GitLab Rails 애플리케이션 코드에서 메모리 누수가 발생합니다.

웹 요청의 경우, 이 문제는 특정 시간 동안 주어진 상주 집합 크기(RSS) 임계값을 초과하는 경우 워커를 자동으로 재시작하는 감독 스레드를 사용하여 관리됩니다.

GitLab에서 배경 작업을 처리하는 데 사용하는 Sidekiq 프로세스에도 동일한 접근 방식을 적용합니다.

기본적으로 GitLab은 Linux 패키지 또는 Docker 설치에 대해서만 사용 가능한 RSS 한계를 모니터링합니다.

그 이유는 GitLab이 메모리로 인한 종료 후 Sidekiq를 재시작하기 위해 runit에 의존하고, 자가 컴파일 및 Helm 차트 설치는 runit 또는 동등한 도구를 사용하지 않기 때문입니다.

기본 설정에서 Sidekiq는 15분마다 한 번 이하로만 재시작되며, 이로 인해 수신되는 백그라운드 작업에 약 1분의 지연이 발생합니다.

일부 백그라운드 작업은 장기 실행 외부 프로세스에 의존합니다. 이러한 프로세스가 Sidekiq가 재시작될 때 깔끔하게 종료되도록 하기 위해 각 Sidekiq 프로세스는 프로세스 그룹 리더로 실행되어야 합니다(예: chpst -P 사용). Linux 패키지 설치 또는 runit가 설치된 bin/background_jobs 스크립트를 사용하는 경우, 이 작업은 자동으로 처리됩니다.

한계 설정

Sidekiq 메모리 한계는 환경 변수를 사용하여 제어됩니다.

  • SIDEKIQ_MEMORY_KILLER_MAX_RSS (KB): 허용된 RSS에 대한 Sidekiq 프로세스 소프트 제한을 정의합니다.

    Sidekiq 프로세스 RSS(킬로바이트로 표현)가 SIDEKIQ_MEMORY_KILLER_MAX_RSS를 초과하고 SIDEKIQ_MEMORY_KILLER_GRACE_TIME보다 오랫동안 지속되면, 우아한 재시작이 트리거됩니다.

    SIDEKIQ_MEMORY_KILLER_MAX_RSS가 설정되지 않았거나 값이 0으로 설정된 경우, 소프트 제한은 모니터링되지 않습니다.

    SIDEKIQ_MEMORY_KILLER_MAX_RSS의 기본값은 2000000입니다.

  • SIDEKIQ_MEMORY_KILLER_GRACE_TIME: 허용된 RSS 소프트 제한보다 높은 상태에서 Sidekiq 프로세스가 실행될 수 있는 유예 시간(초)을 정의합니다.

    Sidekiq 프로세스가 SIDEKIQ_MEMORY_KILLER_GRACE_TIME 내에 허용된 RSS(소프트 제한) 아래로 내려가면, 재시작이 중단됩니다. 기본값은 900초(15분)입니다.

  • SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS (KB): 허용된 RSS에 대한 Sidekiq 프로세스 하드 제한을 정의합니다.

    Sidekiq 프로세스 RSS(킬로바이트로 표현)가 SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS를 초과하면, Sidekiq의 즉각적인 우아한 재시작이 트리거됩니다. 이 값이 설정되지 않았거나 0으로 설정된 경우, 하드 제한은 모니터링되지 않습니다.

  • SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL: 프로세스 RSS를 확인하는 빈도를 정의합니다. 기본값은 3초입니다.

  • SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT: 모든 Sidekiq 작업이 완료되는 데 허용되는 최대 시간을 정의합니다.

    이 시간 동안 새로운 작업은 수락되지 않습니다. 기본값은 30초입니다.

    프로세스 재시작이 Sidekiq에 의해 수행되지 않으면, Sidekiq 프로세스는 Sidekiq 종료 타임아웃( 기본값 25초) + 2초 후에 강제로 종료됩니다.

    지정된 시간 내에 작업이 완료되지 않으면, 현재 실행 중인 모든 작업은 Sidekiq 프로세스에 SIGTERM 신호가 전송되어 중단됩니다.

  • GITLAB_MEMORY_WATCHDOG_ENABLED: 기본적으로 활성화되어 있습니다. Watchdog가 실행되지 않도록 하려면 GITLAB_MEMORY_WATCHDOG_ENABLED를 false로 설정하세요.

작업자 재시작 모니터링

GitLab은 작업자가 메모리 사용량이 높아 재시작될 경우 로그 이벤트를 발생시킵니다.

다음은 /var/log/gitlab/gitlab-rails/sidekiq_client.log에서 이러한 로그 이벤트 중 하나의 예입니다:

{
  "severity": "WARN",
  "time": "2023-02-04T09:45:16.173Z",
  "correlation_id": null,
  "pid": 2725,
  "worker_id": "sidekiq_1",
  "memwd_handler_class": "Gitlab::Memory::Watchdog::SidekiqHandler",
  "memwd_sleep_time_s": 3,
  "memwd_rss_bytes": 1079683247,
  "memwd_max_rss_bytes": 629145600,
  "memwd_max_strikes": 5,
  "memwd_cur_strikes": 6,
  "message": "rss 메모리 한도 초과",
  "running_jobs": [
    {
      jid: "83efb701c59547ee42ff7068",
      worker_class: "Ci::DeleteObjectsWorker"
    },
    {
      jid: "c3a74503dc2637f8f9445dd3",
      worker_class: "Ci::ArchiveTraceWorker"
    }
  ]
}

여기서:

  • memwd_rss_bytes는 실제로 소비된 메모리의 양입니다.
  • memwd_max_rss_bytesper_worker_max_memory_mb를 통해 설정된 RSS 제한입니다.
  • running jobs는 프로세스가 RSS 제한을 초과하여 우아한 재시작을 시작할 때 실행 중이던 작업을 나열합니다.