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

Elastic Container Instance:DeepSeek-R1 シリーズモデルをデプロイし、モデル内のポッドのスケーリングを実装する

最終更新日:Mar 22, 2025

このトピックでは、DataCache を使用して DeepSeek-R1 シリーズモデルを Elastic Container Instance にデプロイする方法について説明します。また、カスタムメトリックに基づいてポッドのスケーリングを実装するために Horizontal Pod Autoscaler (HPA) を構成する方法についても説明します。この例では、DeepSeek-R1-Distill-Qwen-7B を使用します。

DeepSeek のデプロイに Elastic Container Instance を使用する理由

  • Elastic Container Instance は O&M が不要で、柔軟にデプロイでき、弾力性があり費用対効果の高いビジネスの構築に役立ちます。詳細については、「利点」をご参照ください。

  • Elastic Container Instance は DataCacheImageCache を使用して、イメージのプルとモデルのダウンロードにかかる時間を節約し、ネットワークリソースの消費を削減し、システム効率を向上させます。

    説明

    コンテナ化された大規模モデル推論サービスのデプロイには、コンテナの作成と起動、イメージのプル、モデルファイルのダウンロード、モデルのロードと起動という段階が含まれます。大規模モデル推論サービスのイメージとモデルはサイズが大きいため、イメージとモデルのプルには長時間の時間と大量のネットワークトラフィックが必要です。たとえば、vLLM イメージのサイズは約 16.5 GB で、DeepSeek-R1-Distill-Qwen-7B モデルのサイズは約 14 GB です。Elastic Container Instance は、DataCache と ImageCache を使用して、イメージのプルとモデルのダウンロードにかかる時間を節約します。

前提条件

  • DataCache カスタムリソース定義 (CRD) がクラスターにデプロイされています。詳細については、「DataCache CRD のデプロイ」をご参照ください。

  • クラスターが存在する仮想プライベートクラウド (VPC) がインターネット NAT ゲートウェイに関連付けられています。VPC 内のリソースまたは VPC 内の vSwitch に接続されているリソースがインターネットにアクセスできるように、インターネット NAT ゲートウェイ用に SNAT エントリが構成されています。

    説明

    VPC がインターネット NAT ゲートウェイに関連付けられていない場合は、DataCache を作成してアプリケーションをデプロイするときに、VPC に Elastic IP アドレス (EIP) を関連付ける必要があります。このようにして、インターネットからデータをプルできます。

  • ARMS Prometheus コンポーネント (ack-arms-prometheus) がクラスターにインストールされています。詳細については、「Managed Service for Prometheus の使用」をご参照ください。

  • ack-alibaba-cloud-metrics-adapter コンポーネントがクラスターにデプロイされています。

    ack-Alibaba-cloud-metrics-adapter をデプロイするには、Container Service for Kubernetes (ACK) コンソールにログインします。左側のナビゲーションウィンドウで、[マーケットプレイス] > [マーケットプレイス] を選択します。マーケットプレイスページで、ack-alibaba-cloud-metrics-adapter を見つけてデプロイします。

  • KServe がクラスターにデプロイされています。

    KServe は Kubernetes ベースの機械学習モデルサービスフレームワークです。KServe を使用すると、Kubernetes CRD を使用して、トレーニング済みの 1 つ以上のモデルをモデルサービスランタイムにデプロイできます。詳細については、「ack-kserve のインストール」をご参照ください。

ランタイム環境を準備する

DeepSeek モデルごとに、ランタイム環境の要件が異なります。このトピックでは、DeepSeek-R1-Distill-Qwen-7B モデルを使用します。

  • 推奨仕様

    Elastic Container Instance ベースのポッドの作成に使用する GPU アクセラレーション Elastic Compute Service (ECS) インスタンスファミリは、次の条件を満たしている必要があります。ポッドの作成に使用できる GPU アクセラレーション ECS インスタンスファミリの詳細については、「サポートされているインスタンスファミリ」をご参照ください。

    • CPU: 厳密な制限なし

    • メモリサイズ: 16 GiB 以上

    • GPU の数: 1 以上

    • GPU メモリのサイズ: 20 GB 以上。たとえば、A10 GPU は要件を満たしています。GPU メモリサイズが 20 GB 未満の場合、メモリ不足 (OOM) エラーが発生する可能性があります。

  • ソフトウェア要件

    大規模モデルのデプロイは、多数のライブラリと構成に依存します。vLLM は主流の大規模モデル推論エンジンであり、このトピックでは推論サービスのデプロイに使用されます。Elastic Container Instance はパブリックコンテナイメージを提供します。パブリックコンテナイメージを直接使用するか、パブリックコンテナイメージに基づいて二次開発を行うことができます。イメージアドレスは registry.cn-hangzhou.aliyuncs.com/eci_open/vllm-openai:v0.7.2 です。イメージサイズは約 16.5 GB です。

ステップ 1: DataCache を作成する

DeepSeek を初めてデプロイするときは、モデルデータをプルする必要がないように、事前に DataCache を作成する必要があります。これにより、DeepSeek のデプロイが高速化されます。

  1. Hugging Face にアクセスして、モデルの ID を取得します。

    このトピックでは、DeepSeek-R1-Distill-Qwen-7B のメインバージョンを使用します。Hugging Face でモデルを見つけ、モデル詳細ページの上部にあるモデルの ID をコピーします。

  2. DataCache の YAML 構成ファイルを記述します。次に、YAML ファイルを使用して DataCache を作成し、DeepSeek-R1-Distill-Qwen-7B モデルデータをプルして DataCache に保存します。

    kubectl create -f datacache-test.yaml

    datacache-test.yaml という名前の DataCache YAML 構成ファイルの例。

    apiVersion: eci.aliyun.com/v1alpha1
    kind: DataCache
    metadata:
      name: deepseek-r1-distill-qwen-7b
    spec:
      bucket: test
      path: /model/deepseek-r1-distill-qwen-7b
      dataSource:
        type: URL
        options:
          repoSource: HuggingFace/Model                          # データソースが Hugging Face であるモデルを指定します。
          repoId: deepseek-ai/DeepSeek-R1-Distill-Qwen-7B        # モデルの ID を指定します。
          revision: main                                         # モデルのバージョンを指定します。
      netConfig:
        securityGroupId: sg-bp1***********
        vSwitchId: vsw-bp1uo************                 # SNAT エントリが構成されている vSwitch を指定します。
        # モデルのインターネットアクセスを有効にするために vSwitch に SNAT エントリが構成されていない場合は、Elastic IP アドレス (EIP) を作成して vSwitch に関連付ける必要があります。
        eipCreateParam:                                  
          bandwidth: 5                                   # EIP 帯域幅
  3. DataCache のステータスをクエリします。

    kubectl get edc

    モデルデータがダウンロードされ、DataCache のステータスが Available になると、DataCache を使用できるようになります。Alibaba Cloud は DeepSeek-R1 シリーズモデルのホットロード機能を提供しており、これにより DataCache が数秒で作成されます。

    NAME                          AGE   DATACACHEID                STATUS      PROGRESS   BUCKET    PATH
    deepseek-r1-distill-qwen-7b   40s   edc-uf6btsb4q5j4b9ue****   Available   100%       test      /model/deepseek-r1-distill-qwen-7b

ステップ 2: ack-alibaba-cloud-metrics-adapter のルールを構成する

カスタムメトリックベースの自動スケーリングは、ack-alibaba-cloud-metrics-adapter コンポーネントと ACK が提供する Kubernetes HPA メカニズムに基づいて実装されます。次の表に、HPA でサポートされている GPU メトリックを示します。詳細については、「GPU メトリックに基づく自動スケーリングの有効化」をご参照ください。

メトリック

説明

単位

DCGM_FI_DEV_GPU_UTIL

GPU カードの使用率。このメトリックは、排他モードでスケジュールされている GPU でのみ使用できます。

%

DCGM_FI_DEV_FB_USED

GPU カードの使用済みメモリ。このメトリックは、排他モードでスケジュールされている GPU でのみ使用できます。

MiB

DCGM_CUSTOM_PROCESS_SM_UTIL

ポッドの GPU 使用率。

%

DCGM_CUSTOM_PROCESS_MEM_USED

ポッドに割り当てられている GPU メモリの使用量。

MiB

  1. ACK コンソール にログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。[クラスター] ページで、クラスターの名前をクリックします。

  2. クラスター管理ページの左側のナビゲーションウィンドウで、[アプリケーション] > [helm] を選択します。

  3. [Helm] ページで、ack-alibaba-cloud-metrics-adapter の [アクション] 列の [更新] をクリックします。

    custom フィールドに次の rules を追加します。

    サンプルコードを表示

    - metricsQuery: avg(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
      resources:
        overrides:
          NodeName:
            resource: node
      seriesQuery: DCGM_FI_DEV_GPU_UTIL{} # このメトリックは GPU 使用率を示します。
    - metricsQuery: avg(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
      resources:
        overrides:
          NamespaceName:
            resource: namespace
          NodeName:
            resource: node
          PodName:
            resource: pod
      seriesQuery: DCGM_CUSTOM_PROCESS_SM_UTIL{} # このメトリックはポッドの GPU 使用率を示します。
    - metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
      resources:
        overrides:
          NodeName:
            resource: node
      seriesQuery: DCGM_FI_DEV_FB_USED{} # このメトリックは使用されている GPU メモリの量を示します。
    - metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
      resources:
        overrides:
          NamespaceName:
            resource: namespace
          NodeName:
            resource: node
          PodName:
            resource: pod
      seriesQuery: DCGM_CUSTOM_PROCESS_MEM_USED{} # このメトリックはポッドの GPU メモリ使用量を示します。
    - metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>) / sum(DCGM_CUSTOM_CONTAINER_MEM_ALLOCATED{}) by (<<.GroupBy>>)
      name:
        as: ${1}_GPU_MEM_USED_RATIO
        matches: ^(.*)_MEM_USED
      resources:
        overrides:
          NamespaceName:
            resource: namespace
          PodName:
            resource: pod
      seriesQuery: DCGM_CUSTOM_PROCESS_MEM_USED{NamespaceName!="",PodName!=""}  # このメトリックは GPU メモリ使用率を示します。

ステップ 3: スケーラブルな DeepSeek モデル推論サービスをデプロイする

  1. DeepSeek アプリケーションの YAML 構成ファイルを記述し、YAML ファイルに基づいてアプリケーションをデプロイします。

    kubectl create -f deepseek-r1-7b-kserve.yaml

    次のサンプルコードは、deepseek-r1-7b-kserve.yaml ファイルの内容を示しています。ファイルの説明:

    • ポッドは GPU アクセラレーション ECS インスタンスタイプに基づいており、DeepSeek-R1-Distill-Qwen-7B モデルがマウントされています。

    • InferenceService のプレディクターは、vLLM を含むイメージを使用します。コンテナが起動されると、コンテナは vllm serve /deepseek-r1-7b --tensor-parallel-size 1 --max-model-len 24384 --enforce-eager を実行して OpenAI-Compatible Server を起動します。

    • スケーリングは、ポッドの GPU 使用率を示す DCGM_CUSTOM_PROCESS_SM_UTIL メトリックに基づいて予測されます。平均 GPU 使用率が 50% に達すると、HPA は自動的にポッドをスケールアウトします。ポッドの合計最大数は、maxReplicas の値を超えることはできません。

    apiVersion: serving.kserve.io/v1beta1
    kind: InferenceService
    metadata:
      name: deepseek-r1-7b-kserve
      labels:
        alibabacloud.com/eci: "true"
      annotations:
        serving.kserve.io/autoscalerClass: external
        k8s.aliyun.com/eci-use-specs: ecs.gn7i-c16g1.4xlarge,ecs.gn7i-c32g1.8xlarge  # GPU アクセラレーション ECS インスタンスタイプを指定します。ポッドの作成成功率を高めるために、複数の ECS インスタンスタイプを指定できます。
        k8s.aliyun.com/eci-extra-ephemeral-storage: "20Gi"   # ポッドの起動は大きなフレームワークに依存するため、追加の一時記憶領域を指定します。追加の一時記憶領域に対して課金されます。
        k8s.aliyun.com/eci-data-cache-bucket: "test"      # DataCache を格納するバケットを指定します。
        # より高速なロード速度が必要な場合は、AutoPL ディスクを使用できます。
        k8s.aliyun.com/eci-data-cache-provisionedIops: "15000"   # 拡張 SSD (ESSD) AutoPL ディスクにプロビジョニングされる IOPS を指定します。
        k8s.aliyun.com/eci-data-cache-burstingEnabled: "true"    # アプリケーションの起動を高速化するために、ESSD AutoPL ディスクのパフォーマンスバースト機能を有効にします。
    spec:
      predictor:
        containers:
          - name: vllm
            command:
              - /bin/sh
            args:
              - -c
              - vllm serve /deepseek-r1-7b --port 8080 --tensor-parallel-size 1 --max-model-len 24384 --enforce-eager
            image: registry-vpc.cn-hangzhou.aliyuncs.com/eci_open/vllm-openai:v0.7.2
            resources:
              limits:
                cpu: "16"
                memory: "60Gi"
                nvidia.com/gpu: "1"
              requests:
                cpu: "16"
                memory: "60Gi"
                nvidia.com/gpu: "1"
            volumeMounts:
              - mountPath: /deepseek-r1-7b # モデルのパスを指定します。
                name: llm-model
        volumes:
          - name: llm-model
            hostPath:
              path: /model/deepseek-r1-distill-qwen-7b  # DataCache のマウントパスを指定します。
    ---
    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: deepseek-r1-7b-kserve-predictor
      namespace: default
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: deepseek-r1-7b-kserve-predictor
      metrics:
        - pods:
            metric:
              name: DCGM_CUSTOM_PROCESS_SM_UTIL       # 監視するメトリックの名前を指定します。
            target:
              type: Utilization                      # ターゲット値のタイプ (使用率または生の値など) を定義します。
              averageValue: '50'                     # メトリックのターゲット平均値を設定します。
          type: Pods
      minReplicas: 1                                # Running 状態のポッドの最小数を指定します。
      maxReplicas: 100                              # ポッドの最大許容数を指定します。

    予期される出力:

    inferenceservice.serving.kserve.io/deepseek-r1-7b-kserve created
    horizontalpodautoscaler.autoscaling/deepseek-r1-7b-kserve-predictor created
  2. アプリケーションがデプロイされているかどうかを確認します。

    kubectl get pods --selector=app=isvc.deepseek-r1-7b-kserve-predictor

    予期される出力:

    NAME                                               READY   STATUS    RESTARTS   AGE
    deepseek-r1-7b-kserve-predictor-6785df7b7f-r7kjx   1/1     Running   0          116s

ステップ 4: モデルの推論効果をテストする

  1. DeepSeek 推論アプリケーションで使用される Server Load Balancer (SLB) インスタンスの IP アドレスとホスト名を取得し、IP アドレスとホスト名を変数として設定します。

    NGINX_INGRESS_IP=$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}')
    SERVICE_HOSTNAME=$(kubectl get inferenceservice deepseek-r1-7b-kserve -o jsonpath='{.status.url}' | cut -d "/" -f 3)
  2. DeepSeek モデル推論サービスをテストします。

    DeepSeek モデル推論サービスにリクエストを送信します。例:

    curl POST http://$NGINX_INGRESS_IP:80/v1/chat/completions \
         -H "Host: $SERVICE_HOSTNAME" \
         -H "Content-Type: application/json" \
         -d '{
               "model": "/deepseek-r1-7b",
               "messages": [
                   {
                       "role": "user",
                       "content": "Briefly describe containers in one sentence"
                   }
               ],
               "temperature": 0.6,
               "max_tokens": 3000
             }' \
         --verbose

    予期される出力:

    {"id":"chatcmpl-56e6ff393d999571ce6ead1b72f9302d","object":"chat.completion","created":1739340308,"model":"/deepseek-r1-7b","choices":[{"index":0,"message":{"role":"assistant","reasoning_content":null,"content":"<think>\n 1 文でコンテナについて簡単に説明する必要があります。コンテナとは何ですか? プログラミング、特に Docker では、コンテナはアプリケーションを独立して実行できる隔離された環境のようです。コンテナ化により、開発とデプロイが容易になりますよね? したがって、コンテナは、アプリケーションを依存関係から分離できる軽量のランタイムであり、開発とデプロイのプロセスをより効率的にする必要があります。そうですか? したがって、コンテナの 1 文の紹介では、コンテナの分離、軽量、独立動作の機能について説明する必要があります。クラウドネイティブサービスやマイクロサービスアーキテクチャなどのコンテナ化テクノロジーのアプリケーションシナリオについても言及される場合があります。さて、これらのアイデアを 1 つの文にまとめる必要があります。\n</think>\n\nコンテナは、アプリケーションを独立して実行できる隔離されたランタイム環境であり、軽量で効率的なリソース管理を提供し、クラウドネイティブサービスとマイクロサービスアーキテクチャをサポートします。","tool_calls":[]},"logprobs":null,"finish_reason":"stop","stop_reason":null}],"usage":{"prompt_tokens":8,"total_tokens":168,"completion_tokens":160,"prompt_tokens_details":null},"prompt_logprobs":null}

    <think></think> 内のコンテンツは、モデルが最終的な回答を生成する前の思考プロセスまたは推論ステップを表します。これらのマーカーは最終出力の一部ではなく、モデルが回答を生成する前の自己プロンプトまたは論理推論の記録です。

    抽出された最終回答:

    コンテナは、アプリケーションを独立して実行できる隔離されたランタイム環境であり、軽量で効率的なリソース管理を提供し、クラウドネイティブサービスとマイクロサービスアーキテクチャをサポートします。

  3. メトリック値がスケーリングしきい値を超えたときに HPA がポッドをスケールアウトするかどうかをテストします。

    1. 次のコマンドを実行して、クラスター内のポッドの数をクエリします。

      kubectl get pods --selector=app=isvc.deepseek-r1-7b-kserve-predictor

      次の出力は、クラスターに 1 つのポッドが含まれていることを示しています。

      NAME                                               READY   STATUS    RESTARTS   AGE
      deepseek-r1-7b-kserve-predictor-6785df7b7f-r7kjx   1/1     Running   0          6m54s
    2. 次のコマンドを実行して、HPA のステータスをクエリします。

      kubectl get hpa

      予期される出力:

      NAME                              REFERENCE                                    TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
      deepseek-r1-7b-kserve-predictor   Deployment/deepseek-r1-7b-kserve-predictor   9/50       1         100       1          8m
    3. hey を使用してストレステストを実行します。

      hey の詳細については、「hey」をご参照ください。

      hey -z 2m -c 20 -m POST -host $SERVICE_HOSTNAME -H "Content-Type: application/json" -d '{"model": "/deepseek-r1-7b", "messages": [{"role": "user", "content": "hello world!"}], "max_tokens": 512, "temperature": 0.7, "top_p": 0.9, "seed": 10}' http://$NGINX_INGRESS_IP:80/v1/chat/completions
    4. クラスター内のポッドの数をクエリして、HPA がポッドをスケールアウトしたかどうかを確認します。

      kubectl get pods --selector=app=isvc.deepseek-r1-7b-kserve-predictor

      次の出力は、HPA がポッドをスケールアウトしたことを示しています。

      NAME                                               READY   STATUS    RESTARTS   AGE
      deepseek-r1-7b-kserve-predictor-6785df7b7f-r7kjx   1/1     Running   0          8m5s
      deepseek-r1-7b-kserve-predictor-6785df7b7f-6l2kj   1/1     Running   0          104s
      deepseek-r1-7b-kserve-predictor-6785df7b7f-3q5dz   1/1     Running   0          104s
    5. 次のコマンドを実行して、HPA のステータスをクエリします。

      kubecl get hpa

      予期される出力:

      NAME                              REFERENCE                                    TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
      deepseek-r1-7b-kserve-predictor   Deployment/deepseek-r1-7b-kserve-predictor   5/50       1         100       3          10m