Container Service for Kubernetes (ACK) クラスターでSparkジョブを実行すると、多数のログが生成され、異なるポッドに分散されます。 これにより、ログ管理が複雑になります。 Simple Log Serviceを使用して、ログを収集、処理、クエリ、分析、視覚化し、アラートを生成できます。 これにより、Sparkログを効率的に管理できます。 このトピックでは、Simple Log Serviceを使用してACKクラスターのSparkジョブのログを管理する方法について説明します。
前提条件
ack-spark-operatorコンポーネントがインストールされています。 詳細については、「手順1: ack-spark-operatorコンポーネントのインストール」をご参照ください。
Simple Log Serviceプロジェクトが作成されました。 詳細については、「プロジェクトの管理」をご参照ください。
Logtailコンポーネントがインストールされます。 詳細については、「ACKクラスターへのLogtailコンポーネントのインストール」をご参照ください。
手順の概要
このトピックでは、Sparkジョブによって生成されたシステムログとビジネスログを管理するSimple Log Serviceを設定する方法について説明します。
Sparkコンテナイメージのビルド: log4j JSONテンプレートレイアウトの依存関係を含むSparkコンテナイメージをビルドし、イメージをイメージリポジトリにプッシュします。
Log4j2ログの設定: Log4j2ログを設定するためのConfigMapを作成し、ログレベルをINFOに設定してから、ログ印刷形式をJSONLに設定します。
Logtail設定の作成: AliyunConfigリソースを作成します。 Simple Log Serviceは、指定されたLogstoreにLogtail設定を作成し、Sparkオペレーターを使用して送信されたSparkジョブのログを収集します。
サンプルSparkジョブを送信する: サンプルSparkジョブを作成して実行し、ポッドログ出力がJSONL形式であるかどうかを確認してから、特定のフィールドの意味を記述します。
Sparkログの照会と分析: Simple Log Serviceコンソールにログインし、指定された期間内にSparkジョブログを照会して分析します。
(オプション) 環境をクリアする: テストが完了したら、不要なSparkジョブとリソースを削除して、追加コストを防ぎます。
ステップ1: Sparkコンテナイメージのビルド
次のDockerfileを作成し、必要な依存関係をSparkのクラスパスに追加します。 この例では、Spark 3.5.3が使用されます。 イメージがビルドされたら、イメージをイメージリポジトリにプッシュします。 ログの収集と解析を容易にするため、ログはJSONL形式で出力されます。
ARG SPARK_IMAGE=<SPARK_IMAGE> # Replace <SPARK_IMAGE> with your Spark base image.
FROM ${SPARK_IMAGE}
# Add dependency for log4j-layout-template-json
ADD --chown=spark:spark --chmod=644 https://repo1.maven.org/maven2/org/apache/logging/log4j/log4j-layout-template-json/2.24.1/log4j-layout-template-json-2.24.1.jar ${SPARK_HOME}/jarsステップ2: Log4jログの設定
次の内容を使用して、spark-log-conf.yamlという名前のファイルを作成し、ログレベルをINFOに設定し、ログ印刷形式をJSONL形式に設定します。 標準化されたログ形式であるログテンプレートとしてElastic Common Schema (ECS) を使用します。 詳細については、「Log4jログの収集」をご参照ください。
apiVersion: v1
kind: ConfigMap
metadata:
name: spark-log-conf
namespace: default
data:
log4j2.properties: |
# Set everything to be logged to the console and file
rootLogger.level = info
rootLogger.appenderRefs = console, file
rootLogger.appenderRef.console.ref = STDOUT
rootLogger.appenderRef.file.ref = FileAppender
appender.console.name = STDOUT
appender.console.type = Console
appender.console.layout.type = JsonTemplateLayout
appender.console.layout.eventTemplateUri = classpath:EcsLayout.json
appender.file.name = FileAppender
appender.file.type = File
appender.file.fileName = /opt/spark/logs/spark.log
appender.file.layout.type = JsonTemplateLayout
appender.file.layout.eventTemplateUri = classpath:EcsLayout.json次のコマンドを実行して、ConfigMapを作成します。
kubectl apply -f spark-log-conf.yaml期待される出力:
configmap/spark-log-conf createdステップ3: Logtail設定の作成
次の内容を使用して、aliyun-log-config.yamlという名前のAliyunLogConfigマニフェストファイルを作成します。 <SLS_PROJECT> をSimple Log Serviceプロジェクトの名前に置き換え、<SLS_LOGSTORE> をSimple Log Service Logstoreの名前に置き換えます。 設定の詳細については、「AliyunLogConfigを使用したLogtail設定の管理」をご参照ください。
apiVersion: log.alibabacloud.com/v1alpha1
kind: AliyunLogConfig
metadata:
name: spark
namespace: default
spec:
# (Optional) The name of the project. Default value: k8s-log-<Your_Cluster_ID>.
project: <SLS_PROJECT>
# The name of the Logstore. If the Logstore that you specify does not exist, Simple Log Service automatically creates a Logstore.
logstore: <SLS_LOGSTORE>
# The Logtail configuration.
logtailConfig:
# The name of the Logtail configuration.
configName: spark
# The type of the data source. The value file specifies text logs.
inputType: file
# The configurations of the log input.
inputDetail:
# The directory in which the log file is located.
logPath: /opt/spark/logs
# The name of a log file. Wildcard characters are supported.
filePattern: '*.log'
# The encoding of the log file.
fileEncoding: utf8
# The log type.
logType: json_log
localStorage: true
key:
- content
logBeginRegex: .*
logTimezone: ''
discardNonUtf8: false
discardUnmatch: true
preserve: true
preserveDepth: 0
regex: (.*)
outputType: LogService
topicFormat: none
adjustTimezone: false
enableRawLog: false
# Collect text logs from containers.
dockerFile: true
# Advanced configurations.
advanced:
# Preview the container metadata.
collect_containers_flag: true
# Logtail configurations in Kubernetes.
k8s:
# Filter pods based on the tag.
IncludeK8sLabel:
sparkoperator.k8s.io/launched-by-spark-operator: "true"
# Filter containers based on the container name.
K8sContainerRegex: "^spark-kubernetes-(driver|executor)$"
# Additional log tag configurations.
ExternalK8sLabelTag:
spark-app-name: spark-app-name
spark-version: spark-version
spark-role: spark-role
spark-app-selector: spark-app-selector
sparkoperator.k8s.io/submission-id: sparkoperator.k8s.io/submission-id
# The log processing plug-in.
plugin:
processors:
# Log isolation.
- type: processor_split_log_string
detail:
SplitKey: content
SplitSep: ''
# Parse the JSON field.
- type: processor_json
detail:
ExpandArray: false
ExpandConnector: ''
ExpandDepth: 0
IgnoreFirstConnector: false
SourceKey: content
KeepSource: false
KeepSourceIfParseError: true
NoKeyError: false
UseSourceKeyAsPrefix: false
# Extract the log timestamp.
- type: processor_strptime
detail:
SourceKey: '@timestamp'
Format: '%Y-%m-%dT%H:%M:%S.%fZ'
KeepSource: false
AdjustUTCOffset: true
UTCOffset: 0
AlarmIfFail: false次のコマンドを実行してLogtail設定を作成します。
kubectl apply -f aliyun-log-config.yaml新しいLogstoreおよびLogtail設定を表示するには、次の手順を実行します。
にログインします。Simple Log Serviceコンソール.
[プロジェクト] セクションで、目的のプロジェクトをクリックします。

を選択します。 対象のLogtail設定の > アイコンをクリックします。 を選択します。

対象のLogtail設定をクリックして、設定の詳細を表示します。
ステップ4: サンプルSparkジョブを送信する
次のコンテンツを使用して、spark-pi.yamlという名前のSparkApplicationマニフェストファイルを作成します。
apiVersion: sparkoperator.k8s.io/v1beta2
kind: SparkApplication
metadata:
name: spark-pi
namespace: default
spec:
type: Scala
mode: cluster
image: <SPARK_IMAGE>
mainClass: org.apache.spark.examples.SparkPi
mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-3.5.3.jar
arguments:
- "5000"
sparkVersion: 3.5.3
sparkConfigMap: spark-log-conf
driver:
cores: 1
memory: 512m
serviceAccount: spark-operator-spark
executor:
instances: 1
cores: 1
memory: 4g次のコマンドを実行して、ジョブを送信します。
kubectl apply -f spark-pi.yamlジョブの実行が完了するまで待ち、ドライバポッドログの最後の10行を確認します。
kubectl logs --tail=10 spark-pi-driver 期待される出力:
{"@timestamp":"2024-11-20T11:45:48.487Z","ecs.version":"1.2.0","log.level":"WARN","message":"Kubernetes client has been closed.","process.thread.name":"-937428334-pool-19-thread-1","log.logger":"org.apache.spark.scheduler.cluster.k8s.ExecutorPodsWatchSnapshotSource"}
{"@timestamp":"2024-11-20T11:45:48.585Z","ecs.version":"1.2.0","log.level":"INFO","message":"MapOutputTrackerMasterEndpoint stopped!","process.thread.name":"dispatcher-event-loop-7","log.logger":"org.apache.spark.MapOutputTrackerMasterEndpoint"}
{"@timestamp":"2024-11-20T11:45:48.592Z","ecs.version":"1.2.0","log.level":"INFO","message":"MemoryStore cleared","process.thread.name":"main","log.logger":"org.apache.spark.storage.memory.MemoryStore"}
{"@timestamp":"2024-11-20T11:45:48.592Z","ecs.version":"1.2.0","log.level":"INFO","message":"BlockManager stopped","process.thread.name":"main","log.logger":"org.apache.spark.storage.BlockManager"}
{"@timestamp":"2024-11-20T11:45:48.596Z","ecs.version":"1.2.0","log.level":"INFO","message":"BlockManagerMaster stopped","process.thread.name":"main","log.logger":"org.apache.spark.storage.BlockManagerMaster"}
{"@timestamp":"2024-11-20T11:45:48.598Z","ecs.version":"1.2.0","log.level":"INFO","message":"OutputCommitCoordinator stopped!","process.thread.name":"dispatcher-event-loop-1","log.logger":"org.apache.spark.scheduler.OutputCommitCoordinator$OutputCommitCoordinatorEndpoint"}
{"@timestamp":"2024-11-20T11:45:48.602Z","ecs.version":"1.2.0","log.level":"INFO","message":"Successfully stopped SparkContext","process.thread.name":"main","log.logger":"org.apache.spark.SparkContext"}
{"@timestamp":"2024-11-20T11:45:48.604Z","ecs.version":"1.2.0","log.level":"INFO","message":"Shutdown hook called","process.thread.name":"shutdown-hook-0","log.logger":"org.apache.spark.util.ShutdownHookManager"}
{"@timestamp":"2024-11-20T11:45:48.604Z","ecs.version":"1.2.0","log.level":"INFO","message":"Deleting directory /var/data/spark-f783cf2e-44db-452c-83c9-738f9c894ef9/spark-2caa5814-bd32-431c-a9f9-a32208b34fbb","process.thread.name":"shutdown-hook-0","log.logger":"org.apache.spark.util.ShutdownHookManager"}
{"@timestamp":"2024-11-20T11:45:48.606Z","ecs.version":"1.2.0","log.level":"INFO","message":"Deleting directory /tmp/spark-dacdfd95-f166-4b23-9312-af9052730417","process.thread.name":"shutdown-hook-0","log.logger":"org.apache.spark.util.ShutdownHookManager"}出力されたログはJSONL形式で出力されます。 次のセクションでは、各フィールドの意味について説明します。
@ timestamp: ログが生成された時刻。ecs.version: ECSのバージョン番号。log.level: ログのレベル。message: ログメッセージ。process.thread.name: ログを生成するスレッドの名前。log.logger: ログを記録するロガーの名前。
ステップ5: Sparkログの照会と分析
ログの照会と分析を行って、ジョブ実行の時間範囲を指定し、ログが収集されているかどうかを確認できます。

(オプション) ステップ6: 環境をクリアする
このトピックのすべての手順を実行したら、次のコマンドを実行してSparkジョブを削除し、不要になったリソースを解放します。
次のコマンドを実行して、Sparkジョブを削除します。
kubectl delete -f spark-pi.yaml次のコマンドを実行して、Logtail設定を削除します。
kubectl delete -f aliyun-log-config.yaml次のコマンドを実行して、Log4j2ログ設定を削除します。
kubectl delete -f spark-log-conf.yaml