すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud Service Mesh:マルチ LoRA シナリオでの LLM 推論サービスのグレイリリース戦略

最終更新日:Jun 06, 2025

Kubernetes クラスターに Low-Rank Adaptation(LoRA)テクノロジーに基づく微調整を伴う大規模言語モデル(LLM)をデプロイすることは、カスタマイズされた推論機能を提供するための柔軟で効率的な方法です。このトピックでは、Service Mesh (ASM)内でマルチ LoRA を使用して LLM 推論サービスを微調整する方法、さまざまな LoRA モデルのトラフィック分散ポリシーを定義する方法、および LoRA モデルのグレイリリースを実装する方法について説明します。

始める前に

このトピックを読む前に、以下を理解する必要があります:

このトピックを読むことで、以下について学ぶことができます:

  • LoRA およびマルチ LoRA テクノロジーの背景情報。

  • LoRA 微調整モデルのグレイリリースシナリオの実装原則。

  • マルチ LoRA テクノロジーを使用して LoRA モデルのグレイリリースを実装する手順。

背景情報

LoRA とマルチ LoRA

LoRA は、医療、金融、教育など、さまざまなセクターの特定のニーズに合わせて、費用対効果の高い方法で大規模言語モデル(LLM)を微調整するために広く採用されているテクノロジーです。これにより、推論のために単一のベース LLM に複数の LoRA モデルの重みをデプロイすることができ、マルチ LoRA テクノロジーとして知られる効率的な GPU リソースの共有が可能になります。 vLLM プラットフォームは、複数の LoRA モデルのロードと推論をサポートしています。

LoRA 微調整モデルのグレイリリースシナリオ

マルチ LoRA シナリオでは、複数の LoRA モデルを単一の LLM 推論サービスにロードできます。異なるモデルへのリクエストは、リクエスト内のモデル名によって区別され、さまざまな LoRA モデル間でグレイテストを実行して、ベース LLM に対する微調整の効果を評価できます。

前提条件

手順

このプラクティスでは、vLLM を使用してクラスターにベースモデルとして Llama2 ラージモデルをデプロイし、このベースモデルに基づいて sql-lora から sql-lora-4、および tweet-summary から tweet-summary-4 という名前の 10 個の LoRA モデルを登録します。必要に応じて、GPU アクセラレーションノードまたは ACS クラスターを持つ ACK クラスターで検証することを選択します。

ステップ 1: サンプルの LLM 推論サービスをデプロイする

  1. 以下に示すコンテンツを使用して vllm-service.yaml を作成します。

    説明

    このトピックで説明されているイメージには、16 GiB 以上のビデオメモリを搭載した GPU が必要です。 16 GiB のビデオメモリを搭載した T4 カードタイプでは、このアプリケーションを起動するための十分なリソースが提供されません。 ACK クラスターには A10 カードタイプ、ACS クラスターには第 8 世代 GPU B を使用することをお勧めします。モデルの詳細については、チケットを送信してサポートを受けてください。

    LLM イメージのサイズが大きいため、事前に ACR に保存し、プルに内部ネットワークアドレスを使用することをお勧めします。パブリックネットワークから直接プルすると、クラスターの EIP 帯域幅構成によっては、待機時間が長くなる可能性があります。

    ACK クラスター

    展開して YAML コンテンツを表示する

    apiVersion: v1
    kind: Service
    metadata:
      name: vllm-llama2-7b-pool
    spec:
      selector:
        app: vllm-llama2-7b-pool
      ports:
      - protocol: TCP
        port: 8000
        targetPort: 8000
      type: ClusterIP
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: chat-template
    data:
      llama-2-chat.jinja: |
        # 会話の役割は、ユーザー/アシスタント/ユーザー/アシスタント/...と交互に繰り返される必要があります。
        {% if messages[0]['role'] == 'system' %}
          {% set system_message = '<<SYS>>\n' + messages[0]['content'] | trim + '\n<</SYS>>\n\n' %}
          {% set messages = messages[1:] %}
        {% else %}
            {% set system_message = '' %}
        {% endif %}
    
        {% for message in messages %}
            {% if (message['role'] == 'user') != (loop.index0 % 2 == 0) %}
                {{ raise_exception('Conversation roles must alternate user/assistant/user/assistant/...') }}
            {% endif %}
    
            {% if loop.index0 == 0 %}
                {% set content = system_message + message['content'] %}
            {% else %}
                {% set content = message['content'] %}
            {% endif %}
            {% if message['role'] == 'user' %}
                {{ bos_token + '[INST] ' + content | trim + ' [/INST]' }}
            {% elif message['role'] == 'assistant' %}
                {{ ' ' + content | trim + ' ' + eos_token }}
            {% endif %}
        {% endfor %}
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vllm-llama2-7b-pool
      namespace: default
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: vllm-llama2-7b-pool
      template:
        metadata:
          annotations:
            prometheus.io/path: /metrics
            prometheus.io/port: '8000'
            prometheus.io/scrape: 'true'
          labels:
            app: vllm-llama2-7b-pool
        spec:
          containers:
            - name: lora
              image: "registry-cn-hangzhou-vpc.ack.aliyuncs.com/dev/llama2-with-lora:v0.2"
              imagePullPolicy: IfNotPresent
              command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
              args:
              - "--model"
              - "/model/llama2"
              - "--tensor-parallel-size"
              - "1"
              - "--port"
              - "8000"
              - '--gpu_memory_utilization'
              - '0.8'
              - "--enable-lora"
              - "--max-loras"
              - "10"
              - "--max-cpu-loras"
              - "12"
              - "--lora-modules"
              # LoRA モジュールを定義します。
              - 'sql-lora=/adapters/yard1/llama-2-7b-sql-lora-test_0'
              - 'sql-lora-1=/adapters/yard1/llama-2-7b-sql-lora-test_1'
              - 'sql-lora-2=/adapters/yard1/llama-2-7b-sql-lora-test_2'
              - 'sql-lora-3=/adapters/yard1/llama-2-7b-sql-lora-test_3'
              - 'sql-lora-4=/adapters/yard1/llama-2-7b-sql-lora-test_4'
              - 'tweet-summary=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_0'
              - 'tweet-summary-1=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_1'
              - 'tweet-summary-2=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_2'
              - 'tweet-summary-3=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_3'
              - 'tweet-summary-4=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_4'
              - '--chat-template'
              - '/etc/vllm/llama-2-chat.jinja'
              env:
                - name: PORT
                  value: "8000"
              ports:
                - containerPort: 8000
                  name: http
                  protocol: TCP
              livenessProbe:
                failureThreshold: 2400
                httpGet:
                  path: /health
                  port: http
                  scheme: HTTP
                initialDelaySeconds: 5
                periodSeconds: 5
                successThreshold: 1
                timeoutSeconds: 1
              readinessProbe:
                failureThreshold: 6000
                httpGet:
                  path: /health
                  port: http
                  scheme: HTTP
                initialDelaySeconds: 5
                periodSeconds: 5
                successThreshold: 1
                timeoutSeconds: 1
              resources:
                limits:
                  nvidia.com/gpu: 1
                requests:
                  nvidia.com/gpu: 1
              volumeMounts:
                - mountPath: /data
                  name: data
                - mountPath: /dev/shm
                  name: shm
                - mountPath: /etc/vllm
                  name: chat-template
          restartPolicy: Always
          schedulerName: default-scheduler
          terminationGracePeriodSeconds: 30
          volumes:
            - name: data
              emptyDir: {}
            - name: shm
              emptyDir:
                medium: Memory
            - name: chat-template
              configMap:
                name: chat-template

    ACS クラスター

    展開して YAML コンテンツを表示する

    apiVersion: v1
    kind: Service
    metadata:
      name: vllm-llama2-7b-pool
    spec:
      selector:
        app: vllm-llama2-7b-pool
      ports:
      - protocol: TCP
        port: 8000
        targetPort: 8000
      type: ClusterIP
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: chat-template
    data:
      llama-2-chat.jinja: |
        # 会話の役割は、ユーザー/アシスタント/ユーザー/アシスタント/...と交互に繰り返される必要があります。
        {% if messages[0]['role'] == 'system' %}
          {% set system_message = '<<SYS>>\n' + messages[0]['content'] | trim + '\n<</SYS>>\n\n' %}
          {% set messages = messages[1:] %}
        {% else %}
            {% set system_message = '' %}
        {% endif %}
    
        {% for message in messages %}
            {% if (message['role'] == 'user') != (loop.index0 % 2 == 0) %}
                {{ raise_exception('Conversation roles must alternate user/assistant/user/assistant/...') }}
            {% endif %}
    
            {% if loop.index0 == 0 %}
                {% set content = system_message + message['content'] %}
            {% else %}
                {% set content = message['content'] %}
            {% endif %}
            {% if message['role'] == 'user' %}
                {{ bos_token + '[INST] ' + content | trim + ' [/INST]' }}
            {% elif message['role'] == 'assistant' %}
                {{ ' ' + content | trim + ' ' + eos_token }}
            {% endif %}
        {% endfor %}
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vllm-llama2-7b-pool
      namespace: default
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: vllm-llama2-7b-pool
      template:
        metadata:
          annotations:
            prometheus.io/path: /metrics
            prometheus.io/port: '8000'
            prometheus.io/scrape: 'true'
          labels:
            app: vllm-llama2-7b-pool
            alibabacloud.com/compute-class: gpu # GPU 計算能力を使用することを指定します。
            alibabacloud.com/compute-qos: default
            alibabacloud.com/gpu-model-series: "example-model" # GPU モデルを example-model として指定します。実際の状況に応じて入力してください。
        spec:
          containers:
            - name: lora
              image: "registry-cn-hangzhou-vpc.ack.aliyuncs.com/dev/llama2-with-lora:v0.2"
              imagePullPolicy: IfNotPresent
              command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
              args:
              - "--model"
              - "/model/llama2"
              - "--tensor-parallel-size"
              - "1"
              - "--port"
              - "8000"
              - '--gpu_memory_utilization'
              - '0.8'
              - "--enable-lora"
              - "--max-loras"
              - "10"
              - "--max-cpu-loras"
              - "12"
              - "--lora-modules"
              # LoRA モジュールを定義します。
              - 'sql-lora=/adapters/yard1/llama-2-7b-sql-lora-test_0'
              - 'sql-lora-1=/adapters/yard1/llama-2-7b-sql-lora-test_1'
              - 'sql-lora-2=/adapters/yard1/llama-2-7b-sql-lora-test_2'
              - 'sql-lora-3=/adapters/yard1/llama-2-7b-sql-lora-test_3'
              - 'sql-lora-4=/adapters/yard1/llama-2-7b-sql-lora-test_4'
              - 'tweet-summary=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_0'
              - 'tweet-summary-1=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_1'
              - 'tweet-summary-2=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_2'
              - 'tweet-summary-3=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_3'
              - 'tweet-summary-4=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_4'
              - '--chat-template'
              - '/etc/vllm/llama-2-chat.jinja'
              env:
                - name: PORT
                  value: "8000"
              ports:
                - containerPort: 8000
                  name: http
                  protocol: TCP
              livenessProbe:
                failureThreshold: 2400
                httpGet:
                  path: /health
                  port: http
                  scheme: HTTP
                initialDelaySeconds: 5
                periodSeconds: 5
                successThreshold: 1
                timeoutSeconds: 1
              readinessProbe:
                failureThreshold: 6000
                httpGet:
                  path: /health
                  port: http
                  scheme: HTTP
                initialDelaySeconds: 5
                periodSeconds: 5
                successThreshold: 1
                timeoutSeconds: 1
              resources:
                limits:
                  cpu: 16
                  memory: 64Gi
                  nvidia.com/gpu: 1
                requests:
                  cpu: 8
                  memory: 30Gi
                  nvidia.com/gpu: 1
              volumeMounts:
                - mountPath: /data
                  name: data
                - mountPath: /dev/shm
                  name: shm
                - mountPath: /etc/vllm
                  name: chat-template
          restartPolicy: Always
          schedulerName: default-scheduler
          terminationGracePeriodSeconds: 30
          volumes:
            - name: data
              emptyDir: {}
            - name: shm
              emptyDir:
                medium: Memory
            - name: chat-template
              configMap:
                name: chat-template
  2. データプレーンのクラスターの kubeconfig ファイルを使用して、LLM 推論サービスをデプロイします。

    kubectl apply -f vllm-service.yaml

ステップ 2: ASM ゲートウェイルールを構成する

ASM ゲートウェイでポート 8080 のリスニングを有効にするには、ゲートウェイルールをデプロイします。

  1. 次の内容で gateway.yaml という名前のファイルを作成します。

    apiVersion: networking.istio.io/v1
    kind: Gateway
    metadata:
      name: llm-inference-gateway
      namespace: default
    spec:
      selector:
        istio: ingressgateway
      servers:
        - hosts:
            - '*'
          port:
            name: http-service
            number: 8080
            protocol: HTTP
  2. ゲートウェイルールを作成します。

    kubectl apply -f gateway.yaml

ステップ 3: LLM 推論サービスのルーティングと負荷分散を構成する

  1. ASM kubeconfig を使用して、LLM 推論サービスのルーティングを有効にします。

    kubectl patch asmmeshconfig default --type=merge --patch='{"spec":{"gatewayAPIInferenceExtension":{"enabled":true}}}'
  2. InferencePool リソースをデプロイします。

    InferencePool リソースは、ラベルセレクターを介してクラスター内の一連の LLM 推論サービスワークロードを定義します。 ASM は、作成した InferencePool に基づいて、LLM 推論サービスの vLLM 負荷分散を有効にします。

    1. 以下に示すコンテンツを使用して inferencepool.yaml を作成します。

      apiVersion: inference.networking.x-k8s.io/v1alpha1
      kind: InferencePool
      metadata:
        name: vllm-llama2-7b-pool
      spec:
        targetPortNumber: 8000
        selector:
          app: vllm-llama2-7b-pool
    2. データプレーンクラスターの kubeconfig を使用して、InferencePool リソースを作成します。

      kubectl apply -f inferencepool.yaml
  3. InferenceModel リソースをデプロイします。

    InferenceModel は、InferencePool 内の特定のモデルのトラフィック分散ポリシーを指定します。

    1. 以下に示すコンテンツを使用して inferencemodel.yaml を作成します。

      apiVersion: inference.networking.x-k8s.io/v1alpha1
      kind: InferenceModel
      metadata:
        name: inferencemodel-sample
      spec:
        modelName: lora-request
        poolRef:
          group: inference.networking.x-k8s.io
          kind: InferencePool
          name: vllm-llama2-7b-pool
        targetModels:
        - name: tweet-summary
          weight: 10
        - name: tweet-summary-1
          weight: 10
        - name: tweet-summary-2
          weight: 10
        - name: tweet-summary-3
          weight: 10
        - name: tweet-summary-4
          weight: 10
        - name: sql-lora
          weight: 10
        - name: sql-lora-1
          weight: 10
        - name: sql-lora-2
          weight: 10
        - name: sql-lora-3
          weight: 10
        - name: sql-lora-4
          weight: 10

      この構成では、モデル名 lora-request のリクエストの 50% が tweet-summary LoRA モデルに転送され、残りの 50% が sql-lora LoRA モデルに転送されます。

    2. InferenceModel リソースを作成します。

      kubectl apply -f inferencemodel.yaml
  4. LLMRoute リソースを作成します。

    LLMRoute リソースを作成して、ゲートウェイのルーティングルールを設定します。これにより、ポート 8080 で受信されたすべてのリクエストが、InferencePool リソースを参照するサンプルの LLM 推論サービスに転送されます。

    1. 以下に示すコンテンツを使用して llmroute.yaml を作成します。

      apiVersion: istio.alibabacloud.com/v1
      kind: LLMRoute
      metadata:
        name: test-llm-route
      spec:
        gateways:
        - llm-inference-gateway
        host: test.com
        rules:
        - backendRefs:
          - backendRef:
              group: inference.networking.x-k8s.io
              kind: InferencePool
              name: vllm-llama2-7b-pool
    2. LLMRoute リソースを作成します。

      kubectl apply -f llmroute.yaml

ステップ 4: 実行結果を確認する

次のコマンドを複数回実行して、テストを開始します。

curl -H "host: test.com" ${ASM gateway IP}:8080/v1/completions -H 'Content-Type: application/json' -d '{
"model": "lora-request",
"prompt": "Write as if you were a critic: San Francisco",
"max_tokens": 100,
"temperature": 0
}' -v

次のような出力が表示されます。

{"id":"cmpl-2fc9a351-d866-422b-b561-874a30843a6b","object":"text_completion","created":1736933141,"model":"tweet-summary-1","choices":[{"index":0,"text":", I'm a newbie to this forum. Write a summary of the article.\nWrite a summary of the article.\nWrite a summary of the article. Write a summary of the article. Write a summary of the article. Write a summary of the article. Write a summary of the article. Write a summary of the article. Write a summary of the article. Write a summary of the article. Write a summary of the article. Write a summary","logprobs":null,"finish_reason":"length","stop_reason":null,"prompt_logprobs":null}],"usage":{"prompt_tokens":2,"total_tokens":102,"completion_tokens":100,"prompt_tokens_details":null}}

model フィールドは、どのモデルがサービスを提供しているかを示しています。複数回のリクエストの後、tweet-summary モデルと sql-lora モデルのリクエスト量比が約 1:1 であることがわかります。

(オプション) ステップ 5: LLM サービスの可観測性メトリックとダッシュボードを構成する

InferencePool および InferenceMode リソースを使用してクラスター内の LLM 推論サービスを宣言し、ルーティングポリシーを設定した後、ログとモニタリングメトリックを介して LLM 推論サービスの可観測性を表示できます。

  1. モニタリングメトリックを収集するには、ASM コンソールで LLM トラフィック可観測性機能を有効にします。

    1. 追加のログ フィールド、メトリック、およびメトリック ディメンションを組み込むことで、LLM 推論リクエストの可観測性を向上させます。詳細な構成手順については、「トラフィックの監視: ASM を使用して LLM トラフィックを効率的に管理する」をご参照ください。

    2. 構成が完了すると、model ディメンションが ASM モニタリングメトリックに組み込まれます。これらのメトリックは、可観測性モニタリングフレームワーク内で Prometheus を利用するか、サービスメッシュモニタリング用にセルフホスト型 Prometheus を統合することで収集できます。

    3. ASM は 2 つの新しいメトリックを導入します。asm_llm_proxy_prompt_tokens(入力トークンの数を表します)と asm_llm_proxy_completion_tokens(すべてのリクエストの出力トークンの数を表します)。これらのメトリックを組み込むには、Prometheus に次のルールを追加します。詳細については、「その他の Prometheus サービス検出構成」をご参照ください。

      scrape_configs:
      - job_name: asm-envoy-stats-llm
        scrape_interval: 30s
        scrape_timeout: 30s
        metrics_path: /stats/prometheus
        scheme: http
        kubernetes_sd_configs:
        - role: pod
        relabel_configs:
        - source_labels:
          - __meta_kubernetes_pod_container_port_name
          action: keep
          regex: .*-envoy-prom
        - source_labels:
          - __address__
          - __meta_kubernetes_pod_annotation_prometheus_io_port
          action: replace
          regex: ([^:]+)(?::\d+)?;(\d+)
          replacement: $1:15090
          target_label: __address__
        - action: labelmap
          regex: __meta_kubernetes_pod_label_(.+)
        - source_labels:
          - __meta_kubernetes_namespace
          action: replace
          target_label: namespace
        - source_labels:
          - __meta_kubernetes_pod_name
          action: replace
          target_label: pod_name
        metric_relabel_configs:
        - action: keep
          source_labels:
          - __name__
          regex: asm_llm_.*
  2. vLLM サービスのモニタリングメトリックを収集します。

    1. LLM 推論リクエストのモニタリングメトリックは、主に外部 LLM 推論リクエストのスループットに関係します。 vLLM サービスによって公開されているメトリックを収集し、その内部状態を監視するために、vLLM サービスポッドに Prometheus コレクターのアノテーションを追加します。

      ...
      annotations:
        prometheus.io/path: /metrics # メトリックが公開される HTTP パス
        prometheus.io/port: "8000" # メトリックが公開されるポート。vLLM サーバーのリスニングポートです。
        prometheus.io/scrape: "true" # 現在のポッドのメトリックをスクレイプするかどうか
      ...
    2. Prometheus のデフォルトのサービス検出メカニズムを使用して、vLLM サービスに関連するメトリックを取得します。 詳細については、「デフォルトのサービス検出」をご参照ください。

      vLLM サービスの主要なメトリックは、vLLM ワークロードの内部状態に関する洞察を提供します。

      メトリック名

      説明

      vllm:gpu_cache_usage_perc

      vLLM の GPU キャッシュ使用率。 vLLM が起動すると、KV キャッシュのためにできるだけ多くの GPU ビデオメモリを事前に占有します。 vLLM サーバーの場合、キャッシュ使用率が低いほど、GPU が新しいリクエストにリソースを割り当てるためのスペースが増えます。

      vllm:request_queue_time_seconds_sum

      待機状態キューで費やされた時間。 LLM 推論リクエストが vLLM サーバーに到着した後、すぐに処理されない場合があり、vLLM スケジューラがプリフィルとデコードをスケジュールするのを待つ必要があります。

      vllm:num_requests_running

      vllm:num_requests_waiting

      vllm:num_requests_swapped

      推論を実行中、待機中、およびメモリにスワップされたリクエストの数。 vLLM サービスの現在のリクエスト圧力を評価するために使用できます。

      vllm:avg_generation_throughput_toks_per_s

      vllm:avg_prompt_throughput_toks_per_s

      プリフィルステージで消費され、デコードステージで生成される 1 秒あたりのトークン数。

      vllm:time_to_first_token_seconds_bucket

      リクエストが vLLM サービスに送信されてから最初のトークンが応答されるまでのレイテンシレベル。 このメトリックは通常、クライアントがリクエストコンテンツを出力してから最初の応答を取得するまでの時間を表し、LLM ユーザーエクスペリエンスに影響を与える重要なメトリックです。

  3. LLM 推論サービスを監視するための Grafana ダッシュボードを構成します。

    Grafana ダッシュボードを介して vLLM でデプロイされた LLM 推論サービスを観測します。

    • ASM 監視メトリックを使用して、リクエストレートとトークンスループットを監視します。

    • vLLM 監視メトリックを使用して、LLM 推論サービスのワークロードの内部状態を評価します。

    Grafana コンソールでデータソース(Prometheus インスタンス)を作成できます。 ASM および vLLM の監視メトリックが Prometheus インスタンスによって収集されていることを確認してください。

    LLM 推論サービスの可観測性ダッシュボードを作成するには、以下に示すコンテンツを Grafana にインポートします。

    JSON コンテンツを表示するには展開します

    {
      "annotations": {
        "list": [
          {
            "builtIn": 1,
            "datasource": {
              "type": "grafana",
              "uid": "-- Grafana --"
            },
            "enable": true,
            "hide": true,
            "iconColor": "rgba(0, 211, 255, 1)",
            "name": "Annotations & Alerts", // アノテーションとアラート
            "target": {
              "limit": 100,
              "matchAny": false,
              "tags": [],
              "type": "dashboard"
            },
            "type": "dashboard"
          }
        ]
      },
      "description": "Monitoring vLLM Inference Server", // vLLM 推論サーバーの監視
      "editable": true,
      "fiscalYearStartMonth": 0,
      "graphTooltip": 0,
      "id": 49,
      "links": [],
      "liveNow": false,
      "panels": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${DS_PROMETHEUS}"
          },
          "description": "",
          "fieldConfig": {
            "defaults": {
              "color": {
                "mode": "palette-classic"
              },
              "custom": {
                "axisCenteredZero": false,
                "axisColorMode": "text",
                "axisLabel": "",
                "axisPlacement": "auto",
                "barAlignment": 0,
                "drawStyle": "line",
                "fillOpacity": 0,
                "gradientMode": "none",
                "hideFrom": {
                  "legend": false,
                  "tooltip": false,
                  "viz": false
                },
                "lineInterpolation": "linear", // 線形
                "lineWidth": 1,
                "pointSize": 5,
                "scaleDistribution": {
                  "type": "linear" // 線形
                },
                "showPoints": "auto",
                "spanNulls": false,
                "stacking": {
                  "group": "A",
                  "mode": "none"
                },
                "thresholdsStyle": {
                  "mode": "off"
                }
              },
              "mappings": [], // マッピング
              "thresholds": { // しきい値
                "mode": "absolute",
                "steps": [
                  {
                    "color": "green"
                  },
                  {
                    "color": "red",
                    "value": 80
                  }
                ]
              }
            },
            "overrides": [] // オーバーライド
          },
          "gridPos": {
            "h": 8,
            "w": 12,
            "x": 0,
            "y": 0
          },
          "id": 23,
          "options": {
            "legend": { // 凡例
              "calcs": [],
              "displayMode": "list", // リスト
              "placement": "bottom",
              "showLegend": true
            },
            "tooltip": {

    Copyright 2023

    image