Kubernetes クラスター内の ECI で Spark ジョブを実行すると、自動スケーリング、自動デプロイ、高可用性が実現し、効率と安定性が向上します。ACK Serverless クラスターに Spark Operator をインストールして、ECI 上で Spark ジョブを実行および管理します。
背景情報
Apache Spark は、データ分析で広く使用されているオープンソースプロジェクトです。ビッグデータと機械学習のワークロードに使用されます。Apache Spark 2.3.0 以降、Kubernetes 上で Spark リソースを実行および管理できるようになりました。
Spark on Kubernetes 向けに設計された Spark Operator を使用すると、カスタムリソース定義 (CRD) として定義することで、Kubernetes クラスターに Spark ジョブを送信できます。Spark Operator には、次の利点があります。
-
Kubernetes に対するネイティブ Spark サポートの制限を克服します。
-
ストレージ、モニタリング、ログなど、Kubernetes エコシステム内のコンポーネントと迅速に統合できます。
-
障害復旧、オートスケーリング、スケジューリング最適化などの高度な Kubernetes 機能をサポートします。
前提条件
-
ACK Serverless クラスターを作成します。
ACKコンソールでACKサーバーレスクラスターを作成します。 詳細については、「ACKサーバーレスクラスターの作成」をご参照ください。
重要インターネット経由でイメージを取得する必要がある場合、またはトレーニングジョブがインターネットにアクセスする必要がある場合は、インターネットNATゲートウェイを設定する必要があります。
kubectlと次のいずれかの方法を使用して、ACKサーバーレスクラスターを管理およびアクセスできます。
オンプレミスマシンからクラスターを管理する場合は、kubectlクライアントをインストールして設定します。 詳細については、「kubeconfig ファイルの取得と kubectl によるクラスターへの接続」をご参照ください。
kubectlを使用して、Cloud Shell上のACKサーバーレスクラスターを管理します。 詳細については、「kubectlを使用したCloud ShellでのACKクラスターの管理」をご参照ください。
-
OSS バケットの作成
テストデータ、テスト結果、およびログを格納するために、OSS バケットを作成する必要があります。詳細については、「バケットの作成」をご参照ください。
Spark Operator のインストール
-
Spark Operator をインストールします。
-
ACK コンソールの左側のナビゲーションペインで、ストア > Marketplace を選択します。
-
アプリカタログ タブで、[ack-spark-operator] を見つけてクリックします。
-
右上隅で、デプロイ をクリックします。
-
表示されるパネルで、ターゲットクラスターを選択し、プロンプトに従って設定を完了します。
-
-
ServiceAccount、Role、RoleBinding を作成します。
Spark ジョブには、Pod を作成する権限を持つ ServiceAccount が必要です。次の YAML マニフェストを使用して、ServiceAccount、Role、RoleBinding を作成します。必要に応じて namespace を変更してください。
apiVersion: v1 kind: ServiceAccount metadata: name: spark namespace: default --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: spark-role rules: - apiGroups: [""] resources: ["pods"] verbs: ["*"] - apiGroups: [""] resources: ["services"] verbs: ["*"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: spark-role-binding namespace: default subjects: - kind: ServiceAccount name: spark namespace: default roleRef: kind: Role name: spark-role apiGroup: rbac.authorization.k8s.io
Spark ジョブイメージの構築
Spark ジョブの JAR パッケージをコンパイルし、Dockerfile を使用してイメージにパッケージ化します。
次の Dockerfile は、Alibaba Cloud Container Service が提供するベース Spark イメージに基づいています。
FROM registry.aliyuncs.com/acs/spark:ack-2.4.5-latest
RUN mkdir -p /opt/spark/jars
# OSS を使用する必要がある場合 (例: OSS からデータを読み取る、または OSS にイベントを書き込む)、次の JAR パッケージをイメージに追加します。
ADD https://repo1.maven.org/maven2/com/aliyun/odps/hadoop-fs-oss/3.3.8-public/hadoop-fs-oss-3.3.8-public.jar $SPARK_HOME/jars
ADD https://repo1.maven.org/maven2/com/aliyun/oss/aliyun-sdk-oss/3.8.1/aliyun-sdk-oss-3.8.1.jar $SPARK_HOME/jars
ADD https://repo1.maven.org/maven2/org/aspectj/aspectjweaver/1.9.5/aspectjweaver-1.9.5.jar $SPARK_HOME/jars
ADD https://repo1.maven.org/maven2/org/jdom/jdom/1.1.3/jdom-1.1.3.jar $SPARK_HOME/jars
COPY SparkExampleScala-assembly-0.1.jar /opt/spark/jars
大規模な Spark イメージのプルには時間がかかる場合があります。ImageCache を使用すると、イメージのプルを高速化できます。詳細については、「ImageCache の管理」および「ImageCache を使用した pod 作成の高速化」をご参照ください。
Alibaba Cloud は、Kubernetes のスケジューリングと弾力性に最適化された Spark 2.4.5 のベースイメージを提供しており、スケジューリングと起動の速度が大幅に向上します。この最適化を有効にするには、Helm チャートで enableAlibabaCloudFeatureGates: true 変数を設定します。さらに高速な起動を実現するには、enableWebhook: false を設定します。
operatorImageName: registry.aliyuncs.com/acs/spark-operator
operatorImageVersion: ack-2.4.5-latest
operatorVersion: v2.4.5-v1beta2
imagePullPolicy: IfNotPresent
rbac:
create: true
serviceAccounts:
spark:
create: true
name: spark
sparkoperator:
create: true
name: ack-spark-operator
sparkJobNamespace: "default"
enableWebhook: false
enableMetrics: true
enableAlibabaCloudFeatureGates: true
ジョブマニフェストの作成と送信
Spark ジョブの YAML 設定ファイルを作成してデプロイします。
-
spark-pi.yaml ファイルを作成します。
以下はジョブマニフェストの例です。詳細については、「spark-on-k8s-operator」をご参照ください。
apiVersion: "sparkoperator.k8s.io/v1beta2" kind: SparkApplication metadata: name: spark-pi namespace: default spec: type: Scala mode: cluster image: "registry.aliyuncs.com/acs/spark:ack-2.4.5-latest" imagePullPolicy: Always mainClass: org.apache.spark.examples.SparkPi mainApplicationFile: "local:///opt/spark/examples/jars/spark-examples_2.11-2.4.5.jar" sparkVersion: "2.4.5" restartPolicy: type: Never driver: cores: 2 coreLimit: "2" memory: "3g" memoryOverhead: "1g" labels: version: 2.4.5 serviceAccount: spark annotations: k8s.aliyun.com/eci-kube-proxy-enabled: 'true' k8s.aliyun.com/eci-auto-imc: "true" tolerations: - key: "virtual-kubelet.io/provider" operator: "Exists" executor: cores: 2 instances: 1 memory: "3g" memoryOverhead: "1g" labels: version: 2.4.5 annotations: k8s.aliyun.com/eci-kube-proxy-enabled: 'true' k8s.aliyun.com/eci-auto-imc: "true" tolerations: - key: "virtual-kubelet.io/provider" operator: "Exists" -
Spark コンピューティングジョブをデプロイします。
kubectl apply -f spark-pi.yaml
ログ収集の設定
Spark ドライバーとエグゼキューターから標準出力ログを収集するには、環境変数をそれらの envVars フィールドに挿入します。詳細については、「ECI のログ収集をカスタマイズする」をご参照ください。
envVars:
aliyun_logs_test-stdout_project: test-k8s-spark
aliyun_logs_test-stdout_machinegroup: k8s-group-app-spark
aliyun_logs_test-stdout: stdout
ジョブを送信する際に、ドライバーとエグゼキューターにこれらの環境変数を設定します。設定後、Log Service コンソールの対応するプロジェクトの [生ログ] タブで、収集されたログを表示できます。ログエントリには、__source__、__tag__:__hostname__、__tag__:__path__、__tag__:__user_defined_id__、__tag__:eci_id などのフィールドに加え、content フィールドにログの内容が含まれます。
ヒストリーサーバーの設定
ヒストリーサーバーは、Spark ジョブを追跡および監査します。SparkApplication CRD に SparkConf フィールドを追加して、イベントを OSS に書き込みます。ヒストリーサーバーは、これらのイベントを読み取ってジョブ情報を表示します。設定例:
sparkConf:
"spark.eventLog.enabled": "true"
"spark.eventLog.dir": "oss://bigdatastore/spark-events"
"spark.hadoop.fs.oss.impl": "org.apache.hadoop.fs.aliyun.oss.AliyunOSSFileSystem"
# OSS バケットエンドポイント (例: oss-cn-beijing.aliyuncs.com)
"spark.hadoop.fs.oss.endpoint": "oss-cn-beijing.aliyuncs.com"
"spark.hadoop.fs.oss.accessKeySecret": ""
"spark.hadoop.fs.oss.accessKeyId": ""
Alibaba Cloud は、spark-history-server Helm チャートも提供しています。ACK コンソールの ストア > Marketplace ページで ack-spark-history-server を検索してインストールします。インストール時に、値 セクションで OSS 関連情報を設定します。例:
oss:
enableOSS: true
# accessKeyId を入力してください
alibabaCloudAccessKeyId: ""
# accessKeySecret を入力してください
alibabaCloudAccessKeySecret: ""
# OSS バケットエンドポイント (例: oss-cn-beijing.aliyuncs.com)
alibabaCloudOSSEndpoint: "oss-cn-beijing.aliyuncs.com"
# OSS ファイルパス (例: oss://bucket-name/path)
eventsDir: "oss://bigdatastore/spark-events"
インストール後、クラスター詳細ページの [サービス] で ack-spark-history-server の外部エンドポイントを見つけます。このエンドポイントにアクセスして、アーカイブされたジョブを表示します。Spark History Server ページには、完了した Spark アプリケーションが、[App ID]、[App Name]、[Started]、[Completed]、[Duration]、[Spark User]、[Last Updated]、[Event Log] などの列で表示されます。イベントログをダウンロードするには、対応する行の [Download] をクリックします。
ジョブ結果の表示
-
Pod の実行ステータスを確認します。
kubectl get pods出力例:
NAME READY STATUS RESTARTS AGE spark-pi-1547981232122-driver 1/1 Running 0 12s spark-pi-1547981232122-exec-1 1/1 Running 0 3s -
リアルタイム Spark UI を表示します。
kubectl port-forward spark-pi-1547981232122-driver 4040:4040 -
SparkApplication のステータスを確認します。
kubectl describe sparkapplication spark-pi出力例:
Name: spark-pi Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"sparkoperator.k8s.io/v1beta2","kind":"SparkApplication","metadata":{"annotations":{},"name":"spark-pi","namespace":"default"...}} API Version: sparkoperator.k8s.io/v1beta2 Kind: SparkApplication Metadata: Creation Timestamp: 2019-01-20T10:47:08Z Generation: 1 Resource Version: 4923532 Self Link: /apis/sparkoperator.k8s.io/v1beta2/namespaces/default/sparkapplications/spark-pi UID: bbe7445c-1ca0-11e9-9ad4-062fd7c19a7b Spec: Type: Scala Mode: cluster Image: registry.aliyuncs.com/acs/spark:ack-2.4.5-latest Image Pull Policy: Always Main Class: org.apache.spark.examples.SparkPi Main Application File: local:///opt/spark/examples/jars/spark-examples_2.11-2.4.5.jar Spark Version: 2.4.5 Restart Policy: Type: Never Driver: Cores: 2 Core Limit: 2 Memory: 3g Memory Overhead: 1g Labels: Version: 2.4.5 Service Account: spark Annotations: k8s.aliyun.com/eci-auto-imc: true k8s.aliyun.com/eci-kube-proxy-enabled: true Tolerations: Key: virtual-kubelet.io/provider Operator: Exists Executor: Instances: 1 Cores: 2 Memory: 3g Memory Overhead: 1g Labels: Version: 2.4.5 Annotations: k8s.aliyun.com/eci-auto-imc: true k8s.aliyun.com/eci-kube-proxy-enabled: true Tolerations: Key: virtual-kubelet.io/provider Operator: Exists Status: Application State: Error Message: State: COMPLETED Driver Info: Pod Name: spark-pi-1547981232122-driver Web UI Port: 31182 Web UI Service Name: spark-pi-ui-svc Execution Attempts: 1 Executor State: spark-pi-1547981232122-exec-1: COMPLETED Last Submission Attempt Time: 2019-01-20T10:47:14Z Spark Application Id: spark-application-1547981285779 Submission Attempts: 1 Termination Time: 2019-01-20T10:48:56Z Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SparkApplicationAdded 55m spark-operator SparkApplication spark-pi was added, Enqueuing it for submission Normal SparkApplicationSubmitted 55m spark-operator SparkApplication spark-pi was submitted successfully Normal SparkDriverPending 55m (x2 over 55m) spark-operator Driver spark-pi-driver is pending Normal SparkExecutorPending 54m (x3 over 54m) spark-operator Executor spark-pi-1547981232122-exec-1 is pending Normal SparkExecutorRunning 53m (x4 over 54m) spark-operator Executor spark-pi-1547981232122-exec-1 is running Normal SparkDriverRunning 53m (x12 over 55m) spark-operator Driver spark-pi-driver is running Normal SparkExecutorCompleted 53m (x2 over 53m) spark-operator Executor spark-pi-1547981232122-exec-1 completed -
ログを表示して結果を確認します。
NAME READY STATUS RESTARTS AGE spark-pi-1547981232122-driver 0/1 Completed 0 1mSparkApplication のステータスが
COMPLETED、または Spark ドライバー Pod のステータスがCompletedの場合、ログを表示して結果を確認します。kubectl logs spark-pi-1547981232122-driver Pi is roughly 3.152155760778804