- 디스크 공간을 너무 많이 사용하는 작업 아티팩트
- 작업 애티팩트 업로드가 오류 500으로 실패하는 경우
- 작업 애티팩트 업로드가
500 Internal Server Error (Missing file)
로 실패하는 경우 - 작업 아티팩트를 Windows 마운트 사용 시
FATAL: invalid argument
로 업로드하지 못하는 문제 - 사용량 할당량이 잘못된 아티팩트 리포지터리 사용량을 표시함
관리자를 위한 작업 아티팩트 문제 해결
작업 아티팩트를 관리하는 동안 다음과 같은 문제가 발생할 수 있습니다.
디스크 공간을 너무 많이 사용하는 작업 아티팩트
작업 아티팩트는 예상보다 빠르게 디스크 공간을 채울 수 있습니다. 몇 가지 가능한 원인은 다음과 같습니다.
- 사용자가 작업 아티팩트 만료를 필요 이상으로 길게 구성한 것입니다.
- 실행된 작업의 수 및 따라서 생성된 아티팩트의 수가 예상보다 많습니다.
- 작업 로그가 예상보다 크고 시간이 지남에 따라 누적됩니다.
- 파일 시스템에서 inodes가 부족할 수 있습니다. 이는 아티팩트 정리에서 남겨진 빈 디렉터리 때문일 수 있습니다. 고아 아티팩트 파일 제거를 위한 Rake 작업을 통해 이를 제거할 수 있습니다.
- 아티팩트 파일이 디스크에 남아 있고 정리에 의해 삭제되지 않을 수 있습니다. 고아 아티팩트 파일 제거를 위한 Rake 작업을 실행하여 이를 제거하세요. 해당 스크립트는 항상 작업을 찾아야 합니다. 위와 마찬가지로 빈 디렉터리도 제거합니다.
- 아티팩트 정리가 중대하게 변경되었을 수 있으며, 업데이트된 시스템을 사용하려면 피처 플래그를 활성화해야 할 수 있습니다.
- 가장 최근 성공한 작업의 최신 아티팩트 유지 기능이 활성화되어 있을 수 있습니다.
이와 같은 경우 등에서는 디스크 공간 사용량이 가장 많은 프로젝트를 식별하고, 어떤 종류의 아티팩트가 가장 많은 공간을 사용하는지 파악하며, 경우에 따라 매뉴얼으로 작업 아티팩트를 삭제하여 디스크 공간을 회수하세요.
아티팩트 정리
아티팩트 정리는 만료된 아티팩트를 식별하고 삭제할 수 있는 프로세스입니다.
GitLab 15.0에서 15.2에서 비활성화된 정리
GitLab 15.0에서 아티팩트 정리가 크게 향상되었으며, 기본적으로 비활성화된 피처 플래그로 소개되었습니다. 이러한 플래그는 기본적으로 GitLab 15.3에서 활성화되었습니다.
GitLab 15.0에서 GitLab 15.2에서 아티팩트 정리가 작동하지 않는 것으로 보인다면 피처 플래그가 활성화되어 있는지 확인해야 합니다.
피처 플래그가 활성화되어 있는지 확인하려면 다음을 실행하세요:
-
Rails 콘솔을 시작합니다.
-
피처 플래그가 활성화되어 있는지 확인합니다.
Feature.enabled?(:ci_detect_wrongly_expired_artifacts) Feature.enabled?(:ci_update_unlocked_job_artifacts) Feature.enabled?(:ci_job_artifacts_backlog_work)
-
플래그 중 하나라도 비활성화되어 있다면, 활성화하세요:
Feature.enable(:ci_detect_wrongly_expired_artifacts) Feature.enable(:ci_update_unlocked_job_artifacts) Feature.enable(:ci_destroy_unlocked_job_artifacts)
이 변경에는 작업 아티팩트를 유지해야 할 경우, 아티팩트를 유지
에서 잠금
으로 변경하는 내용이 포함됩니다.
unknown
상태의 아티팩트
정리가 업데이트되기 전에 생성된 아티팩트는 unknown
상태를 가집니다. 만료되면, 이러한 아티팩트는 새로운 정리에 의해 처리되지 않습니다.
데이터베이스를 확인하여 인스턴스에 unknown
상태의 아티팩트가 있는지 확인할 수 있습니다:
-
데이터베이스 콘솔을 시작합니다:
Linux 패키지 (Omnibus)sudo gitlab-psql
Helm 차트 (Kubernetes)# 도구 상자 pod을 찾습니다 kubectl --namespace <namespace> get pods -lapp=toolbox # PostgreSQL 콘솔에 연결합니다 kubectl exec -it <toolbox-pod-name> -- /srv/gitlab/bin/rails dbconsole --include-password --database main
Dockersudo docker exec -it <container_name> /bin/bash gitlab-psql
자체 컴파일 (소스)sudo -u git -H psql -d gitlabhq_production
-
다음 쿼리를 실행합니다:
select expire_at, file_type, locked, count(*) from ci_job_artifacts where expire_at is not null and file_type != 3 group by expire_at, file_type, locked having count(*) > 1;
기록이 반환된다면 정리 작업이 처리할 수 없는 아티팩트가 있음을 나타냅니다. 예를 들어:
expire_at | file_type | locked | count
-------------------------------+-----------+--------+--------
2021-06-21 22:00:00+00 | 1 | 2 | 73614
2021-06-21 22:00:00+00 | 2 | 2 | 73614
2021-06-21 22:00:00+00 | 4 | 2 | 3522
2021-06-21 22:00:00+00 | 9 | 2 | 32
2021-06-21 22:00:00+00 | 12 | 2 | 163
상태가 2
인 아티팩트는 unknown
입니다. 자세한 내용은 이슈 #346261을 확인하세요.
unknown
아티팩트 정리
모든 unknown
아티팩트를 처리하는 Sidekiq 워커가 GitLab 15.3 이후에는 기본적으로 활성화됩니다. 이는 위의 데이터베이스 쿼리에서 반환된 아티팩트를 분석하고 잠금
또는 잠금 해제
할지를 결정합니다. 필요한 경우 해당 워커가 아티팩트를 삭제합니다.
Self-Managed형 인스턴스에서 워커를 활성화할 수 있습니다:
-
Rails 콘솔을 시작합니다.
-
기능이 활성화되어 있는지 확인합니다.
Feature.enabled?(:ci_job_artifacts_backlog_work)
-
필요하다면 기능을 활성화합니다:
Feature.enable(:ci_job_artifacts_backlog_work)
워커는 매 7분마다 10,000개의 unknown
아티팩트를 처리하며, 이는 대략 24시간에 200만 개의 아티팩트를 처리합니다.
관리자를 위한 워커가 unknown
아티팩트를 처리하는데 5배 큰 일괄 처리를 유도하는 ci_job_artifacts_backlog_large_loop_limit
피처 플래그도 있습니다. 이러한 플래그는 Self-Managed형 인스턴스에서 사용을 권장하지 않습니다.
특정 만료 일자(또는 만료 없음)를 가진 프로젝트 및 아티팩트 디렉터리
Rails 콘솔을 사용하여 다음 중 하나를 가진 작업 아티팩트가 있는 프로젝트를 찾을 수 있습니다:
- 만료 날짜가 없음
- 미래 7일 이상 후에 만료되는 일자
아티팩트를 삭제하는 방법과 유사하게 다음 예상 시간 범위를 사용하고 필요한대로 수정하세요:
7.days.from_now
10.days.from_now
2.weeks.from_now
3.months.from_now
1.year.from_now
다음 스크립트는 .limit(50)
으로 검색을 50개로 제한하지만, 이 숫자는 필요에 따라 변경할 수 있습니다:
# 만료되지 않는 아티팩트를 가진 빌드 및 프로젝트 찾기
artifacts_that_never_expire = Ci::Build.with_downloadable_artifacts.where(artifacts_expire_at: nil).limit(50)
artifacts_that_never_expire.find_each do |build|
puts "ID가 #{build.id}인 빌드에는 만료되지 않는 아티팩트가 있으며, 해당 프로젝트는 #{build.project.full_path}에 속합니다"
end
# 오늘로부터 7일 이후에 만료되는 아티팩트를 가진 빌드 및 프로젝트 찾기
artifacts_expire_in_a_week = Ci::Build.with_downloadable_artifacts.where('artifacts_expire_at > ?', 7.days.from_now).limit(50)
artifacts_expire_in_a_week.find_each do |build|
puts "ID가 #{build.id}인 빌드에는 #{build.artifacts_expire_at}에 만료되는 아티팩트가 있으며, 해당 프로젝트는 #{build.project.full_path}에 속합니다"
end
작업 애티팩트 저장된 총 크기별 프로젝트 디렉터리
다음 코드를 Rails 콘솔에서 실행하여 총 작업 애티팩트 크기순으로 정렬된 상위 20개 프로젝트를 나열합니다.
include ActionView::Helpers::NumberHelper
ProjectStatistics.order(build_artifacts_size: :desc).limit(20).each do |s|
puts "#{number_to_human_size(s.build_artifacts_size)} \t #{s.project.full_path}"
end
나열되는 프로젝트 수를 변경하려면 .limit(20)
을 원하는 숫자로 수정하세요.
단일 프로젝트에서 가장 큰 애티팩트 디렉터리
다음 코드를 Rails 콘솔에서 실행하여 단일 프로젝트에서 가장 큰 50개 작업 애티팩트를 나열합니다.
include ActionView::Helpers::NumberHelper
project = Project.find_by_full_path('path/to/project')
Ci::JobArtifact.where(project: project).order(size: :desc).limit(50).map { |a| puts "ID: #{a.id} - #{a.file_type}: #{number_to_human_size(a.size)}" }
나열되는 작업 애티팩트 수를 변경하려면 .limit(50)
을 원하는 숫자로 수정하세요.
단일 프로젝트의 애티팩트 디렉터리
애티팩트 크기순으로 정렬된 단일 프로젝트의 애티팩트를 나열합니다. 결과에는 다음이 포함됩니다:
- 애티팩트를 생성한 작업의 ID
- 애티팩트 크기
- 애티팩트 파일 유형
- 애티팩트 생성 날짜
- 애티팩트의 디스크 상 위치
p = Project.find_by_id(<project_id>)
arts = Ci::JobArtifact.where(project: p)
list = arts.order(size: :desc).limit(50).each do |art|
puts "Job ID: #{art.job_id} - Size: #{art.size}b - Type: #{art.file_type} - Created: #{art.created_at} - File loc: #{art.file}"
end
나열되는 작업 애티팩트 수를 변경하려면 limit(50)
의 숫자를 수정하세요.
오래된 빌드 및 애티팩트 삭제
프로젝트의 오래된 애티팩트 삭제
project = Project.find_by_full_path('path/to/project')
builds_with_artifacts = project.builds.with_downloadable_artifacts
builds_with_artifacts.where("finished_at < ?", 1.year.ago).each_batch do |batch|
batch.each do |build|
Ci::JobArtifacts::DeleteService.new(build).execute
end
batch.update_all(artifacts_expire_at: Time.current)
end
GitLab 15.3 및 이전 버전에서는 대신 다음을 사용하세요:
project = Project.find_by_full_path('path/to/project')
builds_with_artifacts = project.builds.with_downloadable_artifacts
builds_with_artifacts.where("finished_at < ?", 1.year.ago).each_batch do |batch|
batch.each do |build|
build.artifacts_expire_at = Time.current
build.erase_erasable_artifacts!
end
end
인스턴스 전체의 오래된 애티팩트 삭제
builds_with_artifacts = Ci::Build.with_downloadable_artifacts
builds_with_artifacts.where("finished_at < ?", 1.year.ago).each_batch do |batch|
batch.each do |build|
Ci::JobArtifacts::DeleteService.new(build).execute
end
batch.update_all(artifacts_expire_at: Time.current)
end
GitLab 15.3 및 이전 버전에서는 대신 다음을 사용하세요:
builds_with_artifacts = Ci::Build.with_downloadable_artifacts
builds_with_artifacts.where("finished_at < ?", 1.year.ago).each_batch do |batch|
batch.each do |build|
build.artifacts_expire_at = Time.current
build.erase_erasable_artifacts!
end
end
프로젝트의 오래된 작업 로그 및 애티팩트 삭제
project = Project.find_by_full_path('path/to/project')
builds = project.builds
admin_user = User.find_by(username: 'username')
builds.where("finished_at < ?", 1.year.ago).each_batch do |batch|
batch.each do |build|
print "Ci::Build ID #{build.id}... "
if build.erasable?
Ci::BuildEraseService.new(build, admin_user).execute
puts "Erased"
else
puts "Skipped (Nothing to erase or not erasable)"
end
end
end
인스턴스 전체의 오래된 작업 로그 및 애티팩트 삭제
builds = Ci::Build.all
admin_user = User.find_by(username: 'username')
builds.where("finished_at < ?", 1.year.ago).each_batch do |batch|
batch.each do |build|
print "Ci::Build ID #{build.id}... "
if build.erasable?
Ci::BuildEraseService.new(build, admin_user).execute
puts "Erased"
else
puts "Skipped (Nothing to erase or not erasable)"
end
end
end
GitLab 15.3 및 이전 버전에서는 Ci::BuildEraseService.new(build, admin_user).execute
대신 build.erase(erased_by: admin_user)
로 대체하세요.
1.year.ago
는 Rails ActiveSupport::Duration
메서드입니다. 실수로 여전히 사용 중인 애티팩트를 실수로 삭제하는 위험을 줄이기 위해 긴 기간부터 시작합니다. 필요할 때 짧은 기간으로 삭제를 다시 실행하세요. 예를 들어 3.months.ago
, 2.weeks.ago
, 또는 7.days.ago
가 있습니다.
erase_erasable_artifacts!
메서드는 동기적이며 실행 시 즉시 애티팩트가 제거되며, 백그라운드 대기열에 의해 예약되지 않습니다.
작업 애티팩트 업로드가 오류 500으로 실패하는 경우
애티팩트에 대해 객체 스토리지를 사용하고 작업 애티팩트 업로드가 실패한 경우 다음을 검토하세요:
-
오류 메시지가 포함된 작업 로그:
WARNING: Uploading artifacts as "archive" to coordinator... failed id=12345 responseStatus=500 Internal Server Error status=500 token=abcd1234
-
workhorse 로그에서 다음과 유사한 오류 메시지:
{"error":"MissingRegion: could not find region configuration","level":"error","msg":"error uploading S3 session","time":"2021-03-16T22:10:55-04:00"}
두 경우 모두 애티팩트의 객체 스토리지 구성(object storage configuration)(object_storage.md)에서 region
을 추가해야 할 수 있습니다.
작업 애티팩트 업로드가 500 Internal Server Error (Missing file)
로 실패하는 경우
폴더 경로를 포함하는 버킷 이름은 통합된 객체 스토리지와 호환되지 않습니다. 예를 들어, bucket/path
. 통합된 객체 스토리지를 사용하여 버킷 이름에 경로가 포함된 경우 다음과 유사한 오류가 발생할 수 있습니다.
WARNING: Uploading artifacts as "archive" to coordinator... POST https://gitlab.example.com/api/v4/jobs/job_id/artifacts?artifact_format=zip&artifact_type=archive&expire_in=1+day: 500 Internal Server Error (Missing file)
FATAL: invalid argument
통합된 객체 스토리지를 사용하는 경우 버킷당 별도의 버킷을 사용하는지 확인하세요.
작업 아티팩트를 Windows 마운트 사용 시 FATAL: invalid argument
로 업로드하지 못하는 문제
Windows 마운트에서 CIFS를 사용하여 작업 아티팩트를 사용하는 경우, 러너가 아티팩트를 업로드하려고 시도할 때 invalid argument
오류가 발생할 수 있습니다:
WARNING: Uploading artifacts as "dotenv" to coordinator... POST https://<your-gitlab-instance>/api/v4/jobs/<JOB_ID>/artifacts: 500 Internal Server Error id=1296 responseStatus=500 Internal Server Error status=500 token=*****
FATAL: invalid argument
이 문제를 해결하기 위해 다음을 시도할 수 있습니다:
- CIFS 대신 ext4 마운트로 전환합니다.
- CIFS 파일 임대와 관련된 중요한 버그 수정이 포함된 적어도 Linux 커널 5.15로 업그레이드합니다.
- 이전 커널의 경우
nolease
마운트 옵션을 사용하여 파일 임대를 비활성화합니다.
더 많은 정보는 조사 세부 정보를 참조하세요.
사용량 할당량이 잘못된 아티팩트 리포지터리 사용량을 표시함
때로는 아티팩트 리포지터리 사용량이 아티팩트가 사용하는 총 저장 공간에 대해 잘못된 값을 표시할 수 있습니다. 인스턴스의 모든 프로젝트에 대해 아티팩트 사용 통계를 다시 계산하려면 이 백그라운드 스크립트를 실행할 수 있습니다:
gitlab-rake gitlab:refresh_project_statistics_build_artifacts_size[https://example.com/path/file.csv]
https://example.com/path/file.csv
파일에는 아티팩트 리포지터리 사용량을 다시 계산하려는 모든 프로젝트의 프로젝트 ID를 나열해야 합니다. 파일에 대한 이 형식을 사용하세요:
PROJECT_ID
1
2
스크립트가 실행되는 동안 아티팩트 사용량 값이 0
으로 변동할 수 있습니다. 재계산 후에는 사용량이 다시 예상대로 표시되어야 합니다.