가비지 컬렉션
가비지 컬렉션 (Garbage collection)
Nomad 가비지 컬렉션은 프로그래밍 언어의 가비지 컬렉션과 같지 않지만, 그 설계 뒤의 동기는 비슷해요. 가비지 컬렉션은 스케줄러가 더 이상 참조하거나 필요로 하지 않는 객체에 할당된 메모리를 해제해요. Nomad는 종단(terminal) 상태인 객체만, 그리고 검사나 디버깅을 허용하기 위해 지연 후에만 가비지 컬렉션해요.
Nomad는 서버와 클라이언트 노드에서 가비지 컬렉션 프로세스를 실행해요. 서버에서 가비지 컬렉션을 수동으로 트리거할 수도 있어요.
Nomad는 다음 객체를 가비지 컬렉션해요:
출처: 문서
본문
캐스케이딩 가비지 컬렉션 (Cascading garbage collection)
Nomad의 스케줄링된 가비지 컬렉션 프로세스는 일반적으로 각 리소스 타입을 독립적으로 처리해요. 그러나 객체들이 서로를 참조하는 방식 때문에 암시적인 캐스케이드 관계가 있어요. 실제로 Nomad가 상위 레벨 객체를 가비지 컬렉션하면 Nomad는 고아 객체를 방지하기 위해 그 객체의 연관된 하위 객체도 제거해요.
예를 들어 잡을 가비지 컬렉션하면 Nomad는 그 잡의 남은 모든 평가, 배포, 할당 레코드도 상태에서 제거해요. Nomad는 이 객체들을 잡 가비지 컬렉션 프로세스의 일부로, 또는 각 객체의 자체 가비지 컬렉션 프로세스가 즉시 실행되어 가비지 컬렉션해요. Nomad의 스케줄링된 가비지 컬렉션 프로세스는 객체가 지정된 시간 임계값 이상 종단 상태이고 향후 스케줄링 결정에 더 이상 필요하지 않은 후에만 가비지 컬렉션해요. 이는 또한 잡이 중지되면 그 할당이 종단될 때까지 가비지 컬렉션될 수 없음을 의미해요. nomad system gc 명령을 실행해 가비지 컬렉션을 강제하면 Nomad가 지정된 시간 임계값을 무시하지만, 다른 모든 조건은 여전히 적용된다는 점에 유의하세요.
서버 쪽 가비지 컬렉션 (Server-side garbage collection)
Nomad 서버 리더는 가비지 컬렉션으로 표시된 객체를 메모리에서 정리하는 주기적인 가비지 컬렉션 프로세스를 시작해요. Nomad는 평가 같은 일부 객체를 자동으로 가비지 컬렉션으로 표시해요. 또는 nomad system gc를 실행해 잡을 수동으로 가비지 컬렉션으로 표시할 수 있는데, 이것이 가비지 컬렉션 프로세스를 실행해요.
구성 (Configuration)
이 설정들은 서버 노드의 가비지 컬렉션 동작을 관장해요. 구성 가능한 간격 설정이 없는 객체에 대한 간격은 config.go 클래스에서 검토할 수 있어요.
| 객체 | 간격 | 임계값 |
|---|---|---|
| ACL token | 5분 | acl_token_gc_threshold, 기본: 1시간 |
| CSI Plugin | 5분 | csi_plugin_gc_threshold, 기본: 1시간 |
| Deployment | 5분 | deployment_gc_threshold, 기본: 1시간 |
| Encryption root key | root_key_gc_interval, 기본: 10분 |
root_key_gc_threshold, 기본: 1시간 |
| Evaluation | 5분 | eval_gc_threshold, 기본: 1시간 |
| Evaluation, batch | 5분 | batch_eval_gc_threshold, 기본: 24시간 |
| Job | job_gc_interval, 기본: 5분 |
job_gc_threshold, 기본: 4시간 |
| Node | 5분 | node_gc_threshold, 기본: 24시간 |
| Volume | csi_volume_claim_gc_interval, 기본: 5분 |
csi_volume_claim_gc_threshold, 기본: 1시간 |
할당에는 독립적인 임계값 구성이 없어요. 특정 평가가 할당을 생성하므로 Nomad는 평가를 가비지 컬렉션할 때 할당을 가비지 컬렉션해요. 이는 또한 Nomad가 그 할당이 종단될 때까지 평가를 가비지 컬렉션할 수 없음을 의미해요.
트리거 (Triggers)
서버 가비지 컬렉션 프로세스는 만료되거나 종단된 객체를 영구 삭제하기 위해 구성된 간격으로 깨어나 스캔해요. 단, 객체가 종단 상태에 있던 시간이 그 가비지 컬렉션 임계값을 초과해야 해요. 예를 들어 잡의 기본 가비지 컬렉션 임계값은 4시간이므로, 가비지 컬렉션 프로세스가 잡과 그 의존 객체를 영구 삭제하기 전에 잡이 최소 4시간 동안 종단 상태여야 해요.
nomad system gc 명령을 수동으로 실행해 가비지 컬렉션을 강제하면 가비지 컬렉션 프로세스에 임계값을 무시하고 모든 서버와 클라이언트의 모든 종단 객체를 즉시 비우라고 지시하는 거예요.
클라이언트 쪽 가비지 컬렉션 (Client-side garbage collection)
각 클라이언트 노드에서 Nomad는 종료된 할당의 리소스를 정리해 머신의 디스크와 메모리를 확보해야 해요.
구성 (Configuration)
이 설정들은 각 클라이언트 노드에서 할당 가비지 컬렉션 동작을 관장해요.
| 매개변수 | 기본값 | 설명 |
|---|---|---|
gc_interval |
1분 | Nomad가 종단 할당 디렉터리를 가비지 컬렉션하려고 시도하는 간격 |
gc_disk_usage_threshold |
80 | Nomad가 종단 할당을 가비지 컬렉션해 유지하려고 하는 디스크 사용률(%) |
gc_inode_usage_threshold |
70 | Nomad가 종단 할당을 가비지 컬렉션해 유지하려고 하는 inode 사용률(%) |
gc_max_allocs |
50 | 클라이언트가 종단 할당의 가비지 컬렉션을 트리거하기 전에 추적할 최대 할당 수 |
gc_parallel_destroys |
2 | 가비지 컬렉터가 허용하는 최대 병렬 파괴 수 |
전체 매개변수 설명과 예시는 agent configuration reference의 client 블록을 참고하세요.
클라이언트 할당에는 시간 기반 보존 설정이 없다는 점에 유의하세요. 할당이 종단되자마자 구성된 임계값이 요구하거나 할당이 서버에서 가비지 컬렉션되면 정리 대상이 돼요.
트리거 (Triggers)
Nomad의 클라이언트는 다음 트리거를 기반으로 할당 가비지 컬렉션을 실행해요:
- 스케줄링된 간격
가비지 컬렉션 프로세스는 구성된 gc_interval에 따라 티커를 시작해요. 각 틱에서 가비지 컬렉션 프로세스는 종단 할당을 제거해야 하는지 확인해요.
- 종단 상태
할당이 종단 상태로 전환되면 Nomad는 할당을 가비지 컬렉션으로 표시하고 가비지 컬렉션 프로세스에 즉시 실행하라고 신호를 보내요. 스케줄링된 간격과 마찬가지로 임계값에 도달하지 않았다면 이것은 no-op일 수 있어요.
- 할당 배치
Nomad는 새 할당을 위한 공간을 만들기 위해 선제적으로 가비지 컬렉션을 실행할 수 있어요. 새 할당을 추가하면 gc_max_allocs 제한을 초과할 경우 클라이언트는 더 오래된 종단 할당을 가비지 컬렉션해요.
- 서버 가비지 컬렉션
서버가 할당을 가비지 컬렉션하거나 nomad system gc 명령을 실행해 가비지 컬렉션을 강제하면 가비지 컬렉션 프로세스가 클러스터 전역의 모든 임계값 설정을 무시하고 모든 서버와 클라이언트의 모든 종단 객체를 제거해요.
Nomad는 디스크나 inode 사용률을 지속적으로 모니터링해 가비지 컬렉션을 트리거하지 않아요. 대신 Nomad는 앞서 언급한 트리거 중 하나가 가비지 컬렉션 프로세스를 호출할 때만 디스크와 inode 임계값을 확인해요. gc_inode_usage_threshold와 gc_disk_usage_threshold 값은 가비지 컬렉션을 트리거하지 않아요. 그보다 이 값들은 컬렉션 실행 중에 가비지 컬렉터가 어떻게 동작하는지에 영향을 줘요.
할당 선택 (Allocation selection)
가비지 컬렉션 프로세스가 실행되면 Nomad는 리소스 임계값을 충족하는 데 필요한 만큼 완료된 할당을 파괴해요. 클라이언트는 완료 표시된 시간 순(가장 오래된 것 먼저)으로 정렬된 종단 할당의 우선순위 큐를 유지해요.
프로세스는 조건이 구성된 한도 안으로 돌아올 때까지 큐에서 할당을 반복적으로 축출해요. 구체적으로 가비지 컬렉션 루프는 순서대로 확인해요:
- 디스크 사용률이
gc_disk_usage_threshold값을 초과하는지 - inode 사용률이
gc_inode_usage_threshold값을 초과하는지 - 할당 수가
gc_max_allocs값을 초과하는지
이 조건 중 하나라도 true이면 가비지 컬렉터는 제거할 가장 오래된 완료 할당을 선택해요.
하나의 할당을 삭제한 후 루프는 지표를 다시 확인하고 모든 임계값이 충족되거나 종단 할당이 더 이상 없을 때까지 다음으로 오래된 할당을 계속 제거해요. 이는 노드가 한도를 훨씬 초과했다면 단일 실행에서 가비지 컬렉션이 여러 할당을 연속으로 제거한다는 뜻이에요. 축출은 종료 시간 순으로 발생하며, 가장 먼저 완료된 할당이 먼저예요.
노드의 사용률과 할당 수가 한도 미만이면 정상 가비지 컬렉션 주기는 어떤 할당도 제거하지 않아요. 즉 주기적·이벤트 기반 가비지 컬렉션은 할당이 완료되었다는 이유만으로 삭제하지 않아요. 압박이나 한도 도달이 있어야 해요. 예외는 관리 명령이나 서버 쪽 제거가 클라이언트 쪽 가비지 컬렉션을 트리거할 때예요. 그 강제 시나리오를 제외하면 기본 동작은 임계값 기반이에요. Nomad는 공간, inode 또는 수 제한에 도달해 그 할당들을 회수해야 할 때까지 할당을 디스크에 남겨둬요.
태스크 드라이버 리소스 가비지 컬렉션 (Task driver resources garbage collection)
대부분의 태스크 드라이버는 자체 가비지 컬렉션 프로세스가 없어요. 할당이 종단되면 클라이언트 가비지 컬렉션 프로세스가 태스크 드라이버와 통신해 태스크의 리소스가 정리되었는지 확인해요. Docker 태스크 드라이버는 자체 리소스를 주기적으로 정리한다는 점에 유의하세요. 자세한 내용은 Docker task driver plugin options를 참고하세요.
태스크에 재시작 시도가 구성되어 있고 태스크가 실패하면 Nomad 클라이언트는 같은 할당 안에서 인플레이스 태스크 재시작을 시도해요. 태스크 드라이버는 태스크에 대해 새 프로세스나 컨테이너를 시작해요. 태스크가 계속 실패하고 구성된 재시작 시도를 초과하면 Nomad는 태스크를 종료하고 할당을 종단으로 표시해요. 그런 다음 태스크 드라이버는 Docker 컨테이너나 cgroups 같은 리소스를 정리해요. 가비지 컬렉션 프로세스가 실행되면 할당을 삭제하기 전에 태스크 드라이버 정리가 완료되었는지 확인해요. 태스크 드라이버가 제대로 정리하지 못하면 Nomad는 오류를 기록하지만 가비지 컬렉션 프로세스를 계속해요. 태스크 드라이버 정리 실패 문제는 할당이 실제로 언제 해제되는지에 영향을 줄 수 있어요. 예를 들어 볼륨이 분리되지 않으면 수정될 때까지 디스크 공간이 완전히 회수되지 않을 수 있어요.
리소스 (Resources)
- Nomad's internal garbage collection and optimization discovery during the Nomad Bench project blog post
- 구성
- the
nomad system gccommand reference - System HTTP API Force GC