© 2021 NTT DATA Corporation
Apache Spark on Kubernetes入門
2021年9月18日
株式会社NTTデータ技術革新統括本部技術開発本部先進コンピューティング技術センタ
© 2021 NTT DATA Corporation 2
本日のトピック
分散処理ソフトウェアであるApache Sparkを、
コンテナオーケストレーションツールのKubernetesクラスタ上で動作させる方法について紹介
• Apach Spark on K8sの概要
についてまず触れ、最初につまづきがちな
• コンテナのビルド方法
• メモリ関連の設定方法
について詳しく述べつつ、細かなTipsについて触れていきます。
© 2021 NTT DATA Corporation 3
自己紹介
依田 玲央奈 (よだ れおな)
• -2020
データエンジニア
前処理/分析にSparkを利用
• 2021-
OSS開発、サポート
よちよち歩きはじめたて
© 2021 NTT DATA Corporation 4
所属チームについて
様々なOSSのコミッタが在籍
Apache Airflow
Apache Bigtop
Apache Hadoop
Apache Spark
OpenJDK
PostgreSQL
…
https://www.nttdata.com/jp/ja/news/information/2021/083000/
プランクトン依田は日々おびえながら過ごしてます
© 2021 NTT DATA Corporation 5
Apache Spark on Kubernetes
の概要
© 2021 NTT DATA Corporation 6
Kubernetes (K8s)
多数のコンテナから構成されるアプリケーションの実行を、
様々な機能を用いて支援・管理するツール
コンテナ利用の拡大とともに様々なシステムで利用されるように
コンテナ化された
アプリケーション
ユーザー
Kubernetesクラスタ
© 2021 NTT DATA Corporation 7
主な機能
• Self-healing
処理を失敗したコンテナを自動で再起動
• Service discovery and load balancing
K8sの内部NWにおいて、DNSや独自IPを利用しコンテナへ
アクセス、また外部に向けて公開可
Pod: K8sを構成する1単位
内部に1~複数のコンテナを持つ
© 2021 NTT DATA Corporation 8
主な機能
• Automatic bin packing
各コンテナがどの程度のCPU/メモリを利用するかを宣言、
K8sはノードへの配置を調整
Node: ホストマシンの呼称
© 2021 NTT DATA Corporation 9
YAMLでリソースを記述し
kubectlコマンドでデプロイ
kubectlコマンドを通じ
リソース操作
Kubernetes (K8s)の操作
※今回メインで紹介するSpark Jobのデプロイ方法とは少し異なります
Image
Registry
© 2021 NTT DATA Corporation 10
Apache Spark
大量のデータを複数台マシンで、高速に処理するソフトウェア
大量のデータセットを
(数100GBs, TBs, PBs...)
複数台のサーバで構成された
クラスタを用いて
現実的な時間で処理する
(数十分, 数時間のオーダー)
© 2021 NTT DATA Corporation 11
Sparkの構成要素
• ユーザーが記述したジョブをDriver(スケジューラ)がタスクへ分解
• Executorがそれぞれのタスクを処理
Executor
ワーカノード
Executor
タスク タスク
・・・
ワーカノード
Driver
(スケジューラ)
複数のExecutor / スロットで、
ワーカノード単体でも並列処理
スロット スロット
Executorにタスクを割り当てる
クラスタ
© 2021 NTT DATA Corporation 12
Sparkのプログラミング言語とソフトウェアスタック
様々なインターフェースから、様々な形態のジョブを記述可能
Spark Core
(実行エンジンおよび汎用的なデータ処理ライブラリ)
Spark
Streaming
(ストリーム処理)
Structured
Streaming
(ストリーム処理)
GraphX
(グラフ処理)
MLlib
(機械学習)
Spark SQL
(クエリ処理)
SQL
例: 1台のメモリに乗らない
巨大データセットをPySpark
で高速に分析
© 2021 NTT DATA Corporation 13
Sparkの実行環境
利用シーンに応じて様々な実行環境
• Local: ローカル環境実行、手元での開発、試験など
• Standalone: 手動で各サーバー上で起動するシンプルなクラスター環境
• YARN: Hadoopのリソースマネージャ、様々なOSSが利用
• Mesos: Mesos自体は昨年atticに
© 2021 NTT DATA Corporation 14
2021/3 リリースのSpark 3.1.1 より
© 2021 NTT DATA Corporation 15
Running Apache Spark on K8s
• v2.3.0 (2018/2)
• Experimental support
• v2.4.0 (2018/11)
• PySpark bindings for K8S
• R bindings for K8S
• Support client mode for Kubernetes cluster backend
• Support for mounting K8S volumes
• v3.0.0 (2020/6)
• Support user-specified driver and executor pod templates
• Allow dynamic allocation without an external shuffle service
• More responsive dynamic allocation with K8S
• Kerberos Support for Spark on K8S
• Kerberos Support in Kubernetes resource manager (Client Mode)
• Support client dependencies with a Hadoop Compatible File System
• Add configurable auth secret source in k8s backend
• Support subpath mounting with Kubernetes
• Make Python 3 the default in PySpark Bindings for K8S
• v3.1.1 (2021/3)
• GA
Release note より抜粋
実は3年前より利用可能
© 2021 NTT DATA Corporation 16
Kubernetes上で実行するメリット
• 既存K8sクラスタのリソース利用
• ビルドされたコンテナ(と、キックするクライアント)があれば利用可能
• 他コンポーネントとのロギング、モニタリングの共通化
• ジョブの実行単位はPod
 daemonsetによるリソースを監視する仕組みを流用可能
(fluent bitなど)
※現在一部Spark機能を使えないものもあるので注意
(YARN modeにおけるのジョブキューの機能や、
External Shuffle Resourceなど)
Daemonset: 各Nodeに
常駐するK8sのリソース
© 2021 NTT DATA Corporation 17
起動方法
他のリソースマネジャーと同様spark-submitを通じて起動
./bin/spark-submit 
--master k8s://https://${K8S_API_ADDR}:${K8S_API_PORT} 
--deploy-mode cluster 
--name spark-pi 
--class org.apache.spark.examples.SparkPi 
--conf spark.executor.instances=2 
--conf spark.kubernetes.container.image=${SPARK_IMAGE} 
--conf spark.kubernetes.driver.pod.name=sparkdriverpod 
local:///opt/spark/examples/jars/spark-examples_2.12-
3.1.2.jar 1000
kubectlでクラスタ操作可能な環境に、Sparkのライブラリを配置してクライアントに
© 2021 NTT DATA Corporation 18
起動方法
他のリソースマネジャーと同様spark-submitを通じて起動
./bin/spark-submit 
--master k8s://https://${K8S_API_ADDR}:${K8S_API_PORT} 
--deploy-mode cluster 
--name spark-pi 
--class org.apache.spark.examples.SparkPi 
--conf spark.executor.instances=2 
--conf spark.kubernetes.container.image=${SPARK_IMAGE} 
--conf spark.kubernetes.driver.pod.name=sparkdriverpod 
local:///opt/spark/examples/jars/spark-examples_2.12-3.1.2.jar 1000
Prefixをk8sに
© 2021 NTT DATA Corporation 19
起動方法
他のリソースマネジャーと同様spark-submitを通じて起動
./bin/spark-submit 
--master k8s://https://${K8S_API_ADDR}:${K8S_API_PORT} 
--deploy-mode cluster 
--name spark-pi 
--class org.apache.spark.examples.SparkPi 
--conf spark.executor.instances=2 
--conf spark.kubernetes.container.image=${SPARK_IMAGE} 
--conf spark.kubernetes.driver.pod.name=sparkdriverpod 
local:///opt/spark/examples/jars/spark-examples_2.12-3.1.2.jar 1000
K8sのControl Planeのアドレス:ポート
(kubectl cluster-info などで確認可能)
© 2021 NTT DATA Corporation 20
起動方法
他のリソースマネジャーたちと同様spark-submitを通じて起動
./bin/spark-submit 
--master k8s://https://${K8S_API_ADDR}:${K8S_API_PORT} 
--deploy-mode cluster 
--name spark-pi 
--class org.apache.spark.examples.SparkPi 
--conf spark.executor.instances=2 
--conf spark.kubernetes.container.image=${SPARK_IMAGE} 
--conf spark.kubernetes.driver.pod.name=sparkdriverpod 
local:///opt/spark/examples/jars/spark-examples_2.12-3.1.2.jar 1000
Client Mode(対話的なデータ操作)も可能、後述
© 2021 NTT DATA Corporation 21
起動方法
他のリソースマネジャーたちと同様spark-submitを通じて起動
./bin/spark-submit 
--master k8s://https://${K8S_API_ADDR}:${K8S_API_PORT} 
--deploy-mode cluster 
--name spark-pi 
--class org.apache.spark.examples.SparkPi 
--conf spark.executor.instances=2 
--conf spark.kubernetes.container.image=${SPARK_IMAGE} 
--conf spark.kubernetes.driver.pod.name=sparkdriverpod 
local:///opt/spark/examples/jars/spark-examples_2.12-3.1.2.jar 1000
Executorの並列数(=起動するExecutor Pod数)
© 2021 NTT DATA Corporation 22
起動方法
他のリソースマネジャーたちと同様spark-submitを通じて起動
./bin/spark-submit 
--master k8s://https://${K8S_API_ADDR}:${K8S_API_PORT} 
--deploy-mode cluster 
--name spark-pi 
--class org.apache.spark.examples.SparkPi 
--conf spark.executor.instances=2 
--conf spark.kubernetes.container.image=${SPARK_IMAGE} 
--conf spark.kubernetes.driver.pod.name=sparkdriverpod 
local:///opt/spark/examples/jars/spark-examples_2.12-3.1.2.jar 1000
コンテナのリポジトリ/イメージ名
KubernetesクラスタがPullできる場所にある必要あり
© 2021 NTT DATA Corporation 23
起動の流れ
Driver/ExecutorとしてPodが利用される
・・・
Image
Registry
1. spark-submit
© 2021 NTT DATA Corporation 24
起動の流れ
Driver/ExecutorとしてPodが利用される
・・・
Driver Pod
Image
Registry
1. spark-submit
2. Driver Podが起動
© 2021 NTT DATA Corporation 25
起動の流れ
Driver/ExecutorとしてPodが利用される
・・・
Driver Pod
Image
Registry
1. spark-submit
2. Driver Podが起動 3. Executor Pod
起動依頼
© 2021 NTT DATA Corporation 26
起動の流れ
Driver/ExecutorとしてPodが利用される
Executor Pod
・・・
Executor Pod
Driver Pod
Image
Registry
1. spark-submit
2. Driver Podが起動 3. Executor Pod
起動依頼
4. Executor Podが起動
© 2021 NTT DATA Corporation 27
起動の流れ
Driver/ExecutorとしてPodが利用される
Executor Pod
・・・
Executor Pod
Driver Pod
Image
Registry
1. spark-submit
2. Driver Podが起動 3. Executor Pod
起動依頼
4. Executor Podが起動
5. タスク実行
© 2021 NTT DATA Corporation 28
動作の仕組みに起因する注意点
RBACが有効化されているクラスタでは、Driver PodがExecutor Podを起動するために、
Podを起動する権限を持ったService Accountを作成して利用する必要あり
kubectl create serviceaccount spark
kubectl create clusterrolebinding spark-role 
--clusterrole=edit --serviceaccount=default:spark --namespace=default
作成例
作成したSAを利用するようspark-submitにオプションを付与
--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark
※RBAC (Role-Based Access Control): クラスタやNamespace単位で、リソース操作を管理するK8sのしくみ
© 2021 NTT DATA Corporation 29
コンテナのビルド方法
© 2021 NTT DATA Corporation 30
コンテナのビルド方法
2021/9現在、配布されているライブラリ中に含まれるDockerfileと、
スクリプトを利用しビルドするのがOfficialな方法
./bin/docker-image-tool.sh -r <repo> -t my-tag build
./bin/docker-image-tool.sh -r <repo> -t my-tag push
<repo>/spark:<my-tag>の名前でビルドされる
ドキュメント記載の方法
リポジトリにPush
© 2021 NTT DATA Corporation 31
Dockerfileのありか
Dockerfile自体は
/resource-managers/kubernetes/docker/src/main/dockerfiles/spark/Dockerfile
に存在
entrypoint (起動時に実行されるスクリプト)もここに
PySpark, SparkR用のDockerfileが格納
© 2021 NTT DATA Corporation 32
docker-image-tool.shの詳細
細かいオプション有(./bin/docker-image-tool.sh usage で確認可能)
# 一部を紹介
-p file Pythonランタイムを含んだイメージを作成.
Officialなものを利用する場合でも
-p kubernetes/dockerfiles/spark/bindings/python/Dockerfile
のように指定必要
-R file Rランタイムを含んだイメージを作成、Pythonと同様。
-u uid Sparkのメインプロセスの利用するUID指定(デフォルトだと185)
-b arg DockerfileのARGに渡されるパラメータ。
例えば -b java_image_tag=8-jre-slim とすると
OpenJDK 8をベースイメージとして使用(3.1のデフォルトは11-jre-slim)
© 2021 NTT DATA Corporation 33
docker-image-tool.shの詳細
細かいオプション有(./bin/docker-image-tool.sh usage で確認可能)
-m minikubeのDockerデーモンを利用.
(minikubeを実行しているdocker環境内でビルドしてくれる)
-X buildx を利用しクロスプラットフォーム対応イメージをビルド。
(amd64とaarch64を同時にビルドなど)
Buildx有効化が必要 + 同時にPushを行うためリポジトリ指定が必須
DockerHub等を利用する場合
docker loginしておく必要も
© 2021 NTT DATA Corporation 34
メモリ関連の設定方法
© 2021 NTT DATA Corporation 35
リソース管理
DriverやExecutorに対するCPU/メモリ割り当て
./bin/spark-submit 
...
--conf spark.executor.instances=2 
--conf spark.executor.cores=2 
--conf spark.executor.memory=4g 
...
シンプルに指定する方法(Executor2つ、コア数2、メモリ4GB)
spark.{driver,executor}.{cores,memory} を通じ設定
© 2021 NTT DATA Corporation 36
Q. 次のようなクラスタで、このパラメータで実行できるか?
--conf spark.executor.instances=2 
--conf spark.executor.cores=2 
--conf spark.executor.memory=4g 
空きリソース
2CPU, 4GB(4096MB) メモリのNode × 2台
※本当にこんなワークロードだったら1台でやりましょう…
© 2021 NTT DATA Corporation 37
Spark on K8sのメモリ使用
A. メモリが少し不足するため起動しない
kubectl get pod spark-pi-5387257bab525975-exec-1 -o yaml
…
resources:
limits:
memory: 4505Mi
requests:
cpu: "2"
memory: 4505Mi
…
K8sに対して少し大きいメモリを要求
© 2021 NTT DATA Corporation 38
K8sのRequest/Limit
リソース割り当ての値の設定値(CPUとメモリについて設定可能)
Pod内のコンテナごとに設定が可能
Request
この値の合計値がNodeのキャパシティを超えないように、スケジューラがPodをデプロイ
Limit
リソース消費の上限値
メモリの消費がこれに達した場合、PodごとEvictされる
© 2021 NTT DATA Corporation 39
Sparkのメモリ設定①
spark.{driver/executor}.memoryOverhead
の値により積み増し(デフォルト0.1)
spark.{driver/executor}.memory
で設定した値
コンテナの
Request/Limit
に設定される値
Nodeにはこれを上回る
空きリソースが必要
JVMへ与えられるリソース
(-Xms,-Xmxオプション両方に設定)
JVM外に確保
© 2021 NTT DATA Corporation 40
Sparkのメモリ設定②
Sparkが利用するメモリ
spark.memory.fractionで決定
(デフォルト0.6)
ユーザーが利用するメモリ
1-spark.memory.fraction
User Memory
Spark Memory
Reserved Memory Sparkの内部オブジェクト格納
300MiB
ヒープメモリとして
一括で確保されるので、
JVMからメトリクス取得する
しくみを導入しておくと
チューニングにGood
© 2021 NTT DATA Corporation 41
KubernetesのQuality of Service (QoS)
Podのスケジューリングの際の優先順位
• BestEffort
優先度最低、まずこのQoSの設定のものから停止される
Pod内のコンテナにRequest/Limitを設定しないとこのQoS
• Burstable
優先度中
BestEffort、Guaranteed以外の設定でこのQoS
• Guaranteed
優先度最高
Pod内のすべてのコンテナに、CPU、メモリ両方のRequestとLimitが設定され、かつ
それぞれのRequest/Limitの値が同値
© 2021 NTT DATA Corporation 42
デフォルトだとSparkは…
再掲
kubectl get pod spark-pi-5387257bab525975-exec-1 -o yaml
…
resources:
limits:
memory: 4505Mi
requests:
cpu: "2"
memory: 4505Mi
…
CPU limitが設定されてい
ないためBurstable
© 2021 NTT DATA Corporation 43
QoSの変更
--conf spark.kubernetes.executor.request.cores=2 
--conf spark.kubernetes.executor.limit.cores=2 
CPU Request/Limitに
ついて明示的に指定すると
Guaranteedに
ロギング/モニタリング等、他のPodとの優先順位を明確にしておくとGood
(監視関連をGuaranteed、SparkはBurstableにして原因特定をしやすくするなど)
…
podIPs:
- ip: 172.17.0.4
qosClass: Guaranteed
startTime: "2021-09-06T05:17:23Z"
© 2021 NTT DATA Corporation 44
その他のTips、注意事項など
© 2021 NTT DATA Corporation 45
Web UIのみかた
Driver Pod の4040番ポートへつなぐとSpark Web UIが確認可能
kubectl get pod
kubectl port-forward ${DRIVER_POD_NAME} 4040:4040
Driver のPod名を確認
kubectl実行端末 ~ Driver のPodへのポートフォワード
localhost:4040にて閲覧可能
kubectlをサーバー上で実施している場合は--
address=0.0.0.0オプション+サーバーのアドレス:4040にて
閲覧可能に
© 2021 NTT DATA Corporation 46
ジョブの終了時
• Executor Podは実行後消滅
• Driver PodはCompletedの状態に
• logの確認は可能
• port forwardは不可
詳細のトレースにはロギング/モニタリングの環境を設定しておく必要あり
© 2021 NTT DATA Corporation 47
Clientモードの利用
Nodebookから対話的に操作したいときなど
headless serviceを利用し
Executor  Driverへのルート作成
Notebook兼
Driver
apiVersion: v1
kind: Service
metadata:
name: spark-driver-headless
spec:
type: ClusterIP
clusterIP: None
ports:
- name: "spark-driver"
protocol: "TCP"
port: 51810
targetPort: 51810
selector:
app: notebook
headless service
特定名のPodへのFQDNを提供
--conf spark.driver.host=spark-driver-headless.default.svc.cluster.local 
--conf spark.driver.port=51810
© 2021 NTT DATA Corporation 48
ストレージに関する注意点
PodのYAMLを確認すると…
spec:
containers:
...
volumeMounts:
...
- mountPath: /var/data/spark-f4b00c83-08ac-4046-b6ba-0fc83c96c77b
name: spark-local-dir-1
...
volumes:
...
- emptyDir: {}
name: spark-local-dir-1
デフォルトでemptyDirを
作成して、Podがマウントする
© 2021 NTT DATA Corporation 49
emptyDir
Podと同じライフサイクルの一時ディレクトリ
• Podが作成されると同時に作成され、Podが消滅すると同時に消滅
• 同一Pod内のコンテナからマウントし参照可
• 記憶媒体はkubeletの存在するファイルシステムに依存(通常ディスク or SSD)
配置されたノードのストレージを利用
© 2021 NTT DATA Corporation 50
SparkのLocal Strage
シャッフルの際にあふれたデータの保管場所として利用
デフォルトだとemptyDirを利用するため、ノードのディスクを利用する形に
• ノードのディスクに空き容量が必要になる
• パフォーマンスのボトルネックとなる
ことも
Executor Pod
Executor Pod JOINなどでの
データ移動
© 2021 NTT DATA Corporation 51
tmpfs の利用
emptyDirのバックエンドをtmpfsにし、RAMを利用することも可能
--conf spark.kubernetes.local.dirs.tmpfs=true
- emptyDir:
medium: Memory
name: spark-local-dir-1
マニフェストにはこのように反映
メモリの使用量が上昇するため、Nodeの空きリソースや、
先述の memoryOverhead の値を確認しつつ調整する
© 2021 NTT DATA Corporation 52
Spark on Kubernetes を利用した様々な広がり
K8s Operator
Custom Resource Definitionによるユーザー独自のリソース定義と、
それを管理するControllerを作成することで、よりK8sに沿ったアプリケーション
管理を可能にするしくみ)
Sparkについてもいくつか実装が公開
Google Cloud Platform
が公開しているものが有名
kubectl apply -f spark-pi.yaml
YAMLでのデプロイや、
アプリケーション監視によるより細かな制御など
© 2021 NTT DATA Corporation 53
まとめ(本日のトピック再掲)
分散処理ソフトウェアであるApache Sparkを、
コンテナオーケストレーションツールのKubernetesクラスタ上で動作させる方法について紹介
• Apach Spark on K8sの概要
についてまず触れ、最初につまづきがちな
• コンテナのビルド方法
• メモリ関連の設定方法
について詳しく述べつつ、細かなTipsについて紹介
© 2021 NTT DATA Corporation 54
まとめ(本日のトピック再掲)
分散処理ソフトウェアであるApache Sparkを、
コンテナオーケストレーションツールのKubernetesクラスタ上で動作させる方法について紹介
• Apach Spark on K8sの概要
についてまず触れ、最初につまづきがちな
• コンテナのビルド方法
• メモリ関連の設定方法
について詳しく述べつつ、細かなTipsについて紹介
Happy K8s and Spark
experiences !!
© 2021 NTT DATA Corporation
本資料に記載されている会社名、商品名、又はサービス名は、各社の登録商標又は商標です。

Apache Spark on Kubernetes入門(Open Source Conference 2021 Online Hiroshima 発表資料)

  • 1.
    © 2021 NTTDATA Corporation Apache Spark on Kubernetes入門 2021年9月18日 株式会社NTTデータ技術革新統括本部技術開発本部先進コンピューティング技術センタ
  • 2.
    © 2021 NTTDATA Corporation 2 本日のトピック 分散処理ソフトウェアであるApache Sparkを、 コンテナオーケストレーションツールのKubernetesクラスタ上で動作させる方法について紹介 • Apach Spark on K8sの概要 についてまず触れ、最初につまづきがちな • コンテナのビルド方法 • メモリ関連の設定方法 について詳しく述べつつ、細かなTipsについて触れていきます。
  • 3.
    © 2021 NTTDATA Corporation 3 自己紹介 依田 玲央奈 (よだ れおな) • -2020 データエンジニア 前処理/分析にSparkを利用 • 2021- OSS開発、サポート よちよち歩きはじめたて
  • 4.
    © 2021 NTTDATA Corporation 4 所属チームについて 様々なOSSのコミッタが在籍 Apache Airflow Apache Bigtop Apache Hadoop Apache Spark OpenJDK PostgreSQL … https://www.nttdata.com/jp/ja/news/information/2021/083000/ プランクトン依田は日々おびえながら過ごしてます
  • 5.
    © 2021 NTTDATA Corporation 5 Apache Spark on Kubernetes の概要
  • 6.
    © 2021 NTTDATA Corporation 6 Kubernetes (K8s) 多数のコンテナから構成されるアプリケーションの実行を、 様々な機能を用いて支援・管理するツール コンテナ利用の拡大とともに様々なシステムで利用されるように コンテナ化された アプリケーション ユーザー Kubernetesクラスタ
  • 7.
    © 2021 NTTDATA Corporation 7 主な機能 • Self-healing 処理を失敗したコンテナを自動で再起動 • Service discovery and load balancing K8sの内部NWにおいて、DNSや独自IPを利用しコンテナへ アクセス、また外部に向けて公開可 Pod: K8sを構成する1単位 内部に1~複数のコンテナを持つ
  • 8.
    © 2021 NTTDATA Corporation 8 主な機能 • Automatic bin packing 各コンテナがどの程度のCPU/メモリを利用するかを宣言、 K8sはノードへの配置を調整 Node: ホストマシンの呼称
  • 9.
    © 2021 NTTDATA Corporation 9 YAMLでリソースを記述し kubectlコマンドでデプロイ kubectlコマンドを通じ リソース操作 Kubernetes (K8s)の操作 ※今回メインで紹介するSpark Jobのデプロイ方法とは少し異なります Image Registry
  • 10.
    © 2021 NTTDATA Corporation 10 Apache Spark 大量のデータを複数台マシンで、高速に処理するソフトウェア 大量のデータセットを (数100GBs, TBs, PBs...) 複数台のサーバで構成された クラスタを用いて 現実的な時間で処理する (数十分, 数時間のオーダー)
  • 11.
    © 2021 NTTDATA Corporation 11 Sparkの構成要素 • ユーザーが記述したジョブをDriver(スケジューラ)がタスクへ分解 • Executorがそれぞれのタスクを処理 Executor ワーカノード Executor タスク タスク ・・・ ワーカノード Driver (スケジューラ) 複数のExecutor / スロットで、 ワーカノード単体でも並列処理 スロット スロット Executorにタスクを割り当てる クラスタ
  • 12.
    © 2021 NTTDATA Corporation 12 Sparkのプログラミング言語とソフトウェアスタック 様々なインターフェースから、様々な形態のジョブを記述可能 Spark Core (実行エンジンおよび汎用的なデータ処理ライブラリ) Spark Streaming (ストリーム処理) Structured Streaming (ストリーム処理) GraphX (グラフ処理) MLlib (機械学習) Spark SQL (クエリ処理) SQL 例: 1台のメモリに乗らない 巨大データセットをPySpark で高速に分析
  • 13.
    © 2021 NTTDATA Corporation 13 Sparkの実行環境 利用シーンに応じて様々な実行環境 • Local: ローカル環境実行、手元での開発、試験など • Standalone: 手動で各サーバー上で起動するシンプルなクラスター環境 • YARN: Hadoopのリソースマネージャ、様々なOSSが利用 • Mesos: Mesos自体は昨年atticに
  • 14.
    © 2021 NTTDATA Corporation 14 2021/3 リリースのSpark 3.1.1 より
  • 15.
    © 2021 NTTDATA Corporation 15 Running Apache Spark on K8s • v2.3.0 (2018/2) • Experimental support • v2.4.0 (2018/11) • PySpark bindings for K8S • R bindings for K8S • Support client mode for Kubernetes cluster backend • Support for mounting K8S volumes • v3.0.0 (2020/6) • Support user-specified driver and executor pod templates • Allow dynamic allocation without an external shuffle service • More responsive dynamic allocation with K8S • Kerberos Support for Spark on K8S • Kerberos Support in Kubernetes resource manager (Client Mode) • Support client dependencies with a Hadoop Compatible File System • Add configurable auth secret source in k8s backend • Support subpath mounting with Kubernetes • Make Python 3 the default in PySpark Bindings for K8S • v3.1.1 (2021/3) • GA Release note より抜粋 実は3年前より利用可能
  • 16.
    © 2021 NTTDATA Corporation 16 Kubernetes上で実行するメリット • 既存K8sクラスタのリソース利用 • ビルドされたコンテナ(と、キックするクライアント)があれば利用可能 • 他コンポーネントとのロギング、モニタリングの共通化 • ジョブの実行単位はPod  daemonsetによるリソースを監視する仕組みを流用可能 (fluent bitなど) ※現在一部Spark機能を使えないものもあるので注意 (YARN modeにおけるのジョブキューの機能や、 External Shuffle Resourceなど) Daemonset: 各Nodeに 常駐するK8sのリソース
  • 17.
    © 2021 NTTDATA Corporation 17 起動方法 他のリソースマネジャーと同様spark-submitを通じて起動 ./bin/spark-submit --master k8s://https://${K8S_API_ADDR}:${K8S_API_PORT} --deploy-mode cluster --name spark-pi --class org.apache.spark.examples.SparkPi --conf spark.executor.instances=2 --conf spark.kubernetes.container.image=${SPARK_IMAGE} --conf spark.kubernetes.driver.pod.name=sparkdriverpod local:///opt/spark/examples/jars/spark-examples_2.12- 3.1.2.jar 1000 kubectlでクラスタ操作可能な環境に、Sparkのライブラリを配置してクライアントに
  • 18.
    © 2021 NTTDATA Corporation 18 起動方法 他のリソースマネジャーと同様spark-submitを通じて起動 ./bin/spark-submit --master k8s://https://${K8S_API_ADDR}:${K8S_API_PORT} --deploy-mode cluster --name spark-pi --class org.apache.spark.examples.SparkPi --conf spark.executor.instances=2 --conf spark.kubernetes.container.image=${SPARK_IMAGE} --conf spark.kubernetes.driver.pod.name=sparkdriverpod local:///opt/spark/examples/jars/spark-examples_2.12-3.1.2.jar 1000 Prefixをk8sに
  • 19.
    © 2021 NTTDATA Corporation 19 起動方法 他のリソースマネジャーと同様spark-submitを通じて起動 ./bin/spark-submit --master k8s://https://${K8S_API_ADDR}:${K8S_API_PORT} --deploy-mode cluster --name spark-pi --class org.apache.spark.examples.SparkPi --conf spark.executor.instances=2 --conf spark.kubernetes.container.image=${SPARK_IMAGE} --conf spark.kubernetes.driver.pod.name=sparkdriverpod local:///opt/spark/examples/jars/spark-examples_2.12-3.1.2.jar 1000 K8sのControl Planeのアドレス:ポート (kubectl cluster-info などで確認可能)
  • 20.
    © 2021 NTTDATA Corporation 20 起動方法 他のリソースマネジャーたちと同様spark-submitを通じて起動 ./bin/spark-submit --master k8s://https://${K8S_API_ADDR}:${K8S_API_PORT} --deploy-mode cluster --name spark-pi --class org.apache.spark.examples.SparkPi --conf spark.executor.instances=2 --conf spark.kubernetes.container.image=${SPARK_IMAGE} --conf spark.kubernetes.driver.pod.name=sparkdriverpod local:///opt/spark/examples/jars/spark-examples_2.12-3.1.2.jar 1000 Client Mode(対話的なデータ操作)も可能、後述
  • 21.
    © 2021 NTTDATA Corporation 21 起動方法 他のリソースマネジャーたちと同様spark-submitを通じて起動 ./bin/spark-submit --master k8s://https://${K8S_API_ADDR}:${K8S_API_PORT} --deploy-mode cluster --name spark-pi --class org.apache.spark.examples.SparkPi --conf spark.executor.instances=2 --conf spark.kubernetes.container.image=${SPARK_IMAGE} --conf spark.kubernetes.driver.pod.name=sparkdriverpod local:///opt/spark/examples/jars/spark-examples_2.12-3.1.2.jar 1000 Executorの並列数(=起動するExecutor Pod数)
  • 22.
    © 2021 NTTDATA Corporation 22 起動方法 他のリソースマネジャーたちと同様spark-submitを通じて起動 ./bin/spark-submit --master k8s://https://${K8S_API_ADDR}:${K8S_API_PORT} --deploy-mode cluster --name spark-pi --class org.apache.spark.examples.SparkPi --conf spark.executor.instances=2 --conf spark.kubernetes.container.image=${SPARK_IMAGE} --conf spark.kubernetes.driver.pod.name=sparkdriverpod local:///opt/spark/examples/jars/spark-examples_2.12-3.1.2.jar 1000 コンテナのリポジトリ/イメージ名 KubernetesクラスタがPullできる場所にある必要あり
  • 23.
    © 2021 NTTDATA Corporation 23 起動の流れ Driver/ExecutorとしてPodが利用される ・・・ Image Registry 1. spark-submit
  • 24.
    © 2021 NTTDATA Corporation 24 起動の流れ Driver/ExecutorとしてPodが利用される ・・・ Driver Pod Image Registry 1. spark-submit 2. Driver Podが起動
  • 25.
    © 2021 NTTDATA Corporation 25 起動の流れ Driver/ExecutorとしてPodが利用される ・・・ Driver Pod Image Registry 1. spark-submit 2. Driver Podが起動 3. Executor Pod 起動依頼
  • 26.
    © 2021 NTTDATA Corporation 26 起動の流れ Driver/ExecutorとしてPodが利用される Executor Pod ・・・ Executor Pod Driver Pod Image Registry 1. spark-submit 2. Driver Podが起動 3. Executor Pod 起動依頼 4. Executor Podが起動
  • 27.
    © 2021 NTTDATA Corporation 27 起動の流れ Driver/ExecutorとしてPodが利用される Executor Pod ・・・ Executor Pod Driver Pod Image Registry 1. spark-submit 2. Driver Podが起動 3. Executor Pod 起動依頼 4. Executor Podが起動 5. タスク実行
  • 28.
    © 2021 NTTDATA Corporation 28 動作の仕組みに起因する注意点 RBACが有効化されているクラスタでは、Driver PodがExecutor Podを起動するために、 Podを起動する権限を持ったService Accountを作成して利用する必要あり kubectl create serviceaccount spark kubectl create clusterrolebinding spark-role --clusterrole=edit --serviceaccount=default:spark --namespace=default 作成例 作成したSAを利用するようspark-submitにオプションを付与 --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark ※RBAC (Role-Based Access Control): クラスタやNamespace単位で、リソース操作を管理するK8sのしくみ
  • 29.
    © 2021 NTTDATA Corporation 29 コンテナのビルド方法
  • 30.
    © 2021 NTTDATA Corporation 30 コンテナのビルド方法 2021/9現在、配布されているライブラリ中に含まれるDockerfileと、 スクリプトを利用しビルドするのがOfficialな方法 ./bin/docker-image-tool.sh -r <repo> -t my-tag build ./bin/docker-image-tool.sh -r <repo> -t my-tag push <repo>/spark:<my-tag>の名前でビルドされる ドキュメント記載の方法 リポジトリにPush
  • 31.
    © 2021 NTTDATA Corporation 31 Dockerfileのありか Dockerfile自体は /resource-managers/kubernetes/docker/src/main/dockerfiles/spark/Dockerfile に存在 entrypoint (起動時に実行されるスクリプト)もここに PySpark, SparkR用のDockerfileが格納
  • 32.
    © 2021 NTTDATA Corporation 32 docker-image-tool.shの詳細 細かいオプション有(./bin/docker-image-tool.sh usage で確認可能) # 一部を紹介 -p file Pythonランタイムを含んだイメージを作成. Officialなものを利用する場合でも -p kubernetes/dockerfiles/spark/bindings/python/Dockerfile のように指定必要 -R file Rランタイムを含んだイメージを作成、Pythonと同様。 -u uid Sparkのメインプロセスの利用するUID指定(デフォルトだと185) -b arg DockerfileのARGに渡されるパラメータ。 例えば -b java_image_tag=8-jre-slim とすると OpenJDK 8をベースイメージとして使用(3.1のデフォルトは11-jre-slim)
  • 33.
    © 2021 NTTDATA Corporation 33 docker-image-tool.shの詳細 細かいオプション有(./bin/docker-image-tool.sh usage で確認可能) -m minikubeのDockerデーモンを利用. (minikubeを実行しているdocker環境内でビルドしてくれる) -X buildx を利用しクロスプラットフォーム対応イメージをビルド。 (amd64とaarch64を同時にビルドなど) Buildx有効化が必要 + 同時にPushを行うためリポジトリ指定が必須 DockerHub等を利用する場合 docker loginしておく必要も
  • 34.
    © 2021 NTTDATA Corporation 34 メモリ関連の設定方法
  • 35.
    © 2021 NTTDATA Corporation 35 リソース管理 DriverやExecutorに対するCPU/メモリ割り当て ./bin/spark-submit ... --conf spark.executor.instances=2 --conf spark.executor.cores=2 --conf spark.executor.memory=4g ... シンプルに指定する方法(Executor2つ、コア数2、メモリ4GB) spark.{driver,executor}.{cores,memory} を通じ設定
  • 36.
    © 2021 NTTDATA Corporation 36 Q. 次のようなクラスタで、このパラメータで実行できるか? --conf spark.executor.instances=2 --conf spark.executor.cores=2 --conf spark.executor.memory=4g 空きリソース 2CPU, 4GB(4096MB) メモリのNode × 2台 ※本当にこんなワークロードだったら1台でやりましょう…
  • 37.
    © 2021 NTTDATA Corporation 37 Spark on K8sのメモリ使用 A. メモリが少し不足するため起動しない kubectl get pod spark-pi-5387257bab525975-exec-1 -o yaml … resources: limits: memory: 4505Mi requests: cpu: "2" memory: 4505Mi … K8sに対して少し大きいメモリを要求
  • 38.
    © 2021 NTTDATA Corporation 38 K8sのRequest/Limit リソース割り当ての値の設定値(CPUとメモリについて設定可能) Pod内のコンテナごとに設定が可能 Request この値の合計値がNodeのキャパシティを超えないように、スケジューラがPodをデプロイ Limit リソース消費の上限値 メモリの消費がこれに達した場合、PodごとEvictされる
  • 39.
    © 2021 NTTDATA Corporation 39 Sparkのメモリ設定① spark.{driver/executor}.memoryOverhead の値により積み増し(デフォルト0.1) spark.{driver/executor}.memory で設定した値 コンテナの Request/Limit に設定される値 Nodeにはこれを上回る 空きリソースが必要 JVMへ与えられるリソース (-Xms,-Xmxオプション両方に設定) JVM外に確保
  • 40.
    © 2021 NTTDATA Corporation 40 Sparkのメモリ設定② Sparkが利用するメモリ spark.memory.fractionで決定 (デフォルト0.6) ユーザーが利用するメモリ 1-spark.memory.fraction User Memory Spark Memory Reserved Memory Sparkの内部オブジェクト格納 300MiB ヒープメモリとして 一括で確保されるので、 JVMからメトリクス取得する しくみを導入しておくと チューニングにGood
  • 41.
    © 2021 NTTDATA Corporation 41 KubernetesのQuality of Service (QoS) Podのスケジューリングの際の優先順位 • BestEffort 優先度最低、まずこのQoSの設定のものから停止される Pod内のコンテナにRequest/Limitを設定しないとこのQoS • Burstable 優先度中 BestEffort、Guaranteed以外の設定でこのQoS • Guaranteed 優先度最高 Pod内のすべてのコンテナに、CPU、メモリ両方のRequestとLimitが設定され、かつ それぞれのRequest/Limitの値が同値
  • 42.
    © 2021 NTTDATA Corporation 42 デフォルトだとSparkは… 再掲 kubectl get pod spark-pi-5387257bab525975-exec-1 -o yaml … resources: limits: memory: 4505Mi requests: cpu: "2" memory: 4505Mi … CPU limitが設定されてい ないためBurstable
  • 43.
    © 2021 NTTDATA Corporation 43 QoSの変更 --conf spark.kubernetes.executor.request.cores=2 --conf spark.kubernetes.executor.limit.cores=2 CPU Request/Limitに ついて明示的に指定すると Guaranteedに ロギング/モニタリング等、他のPodとの優先順位を明確にしておくとGood (監視関連をGuaranteed、SparkはBurstableにして原因特定をしやすくするなど) … podIPs: - ip: 172.17.0.4 qosClass: Guaranteed startTime: "2021-09-06T05:17:23Z"
  • 44.
    © 2021 NTTDATA Corporation 44 その他のTips、注意事項など
  • 45.
    © 2021 NTTDATA Corporation 45 Web UIのみかた Driver Pod の4040番ポートへつなぐとSpark Web UIが確認可能 kubectl get pod kubectl port-forward ${DRIVER_POD_NAME} 4040:4040 Driver のPod名を確認 kubectl実行端末 ~ Driver のPodへのポートフォワード localhost:4040にて閲覧可能 kubectlをサーバー上で実施している場合は-- address=0.0.0.0オプション+サーバーのアドレス:4040にて 閲覧可能に
  • 46.
    © 2021 NTTDATA Corporation 46 ジョブの終了時 • Executor Podは実行後消滅 • Driver PodはCompletedの状態に • logの確認は可能 • port forwardは不可 詳細のトレースにはロギング/モニタリングの環境を設定しておく必要あり
  • 47.
    © 2021 NTTDATA Corporation 47 Clientモードの利用 Nodebookから対話的に操作したいときなど headless serviceを利用し Executor  Driverへのルート作成 Notebook兼 Driver apiVersion: v1 kind: Service metadata: name: spark-driver-headless spec: type: ClusterIP clusterIP: None ports: - name: "spark-driver" protocol: "TCP" port: 51810 targetPort: 51810 selector: app: notebook headless service 特定名のPodへのFQDNを提供 --conf spark.driver.host=spark-driver-headless.default.svc.cluster.local --conf spark.driver.port=51810
  • 48.
    © 2021 NTTDATA Corporation 48 ストレージに関する注意点 PodのYAMLを確認すると… spec: containers: ... volumeMounts: ... - mountPath: /var/data/spark-f4b00c83-08ac-4046-b6ba-0fc83c96c77b name: spark-local-dir-1 ... volumes: ... - emptyDir: {} name: spark-local-dir-1 デフォルトでemptyDirを 作成して、Podがマウントする
  • 49.
    © 2021 NTTDATA Corporation 49 emptyDir Podと同じライフサイクルの一時ディレクトリ • Podが作成されると同時に作成され、Podが消滅すると同時に消滅 • 同一Pod内のコンテナからマウントし参照可 • 記憶媒体はkubeletの存在するファイルシステムに依存(通常ディスク or SSD) 配置されたノードのストレージを利用
  • 50.
    © 2021 NTTDATA Corporation 50 SparkのLocal Strage シャッフルの際にあふれたデータの保管場所として利用 デフォルトだとemptyDirを利用するため、ノードのディスクを利用する形に • ノードのディスクに空き容量が必要になる • パフォーマンスのボトルネックとなる ことも Executor Pod Executor Pod JOINなどでの データ移動
  • 51.
    © 2021 NTTDATA Corporation 51 tmpfs の利用 emptyDirのバックエンドをtmpfsにし、RAMを利用することも可能 --conf spark.kubernetes.local.dirs.tmpfs=true - emptyDir: medium: Memory name: spark-local-dir-1 マニフェストにはこのように反映 メモリの使用量が上昇するため、Nodeの空きリソースや、 先述の memoryOverhead の値を確認しつつ調整する
  • 52.
    © 2021 NTTDATA Corporation 52 Spark on Kubernetes を利用した様々な広がり K8s Operator Custom Resource Definitionによるユーザー独自のリソース定義と、 それを管理するControllerを作成することで、よりK8sに沿ったアプリケーション 管理を可能にするしくみ) Sparkについてもいくつか実装が公開 Google Cloud Platform が公開しているものが有名 kubectl apply -f spark-pi.yaml YAMLでのデプロイや、 アプリケーション監視によるより細かな制御など
  • 53.
    © 2021 NTTDATA Corporation 53 まとめ(本日のトピック再掲) 分散処理ソフトウェアであるApache Sparkを、 コンテナオーケストレーションツールのKubernetesクラスタ上で動作させる方法について紹介 • Apach Spark on K8sの概要 についてまず触れ、最初につまづきがちな • コンテナのビルド方法 • メモリ関連の設定方法 について詳しく述べつつ、細かなTipsについて紹介
  • 54.
    © 2021 NTTDATA Corporation 54 まとめ(本日のトピック再掲) 分散処理ソフトウェアであるApache Sparkを、 コンテナオーケストレーションツールのKubernetesクラスタ上で動作させる方法について紹介 • Apach Spark on K8sの概要 についてまず触れ、最初につまづきがちな • コンテナのビルド方法 • メモリ関連の設定方法 について詳しく述べつつ、細かなTipsについて紹介 Happy K8s and Spark experiences !!
  • 55.
    © 2021 NTTDATA Corporation 本資料に記載されている会社名、商品名、又はサービス名は、各社の登録商標又は商標です。