# インフラ設計書

## 概要

本ドキュメントは、Apache Spark 4.2.0-SNAPSHOT のインフラストラクチャ設計を記載する。Apache Spark は分散データ処理フレームワークであり、Standalone、YARN、Kubernetes の3つのクラスタマネージャ上でデプロイ可能なアーキテクチャを持つ。本書では、各デプロイモードにおけるサーバー構成、ネットワーク構成、ストレージ構成、外部サービス連携、およびスケーリング設計を網羅的に記述する。

## システム構成

### 全体構成

Apache Spark は Master-Worker 型の分散処理アーキテクチャを採用する。アプリケーションの実行は以下のコンポーネントで構成される。

1. **Driver プロセス**: SparkContext を保持し、ジョブのスケジューリングとタスク分配を担当
2. **Executor プロセス**: Worker ノード上で動作し、タスクの実行とデータの保持を担当
3. **Cluster Manager**: リソース管理を担当（Standalone Master / YARN ResourceManager / Kubernetes API Server）
4. **History Server**: 完了したアプリケーションのイベントログを提供
5. **Spark Connect Server**: gRPC ベースのリモート接続サーバー（オプション）
6. **Thrift Server**: JDBC/ODBC 接続を提供するサーバー（オプション）

デプロイモードは以下の3種類をサポートする。

| デプロイモード | クラスタマネージャ | 特徴 |
| --- | --- | --- |
| Standalone | Spark Master | Spark 独自のクラスタ管理。セットアップが簡易 |
| YARN | Hadoop YARN ResourceManager | Hadoop エコシステムとの統合。既存 Hadoop クラスタ上で動作 |
| Kubernetes | Kubernetes API Server | コンテナベースのデプロイ。Pod として Driver/Executor を管理 |

### サーバー構成

#### Standalone モード

| サーバー種別 | 役割 | スペック（デフォルト設定） | 台数 |
| --- | --- | --- | --- |
| Master ノード | クラスタ管理、リソース割り当て | メモリ: 1G（SPARK_DAEMON_MEMORY）、ポート: 7077（SPARK_MASTER_PORT）、Web UI: 8080（SPARK_MASTER_WEBUI_PORT） | 1台（HA構成で複数台可） |
| Worker ノード | Executor プロセスの実行基盤 | コア数: SPARK_WORKER_CORES、メモリ: SPARK_WORKER_MEMORY、ポート: SPARK_WORKER_PORT、Web UI: SPARK_WORKER_WEBUI_PORT | 可変（workers.template で定義） |
| History Server | 完了アプリケーションのログ表示 | メモリ: 1G（SPARK_DAEMON_MEMORY）、Web UI: 18080 | 1台 |
| Spark Connect Server | gRPC リモート接続提供 | ポート: 15002（DEFAULT_SPARK_CONNECT_SERVER_PORT） | 1台（オプション） |

#### Kubernetes モード

| サーバー種別 | 役割 | スペック（デフォルト設定） | 台数 |
| --- | --- | --- | --- |
| Driver Pod | SparkContext の実行、タスクスケジューリング | メモリ: 1G（spark.driver.memory） + オーバーヘッド、CPU: spark.driver.cores、ポート: 7078（DEFAULT_DRIVER_PORT） | 1 Pod/アプリケーション |
| Executor Pod | タスク実行、データキャッシュ | メモリ: 1G（spark.executor.memory） + オーバーヘッド、CPU: 1コア（SPARK_EXECUTOR_CORES）、ポート: 7079（DEFAULT_BLOCKMANAGER_PORT） | 動的（Dynamic Allocation 対応） |
| Kubernetes API Server | Pod のスケジューリング、リソース管理 | クラスタ依存 | クラスタ依存 |

#### YARN モード

| サーバー種別 | 役割 | スペック | 台数 |
| --- | --- | --- | --- |
| ResourceManager | YARN リソース管理 | Hadoop クラスタ依存 | 1台（HA構成で2台） |
| NodeManager | コンテナ実行基盤 | Hadoop クラスタ依存 | 可変 |
| Driver（Client/Cluster） | SparkContext の実行 | spark.driver.memory（デフォルト 1G） | 1プロセス/アプリケーション |
| Executor | タスク実行 | spark.executor.memory（デフォルト 1G） | 動的 |

### ネットワーク構成

#### ポート一覧

| ポート | 用途 | プロトコル | 設定パラメータ |
| --- | --- | --- | --- |
| 7077 | Spark Master RPC | TCP | SPARK_MASTER_PORT |
| 7078 | Driver RPC（K8s） | TCP | DEFAULT_DRIVER_PORT |
| 7079 | Block Manager（K8s） | TCP | DEFAULT_BLOCKMANAGER_PORT |
| 8080 | Master Web UI | HTTP | SPARK_MASTER_WEBUI_PORT |
| 8081 | Worker Web UI | HTTP | SPARK_WORKER_WEBUI_PORT |
| 4040 | Spark Application UI | HTTP | spark.ui.port |
| 15002 | Spark Connect Server | gRPC | DEFAULT_SPARK_CONNECT_SERVER_PORT |
| 18080 | History Server Web UI | HTTP | spark.history.ui.port |

#### Kubernetes ネットワーク

- **Driver Service**: Kubernetes Service としてドライバーの接続先を公開
  - IP Family Policy: SingleStack（デフォルト）、PreferDualStack、RequireDualStack から選択可能
  - IP Families: IPv4（デフォルト）、IPv6、IPv4/IPv6 デュアルスタック対応
  - サービス終了時に自動削除（spark.kubernetes.driver.service.deleteOnTermination=true）
- **Executor-Driver 通信**: Executor は Driver Pod IP または Driver Service 経由で接続（spark.kubernetes.executor.useDriverPodIP）
- **Namespace**: spark.kubernetes.namespace で指定（デフォルト: default）
- **RBAC**: spark Namespace に ServiceAccount（spark-sa）、ClusterRole（spark-role）を設定し、Pods リソースへの全操作権限を付与

#### Kerberos 認証

- Hadoop 環境との統合時に Kerberos 認証をサポート
- Driver Pod 上で Kerberos 認証情報を管理（KerberosConfDriverFeatureStep）

## ミドルウェア

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| Java（Azul Zulu OpenJDK） | 21（Docker イメージデフォルト）/ 17（CI環境） | Spark ランタイム実行環境 |
| Scala | 2.13 | Spark コア実装言語 |
| Apache Maven | - | ビルドツール（pom.xml） |
| tini | - | Docker コンテナの init プロセス |
| Python | 3.9 / 3.10 / 3.11 / 3.12 / 3.13 | PySpark 実行環境 |
| R | 4.x | SparkR 実行環境 |
| PyPy | 3.10 | PySpark 代替 Python ランタイム |
| gRPC | 1.76.0 | Spark Connect プロトコル通信 |
| Protocol Buffers | 6.33.5 | Spark Connect データシリアライゼーション |
| Apache Hadoop | （外部依存） | HDFS/YARN 連携 |
| Apache Hive | （外部依存） | Hive メタストア連携 |
| Log4j2 | - | ログフレームワーク（log4j2.properties.template） |

## 外部サービス連携

| サービス名 | 用途 | 接続方式 |
| --- | --- | --- |
| HDFS（Hadoop Distributed File System） | 分散ファイルストレージ、イベントログ保存 | Hadoop Client（HADOOP_CONF_DIR） |
| YARN ResourceManager | リソース管理（YARN モード） | YARN Client（YARN_CONF_DIR） |
| Kubernetes API Server | Pod 管理（K8s モード） | Kubernetes Client（kubeconfig / ServiceAccount） |
| Apache Kafka | ストリーミングデータソース | Kafka Connector（connector/kafka-0-10-sql） |
| Amazon Kinesis | ストリーミングデータソース | Kinesis Connector（connector/kinesis-asl） |
| Apache Hive Metastore | メタデータ管理 | Hive Client（hive-site.xml） |
| クラウドストレージ（S3/GCS/ABFS/OBS） | オブジェクトストレージ | hadoop-cloud モジュール経由 |
| Prometheus | メトリクス収集 | PrometheusServlet（/metrics/prometheus） |
| Graphite | メトリクス収集 | GraphiteSink（TCP/UDP） |
| StatsD | メトリクス収集 | StatsdSink（UDP、デフォルトポート 8125） |
| Ganglia | メトリクス収集 | GangliaSink（multicast/unicast） |
| JMX | メトリクス収集 | JmxSink |
| Docker Registry | コンテナイメージ取得 | Docker pull（spark.kubernetes.container.image.pullSecrets） |

## スケーリング設計

### Standalone モードのスケーリング

- **水平スケーリング**: workers ファイルに Worker ノードのホスト名を追加することでクラスタを拡張
- **Worker 管理スクリプト**:
  - `start-workers.sh` / `stop-workers.sh`: 全 Worker の一括起動・停止
  - `start-worker.sh` / `stop-worker.sh`: 個別 Worker の起動・停止
  - `decommission-worker.sh`: Worker のグレースフルデコミッション

### Kubernetes モードのスケーリング

- **動的リソース割り当て（Dynamic Allocation）**: spark.dynamicAllocation.enabled を有効化することで、Executor Pod を需要に応じて自動スケール
- **Executor ロール**: spark.kubernetes.executor.rollInterval と spark.kubernetes.executor.rollPolicy により、一定間隔で Executor を入れ替え可能
  - ロールポリシー: ID、ADD_TIME、TOTAL_GC_TIME、TOTAL_DURATION、AVERAGE_DURATION、FAILED_TASKS、PEAK_JVM_ONHEAP_MEMORY、PEAK_JVM_OFFHEAP_MEMORY、TOTAL_SHUFFLE_WRITE、DISK_USED、OUTLIER（デフォルト）、OUTLIER_NO_FALLBACK
- **Pod テンプレート**: driver-template.yml / executor-template.yml により Pod のカスタマイズが可能
- **StatefulSet アロケータ**: StatefulSetPodsAllocator による安定した Pod 名の管理
- **Deployment アロケータ**: DeploymentPodsAllocator による Deployment ベースの Executor 管理
- **Volcano スケジューラ統合**: PodGroup テンプレートによる優先度ベースのスケジューリング

### Resource Profile

- Executor ごとに異なるリソースプロファイル（CPU、メモリ、GPU等）を設定可能
- SPARK_RESOURCE_PROFILE_ID_LABEL によるラベル管理

## 可用性設計

### Standalone モードの高可用性

- **Master HA**: ZooKeeper を使用した複数 Master のフェイルオーバー構成が可能
- **Worker 障害対応**: Worker 障害時、その上の Executor が失われ、Driver により再スケジュールされる

### Kubernetes モードの高可用性

- **Driver Service**: Kubernetes Service によるドライバーへの安定したアクセス
- **Executor Pod 障害対応**: ExecutorPodsLifecycleManager により障害 Pod を検知し、新規 Pod を自動作成
- **Graceful Decommission**: decom.sh スクリプトによるグレースフルシャットダウン（spark.kubernetes.decommission.script=/opt/decom.sh）
- **PVC 再利用**: ドライバーが PVC を所有し、削除された Executor の PVC を再利用可能（spark.kubernetes.driver.ownPersistentVolumeClaim=true、spark.kubernetes.driver.reusePersistentVolumeClaim=true）

### YARN モードの高可用性

- YARN ResourceManager HA（Hadoop 側の設定に依存）
- Application Master の再試行による障害回復

## バックアップ設計

| 対象 | 方式 | 頻度 | 保持期間 |
| --- | --- | --- | --- |
| イベントログ（spark.eventLog） | HDFS/クラウドストレージへの書き込み | リアルタイム（アプリケーション実行時） | 設定依存（spark.history.fs.cleaner.maxAge） |
| Spark 設定ファイル（conf/） | バージョン管理システム（Git） | 変更時 | リポジトリの保持ポリシーに従う |
| Kubernetes マニフェスト | バージョン管理システム（Git） | 変更時 | リポジトリの保持ポリシーに従う |
| PersistentVolumeClaim データ | Kubernetes StorageClass に依存 | StorageClass 設定依存 | PVC ライフサイクルに従う |

## 監視設計

### メトリクスシステム

Apache Spark は内部メトリクスシステムを備え、以下のインスタンスごとにメトリクスを収集する。

- **master**: Master プロセスのメトリクス
- **worker**: Worker プロセスのメトリクス
- **executor**: Executor プロセスのメトリクス
- **driver**: Driver プロセスのメトリクス
- **applications**: アプリケーション単位のメトリクス

### メトリクスソース

| ソース | 説明 |
| --- | --- |
| JvmSource | JVM ヒープ使用量、GC 統計などの低レベルメトリクス |
| MasterSource | Master 固有のメトリクス（Standalone モード） |
| WorkerSource | Worker 固有のメトリクス（Standalone モード） |

### メトリクスシンク（出力先）

| シンク | プロトコル | デフォルト設定 |
| --- | --- | --- |
| MetricsServlet | HTTP JSON | /metrics/json（自動有効化） |
| PrometheusServlet | HTTP Prometheus 形式 | /metrics/prometheus |
| ConsoleSink | コンソール出力 | 10秒間隔 |
| CSVSink | CSV ファイル出力 | 10秒間隔、出力先 /tmp |
| JmxSink | JMX | - |
| GraphiteSink | TCP/UDP | 10秒間隔 |
| StatsdSink | UDP | 10秒間隔、ポート 8125 |
| GangliaSink | multicast/unicast | 10秒間隔 |
| Slf4jSink | SLF4J ログ | - |

### Web UI による監視

| Web UI | URL | 用途 |
| --- | --- | --- |
| Master UI | http://{master}:8080 | クラスタ全体の状態、Worker 一覧、アプリケーション一覧 |
| Worker UI | http://{worker}:8081 | Worker の状態、実行中 Executor |
| Application UI | http://{driver}:4040 | ジョブ、ステージ、タスクの実行状態 |
| History Server UI | http://{history-server}:18080 | 完了アプリケーションの実行履歴 |

## コンテナイメージ設計（Kubernetes モード）

### ベースイメージ

| イメージ | ベース | 主要パッケージ |
| --- | --- | --- |
| Spark Scala/Java | azul/zulu-openjdk:21 | bash, tini, libc6, libpam-modules, krb5-user, libnss3, procps, net-tools, logrotate, libssl-dev |
| Spark Python | Spark ベースイメージ | python3, python3-pip |
| Spark R | Spark ベースイメージ | r-base, r-base-dev |
| Spark Infra（CI/CD） | ubuntu:jammy-20240911.1 | openjdk-17, python3.9-3.13, R, PyPy, Node.js, npm |

### コンテナ設定

- **SPARK_HOME**: /opt/spark
- **WORKDIR**: /opt/spark/work-dir
- **ENTRYPOINT**: /opt/entrypoint.sh
- **実行ユーザー**: UID 185（非 root）
- **イメージプルポリシー**: IfNotPresent（デフォルト）、Always、Never から選択可能

### イメージ設定パラメータ

| パラメータ | 説明 | デフォルト |
| --- | --- | --- |
| spark.kubernetes.container.image | 共通コンテナイメージ | - |
| spark.kubernetes.driver.container.image | Driver 専用イメージ | container.image にフォールバック |
| spark.kubernetes.executor.container.image | Executor 専用イメージ | container.image にフォールバック |
| spark.kubernetes.container.image.pullPolicy | イメージプルポリシー | IfNotPresent |
| spark.kubernetes.container.image.pullSecrets | プライベートレジストリ認証 | - |

## ストレージ設計（Kubernetes モード）

### Persistent Volume Claim（PVC）

- **アクセスモード**: ReadWriteOncePod（デフォルト）。レガシーモードとして ReadWriteOnce も選択可能（spark.kubernetes.legacy.useReadWriteOnceAccessMode）
- **PVC 所有権**: Driver Pod が PVC を所有（spark.kubernetes.driver.ownPersistentVolumeClaim=true）
- **PVC 再利用**: 削除された Executor の PVC を再利用可能（spark.kubernetes.driver.reusePersistentVolumeClaim=true）
- **PVC 待機**: PVC 数が上限に達した場合に待機可能（spark.kubernetes.driver.waitToReusePersistentVolumeClaim）

### ボリュームマウント

- **Secret Volume**: Kubernetes 認証情報のマウント（/mnt/secrets/spark-kubernetes-credentials）
- **ConfigMap Volume**: Spark 設定の配布（/opt/spark/conf）
- **Pod Template Volume**: Pod テンプレートの配置（/opt/spark/pod-template）
- **Local Dirs**: シャッフル・RDD データ用ローカルディレクトリ（SPARK_LOCAL_DIRS/SPARK_EXECUTOR_DIRS）

## 備考

### 前提条件

- Kubernetes モードでは Kubernetes クラスタ（API Server）が別途必要
- YARN モードでは Hadoop クラスタ（HDFS、YARN）が別途必要
- Standalone モードでは Java ランタイム（JDK 21 推奨）が各ノードに必要
- イベントログの保存先として HDFS またはクラウドストレージが推奨される

### 設定ファイル

| ファイル | 場所 | 用途 |
| --- | --- | --- |
| spark-defaults.conf | ${SPARK_HOME}/conf/ | Spark デフォルト設定 |
| spark-env.sh | ${SPARK_HOME}/conf/ | 環境変数設定 |
| workers | ${SPARK_HOME}/conf/ | Standalone Worker ノード一覧 |
| metrics.properties | ${SPARK_HOME}/conf/ | メトリクスシステム設定 |
| log4j2.properties | ${SPARK_HOME}/conf/ | ログ設定 |
| fairscheduler.xml | ${SPARK_HOME}/conf/ | フェアスケジューラ設定 |

### 接続タイムアウト設定（Kubernetes モード）

| パラメータ | 説明 | デフォルト |
| --- | --- | --- |
| spark.kubernetes.submission.requestTimeout | Driver 起動時のリクエストタイムアウト | 10000ms |
| spark.kubernetes.submission.connectionTimeout | Driver 起動時の接続タイムアウト | 10000ms |
| spark.kubernetes.driver.requestTimeout | Executor 要求時のリクエストタイムアウト | 10000ms |
| spark.kubernetes.driver.connectionTimeout | Executor 要求時の接続タイムアウト | 10000ms |
| spark.kubernetes.configMap.maxSize | ConfigMap 最大サイズ | 1048576 bytes (1 MiB) |
