正式なドキュメントは英語版であり、この日本語訳はAI支援翻訳により作成された参考用のものです。日本語訳の一部の内容は人間によるレビューがまだ行われていないため、翻訳のタイミングにより英語版との間に差異が生じることがあります。最新かつ正確な情報については、英語版をご参照ください。
ドキュメントに関する現在のご利用体験についてお聞かせください。アンケートにご協力ください。

ストレージ管理を自動化する

  • プラン: Free、Premium、Ultimate
  • 提供形態: GitLab.com、GitLab Self-Managed、GitLab Dedicated

このページでは、GitLab REST APIを使用してストレージの使用状況を管理するための、ストレージ分析とクリーンアップを自動化する方法について説明します。

パイプライン効率性を向上させることによって、ストレージの使用状況を管理することもできます。

API自動化に関する詳細については、GitLabコミュニティフォーラムとDiscordも使用できます。

このページのスクリプト例はデモンストレーションのみを目的としており、本番環境では使用しないでください。例を使用して、ストレージ自動化用の独自のスクリプトを設計およびテストできます。

API要件

ストレージ管理を自動化するには、GitLab.comまたはGitLab Self-ManagedのインスタンスがGitLab REST APIにアクセスできる必要があります。

API認証スコープ

APIで認証するには、次のスコープを使用します:

  • ストレージ分析:
    • read_apiスコープを使用した読み取りAPIアクセス。
    • すべてのプロジェクトにおけるデベロッパー、メンテナー、またはオーナーのロール。
  • ストレージクリーンアップ:
    • apiスコープを使用したフルAPIアクセス。
    • すべてのプロジェクトにおけるメンテナーまたはオーナーのロール。

コマンドラインツールまたはプログラミング言語を使用して、REST APIを操作できます。

コマンドラインツール

APIリクエストを送信するには、次のいずれかをインストールします:

  • お好みのパッケージマネージャーでcURL。
  • GitLab CLIを使用し、glab apiサブコマンドを使用します。

JSONレスポンスをフォーマットするには、jqをインストールします。詳細については、生産的なDevOpsワークフローのヒント: を参照してください: jqとCI/CDのLint自動化によるJSONフォーマット。

これらのツールをREST APIで使用するには:

shell
export GITLAB_TOKEN=xxx

curl --silent --header "Authorization: Bearer $GITLAB_TOKEN" "https://gitlab.com/api/v4/user" | jq
shell
glab auth login

glab api groups/YOURGROUPNAME/projects

GitLab CLIの使用

一部のAPIエンドポイントでは、すべての結果を取得するためにページネーションと後続のページのフェッチが必要です。GitLab CLIはフラグ--paginateを提供します。

JSONデータとしてフォーマットされたPOSTボディを必要とするリクエストは、key=valueのペアとして--raw-fieldパラメータに渡すことができます。

詳細については、GitLab CLIエンドポイントのドキュメントを参照してください。

APIクライアントライブラリ

このページで説明されているストレージ管理とクリーンアップの自動化メソッドでは、以下を使用します:

  • 豊富な機能を持つプログラミングインターフェースを提供するpython-gitlabライブラリ。
  • GitLab APIとPythonプロジェクトにあるget_all_projects_top_level_namespace_storage_analysis_cleanup_example.pyスクリプト。

python-gitlabライブラリのユースケースの詳細については、効率的なDevSecOpsワークフロー: を参照してください: 実践的なpython-gitlab API自動化。

他のAPIクライアントライブラリの詳細については、サードパーティクライアントを参照してください。

GitLab Duoコード提案を使用して、コードをより効率的に記述します。

ストレージ分析

ストレージタイプを特定する

プロジェクトAPIエンドポイントは、GitLabインスタンス内のプロジェクトの統計情報を提供します。プロジェクトAPIエンドポイントを使用するには、statisticsキーをブール値trueに設定します。このデータは、次のストレージタイプごとのプロジェクトのストレージ消費量に関するインサイトを提供します:

  • storage_size: 全体的なストレージ
  • lfs_objects_size: LFSオブジェクトストレージ
  • job_artifacts_size: ジョブアーティファクトストレージ
  • packages_size: パッケージストレージ
  • repository_size: Gitリポジトリストレージ
  • snippets_size: スニペットストレージ
  • uploads_size: アップロードストレージ
  • wiki_size: Wikiストレージ

ストレージタイプを特定するには:

shell
curl --silent --header "Authorization: Bearer $GITLAB_TOKEN" "https://gitlab.com/api/v4/projects/$GL_PROJECT_ID?statistics=true" | jq --compact-output '.id,.statistics' | jq
48349590
{
  "commit_count": 2,
  "storage_size": 90241770,
  "repository_size": 3521,
  "wiki_size": 0,
  "lfs_objects_size": 0,
  "job_artifacts_size": 90238249,
  "pipeline_artifacts_size": 0,
  "packages_size": 0,
  "snippets_size": 0,
  "uploads_size": 0
}
shell
export GL_PROJECT_ID=48349590
glab api --method GET projects/$GL_PROJECT_ID --field 'statistics=true' | jq --compact-output '.id,.statistics' | jq
48349590
{
  "commit_count": 2,
  "storage_size": 90241770,
  "repository_size": 3521,
  "wiki_size": 0,
  "lfs_objects_size": 0,
  "job_artifacts_size": 90238249,
  "pipeline_artifacts_size": 0,
  "packages_size": 0,
  "snippets_size": 0,
  "uploads_size": 0
}
python
project_obj = gl.projects.get(project.id, statistics=True)

print("Project {n} statistics: {s}".format(n=project_obj.name_with_namespace, s=json.dump(project_obj.statistics, indent=4)))

プロジェクトの統計情報をターミナルに出力するには、GL_GROUP_ID環境変数をエクスポートしてスクリプトを実行します:

shell
export GL_TOKEN=xxx
export GL_GROUP_ID=56595735

pip3 install python-gitlab
python3 get_all_projects_top_level_namespace_storage_analysis_cleanup_example.py

Project Developer Evangelism and Technical Marketing at GitLab  / playground / Artifact generator group / Gen Job Artifacts 4 statistics: {
    "commit_count": 2,
    "storage_size": 90241770,
    "repository_size": 3521,
    "wiki_size": 0,
    "lfs_objects_size": 0,
    "job_artifacts_size": 90238249,
    "pipeline_artifacts_size": 0,
    "packages_size": 0,
    "snippets_size": 0,
    "uploads_size": 0
}

プロジェクトとグループのストレージを分析する

複数のプロジェクトとグループの分析を自動化できます。たとえば、最上位のネームスペースレベルから開始し、すべてのサブグループとプロジェクトを再帰的に分析できます。異なるストレージタイプを分析することもできます。

複数のサブグループとプロジェクトを分析するアルゴリズムの例を次に示します:

  1. 最上位ネームスペースのIDをフェッチします。ネームスペース/グループの概要からID値をコピーできます。
  2. トップレベルグループからすべてのサブグループをフェッチし、IDをリストに保存します。
  3. すべてのグループをループして、各グループからすべてのプロジェクトをフェッチし、IDをリストに保存します。
  4. 分析するストレージタイプを特定し、プロジェクト統計やジョブアーティファクトなどのプロジェクト属性から情報を収集します。
  5. すべてのプロジェクトをグループごとにグループ化し、そのストレージ情報の概要を出力します。

glabを使用したShellアプローチは、小規模な分析により適している場合があります。大規模な分析の場合は、APIクライアントライブラリを使用するスクリプトを使用する必要があります。この種類のスクリプトは、可読性、データストレージ、フロー制御、テスト、再利用性を向上させることができます。

スクリプトがAPIレート制限に達しないようにするため、以下のサンプルコードは並列APIリクエスト用に最適化されていません。

このアルゴリズムを実装するには:

shell
export GROUP_NAME="gitlab-da"

# Return subgroup IDs
glab api groups/$GROUP_NAME/subgroups | jq --compact-output '.[]' | jq --compact-output '.id'
12034712
67218622
67162711
67640130
16058698
12034604

# Loop over all subgroups to get subgroups, until the result set is empty. Example group: 12034712
glab api groups/12034712/subgroups | jq --compact-output '.[]' | jq --compact-output '.id'
56595735
70677315
67218606
70812167

# Lowest group level
glab api groups/56595735/subgroups | jq --compact-output '.[]' | jq --compact-output '.id'
# empty result, return and continue with analysis

# Fetch projects from all collected groups. Example group: 56595735
glab api groups/56595735/projects | jq --compact-output '.[]' | jq --compact-output '.id'
48349590
48349263
38520467
38520405

# Fetch storage types from a project (ID 48349590): Job artifacts in the `artifacts` key
glab api projects/48349590/jobs | jq --compact-output '.[]' | jq --compact-output '.id, .artifacts'
4828297946
[{"file_type":"archive","size":52444993,"filename":"artifacts.zip","file_format":"zip"},{"file_type":"metadata","size":156,"filename":"metadata.gz","file_format":"gzip"},{"file_type":"trace","size":3140,"filename":"job.log","file_format":null}]
4828297945
[{"file_type":"archive","size":20978113,"filename":"artifacts.zip","file_format":"zip"},{"file_type":"metadata","size":157,"filename":"metadata.gz","file_format":"gzip"},{"file_type":"trace","size":3147,"filename":"job.log","file_format":null}]
4828297944
[{"file_type":"archive","size":10489153,"filename":"artifacts.zip","file_format":"zip"},{"file_type":"metadata","size":158,"filename":"metadata.gz","file_format":"gzip"},{"file_type":"trace","size":3146,"filename":"job.log","file_format":null}]
4828297943
[{"file_type":"archive","size":5244673,"filename":"artifacts.zip","file_format":"zip"},{"file_type":"metadata","size":157,"filename":"metadata.gz","file_format":"gzip"},{"file_type":"trace","size":3145,"filename":"job.log","file_format":null}]
4828297940
[{"file_type":"archive","size":1049089,"filename":"artifacts.zip","file_format":"zip"},{"file_type":"metadata","size":157,"filename":"metadata.gz","file_format":"gzip"},{"file_type":"trace","size":3140,"filename":"job.log","file_format":null}]
python
#!/usr/bin/env python

import datetime
import gitlab
import os
import sys

GITLAB_SERVER = os.environ.get('GL_SERVER', 'https://gitlab.com')
GITLAB_TOKEN = os.environ.get('GL_TOKEN') # token requires developer permissions
PROJECT_ID = os.environ.get('GL_PROJECT_ID') #optional
GROUP_ID = os.environ.get('GL_GROUP_ID') #optional

if __name__ == "__main__":
    if not GITLAB_TOKEN:
        print("🤔 Please set the GL_TOKEN env variable.")
        sys.exit(1)

    gl = gitlab.Gitlab(GITLAB_SERVER, private_token=GITLAB_TOKEN, pagination="keyset", order_by="id", per_page=100)

    # Collect all projects, or prefer projects from a group id, or a project id
    projects = []

    # Direct project ID
    if PROJECT_ID:
        projects.append(gl.projects.get(PROJECT_ID))
    # Groups and projects inside
    elif GROUP_ID:
        group = gl.groups.get(GROUP_ID)

        for project in group.projects.list(include_subgroups=True, get_all=True):
            manageable_project = gl.projects.get(project.id , lazy=True)
            projects.append(manageable_project)

    for project in projects:
        jobs = project.jobs.list(pagination="keyset", order_by="id", per_page=100, iterator=True)
        for job in