# 機能設計書 83-spark-submit

## 概要

本ドキュメントは、Sparkアプリケーションのパッケージングとクラスタへのサブミットを行うコマンドラインツール spark-submit の機能設計を記述する。

### 本機能の処理概要

spark-submitは、Sparkアプリケーションを各種クラスタマネージャ（Standalone、YARN、Kubernetes、Local）に投入するための統一的なコマンドラインインターフェースである。アプリケーションの依存関係解決、クラスパス構成、デプロイモード（client/cluster）の切り替え、各クラスタマネージャ固有の設定をハンドリングする。

**業務上の目的・背景**：Sparkアプリケーションの実行には、クラスタマネージャやデプロイモードに応じた複雑な設定が必要である。spark-submitは、これらの差異を吸収する統一的なインターフェースを提供し、開発者がクラスタマネージャの詳細を意識することなくアプリケーションを投入できるようにする。ジョブのサブミット、キル、ステータス確認の操作を一元化する。

**機能の利用シーン**：バッチジョブの定期実行、開発環境でのローカルテスト実行、本番環境へのアプリケーションデプロイ、CI/CDパイプラインからの自動実行、既存ジョブの監視・キル操作。

**主要な処理内容**：
1. コマンドライン引数のパース：SparkSubmitArgumentsでオプションを解析
2. 環境準備：クラスパス、システムプロパティ、子プロセス引数の構築
3. クラスタマネージャ判定：masterオプションからYARN/Standalone/Kubernetes/Localを判定
4. デプロイモード処理：client/clusterモードに応じた実行方法の切り替え
5. アプリケーション起動：メインクラスの実行またはRESTクライアント経由の投入
6. ジョブ管理：実行中ジョブのキル、ステータス確認

**関連システム・外部連携**：YARN ResourceManager、Kubernetes API Server、Standalone Master、REST Submission Server、Hadoopファイルシステム

**権限による制御**：--proxy-userオプションでHadoopプロキシユーザーとしてジョブを実行可能。Kerberos認証環境ではUserGroupInformationを使用した認証委譲を行う。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はCLIツールであり直接関連する画面はない |

## 機能種別

デプロイ・実行制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --master | String | No | クラスタマネージャURL（yarn, spark://, k8s://, local[*]） | yarn/spark/k8s/localのいずれか |
| --deploy-mode | String | No | デプロイモード（client/cluster）。デフォルトclient | client/clusterのいずれか |
| --class | String | Yes* | メインクラス名（*Pythonスクリプトの場合は不要） | - |
| --jars | String | No | 追加JARファイルのカンマ区切りリスト | - |
| --files | String | No | ワーキングディレクトリに配置するファイル | - |
| --conf | String | No | Spark設定（key=value形式） | - |
| --proxy-user | String | No | プロキシユーザー名 | - |
| --driver-memory | String | No | ドライバメモリ量 | - |
| --executor-memory | String | No | エグゼキュータメモリ量 | - |
| --num-executors | Int | No | エグゼキュータ数 | - |
| application-jar | String | Yes | アプリケーションJAR/Pythonスクリプトパス | - |

### 入力データソース

コマンドライン引数、環境変数（SPARK_HOME等）、spark-defaults.conf設定ファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| アプリケーション実行 | Process | 起動されたSparkアプリケーションプロセス |
| ジョブステータス | REST Response | ジョブの状態情報（REST API経由） |
| キル結果 | Boolean | ジョブキルの成功/失敗 |

### 出力先

標準出力（ログ・ステータス表示）、クラスタマネージャ（アプリケーション投入）

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数パース
   └─ SparkSubmitArguments でオプション・設定を解析
2. ロギング初期化
   └─ シェル/SQLシェルの場合は構造化ログを無効化
3. アクション判定
   └─ SUBMIT / KILL / REQUEST_STATUS / PRINT_VERSION
4. 環境準備（prepareSubmitEnvironment）
   └─ クラスタマネージャ判定（YARN/STANDALONE/KUBERNETES/LOCAL）
   └─ デプロイモード判定（CLIENT/CLUSTER）
   └─ 子プロセスのクラスパス・メインクラス・引数・システムプロパティ構築
5. プロキシユーザー処理
   └─ --proxy-user指定時はdoAs()でラップ
6. メインクラス実行（runMain）
   └─ クラスローダー設定、メインクラスのリフレクション呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[spark-submit実行] --> B[引数パース]
    B --> C{アクション判定}
    C -->|SUBMIT| D[prepareSubmitEnvironment]
    C -->|KILL| E[REST/RPCでキル]
    C -->|STATUS| F[REST/RPCでステータス取得]
    C -->|VERSION| G[バージョン表示]
    D --> H{Standalone Cluster + REST?}
    H -->|Yes| I[REST送信試行]
    H -->|No| J[runMain]
    I -->|失敗| K[レガシーゲートウェイへフォールバック]
    K --> J
    I -->|成功| L[完了]
    J --> M{proxy-user?}
    M -->|Yes| N[doAs実行]
    M -->|No| O[直接実行]
    N --> P[メインクラス起動]
    O --> P
    P --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-83-01 | クラスタマネージャ判定 | masterオプションの値でYARN/STANDALONE/KUBERNETES/LOCALを判定する | prepareSubmitEnvironment内 |
| BR-83-02 | RESTフォールバック | Standalone clusterモードでREST送信に失敗した場合、レガシーゲートウェイにフォールバックする | Standalone clusterモード時 |
| BR-83-03 | Python/R非サポート | Standalone clusterモードではPython/Rアプリケーションはサポートしない | STANDALONE + CLUSTER時 |
| BR-83-04 | Kubernetes proxyユーザー | K8sクライアントモード＋spark.kubernetes.submitInDriver時はSparkHadoopUtilでプロキシ実行 | K8s submitInDriver時 |

### 計算ロジック

特になし。

## データベース操作仕様

### 操作別データベース影響一覧

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 引数エラー | masterがyarn/spark/k8s/localのいずれでもない場合 | 正しいmaster URLを指定 |
| - | デプロイモードエラー | deploy-modeがclient/cluster以外の場合 | client/clusterを指定 |
| SubmitRestConnectionException | REST通信エラー | RESTサーバーへの接続に失敗した場合 | レガシーゲートウェイへフォールバック |
| - | クラスロードエラー | YARN/K8sクラスがロードできない場合 | 対応ビルドを使用 |

### リトライ仕様

RESTベースのサブミッションが失敗した場合、レガシーRPCゲートウェイに自動フォールバックする（Standalone clusterモードのみ）。

## トランザクション仕様

該当なし。

## パフォーマンス要件

- アプリケーション起動時間は最小限に抑える
- 依存関係の解決はMavenリポジトリから自動ダウンロード可能

## セキュリティ考慮事項

- --proxy-userオプションでHadoopプロキシユーザー認証を実施
- Kerberos環境ではUserGroupInformation経由の認証委譲をサポート
- パスワード等の機密設定はログ出力時にマスクされる

## 備考

spark-submitはSparkの最も基本的なデプロイツールである。Spark Connect経由のリモート接続（--remote / sc://）もサポートする。

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

コマンドライン引数のデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SparkSubmitArguments.scala | `core/src/main/scala/org/apache/spark/deploy/SparkSubmitArguments.scala` | コマンドラインオプションのパース、master/deployMode/mainClass等のフィールド定義 |
| 1-2 | SparkSubmitAction (enum) | `core/src/main/scala/org/apache/spark/deploy/SparkSubmit.scala` | **52-55行目**: SUBMIT/KILL/REQUEST_STATUS/PRINT_VERSIONの列挙型 |

**読解のコツ**: SparkSubmitArgumentsはSparkSubmitOptionParserを継承しており、コマンドラインオプションの解析はJava側のライブラリで行われる。

#### Step 2: エントリーポイントを理解する

メインの処理フローを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SparkSubmit.scala | `core/src/main/scala/org/apache/spark/deploy/SparkSubmit.scala` | **70-99行目**: doSubmit()メソッド - 引数パース、アクション分岐 |

**主要処理フロー**:
1. **70行目**: doSubmit()がエントリーポイント
2. **71行目**: parseArguments()で引数パース
3. **94-99行目**: action match で SUBMIT/KILL/REQUEST_STATUS/PRINT_VERSION に分岐

#### Step 3: 環境準備処理を理解する

クラスタマネージャに応じた環境構築の流れを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SparkSubmit.scala | `core/src/main/scala/org/apache/spark/deploy/SparkSubmit.scala` | **243-299行目**: prepareSubmitEnvironment() - クラスタマネージャ判定、デプロイモード判定 |

**主要処理フロー**:
- **254-267行目**: masterオプションからclusterManager (YARN/STANDALONE/KUBERNETES/LOCAL) を判定
- **270-276行目**: deployMode (CLIENT/CLUSTER) を判定
- **278-295行目**: YARN/K8sクラスのロード可能性チェック

#### Step 4: サブミット実行を理解する

実際のジョブ投入処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SparkSubmit.scala | `core/src/main/scala/org/apache/spark/deploy/SparkSubmit.scala` | **166-228行目**: submit()メソッド - RESTフォールバック、proxyユーザー処理 |

### プログラム呼び出し階層図

```
SparkSubmit.main(args)
    |
    +-- doSubmit(args)
            |
            +-- parseArguments(args) -> SparkSubmitArguments
            |
            +-- submit(args, uninitLog, sparkConf)
            |       |
            |       +-- doRunMain()
            |       |       +-- UserGroupInformation.doAs() [proxy-user時]
            |       |       +-- runMain(args, uninitLog)
            |       |               +-- prepareSubmitEnvironment(args)
            |       |               +-- Class.forName(childMainClass)
            |       |               +-- mainMethod.invoke()
            |       |
            |       +-- [REST fallback for Standalone cluster]
            |
            +-- kill(args, sparkConf)
            |       +-- RestSubmissionClient.killSubmission()
            |
            +-- requestStatus(args, sparkConf)
                    +-- RestSubmissionClient.requestSubmissionStatus()
```

### データフロー図

```
[入力]                      [処理]                        [出力]

CLIオプション ──────▶ SparkSubmitArguments ──▶ prepareSubmitEnvironment()
                                                        |
                                              childArgs / childClasspath /
                                              sparkConf / childMainClass
                                                        |
                                                        v
                                              runMain() -> アプリケーション起動
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SparkSubmit.scala | `core/src/main/scala/org/apache/spark/deploy/SparkSubmit.scala` | ソース | メインのサブミットロジック |
| SparkSubmitArguments.scala | `core/src/main/scala/org/apache/spark/deploy/SparkSubmitArguments.scala` | ソース | コマンドライン引数パーサー |
| SparkApplication.scala | `core/src/main/scala/org/apache/spark/deploy/SparkApplication.scala` | ソース | アプリケーション基底クラス |
| Client.scala | `core/src/main/scala/org/apache/spark/deploy/Client.scala` | ソース | Standaloneクライアント |
| RestSubmissionClient.scala | `core/src/main/scala/org/apache/spark/deploy/rest/RestSubmissionClient.scala` | ソース | REST送信クライアント |
| DependencyUtils.scala | `core/src/main/scala/org/apache/spark/deploy/DependencyUtils.scala` | ソース | 依存関係解決ユーティリティ |
