All Products
Search
Document Center

Container Service for Kubernetes:Gunakan Simple Log Service untuk mengumpulkan log pekerjaan Spark

Last Updated:Mar 26, 2026

Pekerjaan Spark yang berjalan di kluster Container Service for Kubernetes (ACK) menghasilkan log yang tersebar di banyak Pod, sehingga menyulitkan manajemen log terpusat. Dengan mengintegrasikan Simple Log Service (SLS), Anda dapat:

  • Mengumpulkan log terstruktur dari semua Pod driver dan executor Spark secara otomatis.

  • Menjalankan kueri dan menganalisis log pekerjaan Spark dalam rentang waktu tertentu.

  • Menyaring log berdasarkan nama aplikasi, versi, role, dan submission ID.

Topik ini menjelaskan cara mengonfigurasi seluruh pipeline pengumpulan log: membangun gambar kontainer Spark dengan dukungan pencatatan terstruktur, men-deploy konfigurasi Logtail untuk mengumpulkan log Pod, serta menjalankan kueri terhadap hasilnya di Simple Log Service.

Prasyarat

Sebelum memulai, pastikan Anda telah:

Cara kerja

Pipeline ini bekerja sebagai berikut:

  1. Gambar kontainer Spark kustom menambahkan pustaka tata letak templat JSON Log4j2, sehingga mengaktifkan output JSONL terstruktur.

  2. ConfigMap mengonfigurasi Log4j2 untuk menulis log dalam format JSONL menggunakan templat Elastic Common Schema (ECS), baik ke stdout maupun ke file di /opt/spark/logs/spark.log.

  3. Konfigurasi Logtail (AliyunLogConfig) memberi tahu Simple Log Service untuk mengumpulkan log dari kontainer yang sesuai dengan label Pod Spark Operator dan pola nama kontainer, lalu mengurai bidang JSONL serta mengekstraksi timestamp.

  4. Setelah pekerjaan Spark berjalan, log-nya tersedia di penyimpanan log (Logstore) yang ditentukan untuk kueri dan analisis.

Langkah 1: Bangun gambar kontainer Spark

Buat Dockerfile berikut. Contoh ini menggunakan Spark 3.5.3 dan menambahkan dependensi log4j-layout-template-json ke classpath Spark, yang memungkinkan output JSONL melalui appender JsonTemplateLayout.

ARG SPARK_IMAGE=<SPARK_IMAGE>  # Ganti <SPARK_IMAGE> dengan gambar dasar Spark Anda.

FROM ${SPARK_IMAGE}

# Tambahkan dependensi untuk 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

Bangun dan dorong gambar ke registri Anda:

docker build -t <your-registry>/<your-image-name>:<tag> .
docker push <your-registry>/<your-image-name>:<tag>

Ganti placeholder dengan detail registri dan gambar aktual Anda.

Langkah 2: Konfigurasi log Log4j2

Buat file bernama spark-log-conf.yaml dengan konten berikut. ConfigMap ini mengatur tingkat log ke INFO dan mengonfigurasi appender konsol serta file agar menghasilkan log dalam format JSONL menggunakan templat ECS. Untuk informasi lebih lanjut, lihat Collect Log4j logs.

apiVersion: v1
kind: ConfigMap
metadata:
  name: spark-log-conf
  namespace: default
data:
  log4j2.properties: |
    # Atur semua hal untuk dicatat ke konsol dan 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

Terapkan ConfigMap:

kubectl apply -f spark-log-conf.yaml

Output yang diharapkan:

configmap/spark-log-conf created

Langkah 3: Buat konfigurasi Logtail

Buat file bernama aliyun-log-config.yaml dengan konten berikut. Ganti <SLS_PROJECT> dengan nama proyek Simple Log Service Anda dan <SLS_LOGSTORE> dengan nama Logstore Anda. Jika Logstore belum ada, Simple Log Service akan membuatnya secara otomatis.

Konfigurasi ini menyaring Pod yang diluncurkan oleh Spark Operator menggunakan label sparkoperator.k8s.io/launched-by-spark-operator: "true", yang secara otomatis ditetapkan oleh Spark Operator pada semua Pod driver dan executor. Log dikumpulkan dari /opt/spark/logs, diurai sebagai JSON, dan bidang @timestamp diekstraksi sebagai waktu log. Untuk informasi lebih lanjut tentang bidang AliyunLogConfig, lihat Use AliyunLogConfig to manage a Logtail configuration.

apiVersion: log.alibabacloud.com/v1alpha1
kind: AliyunLogConfig
metadata:
  name: spark
  namespace: default
spec:
  # (Opsional) Nama proyek. Nilai default: k8s-log-<Your_Cluster_ID>.
  project: <SLS_PROJECT>

  # Nama Logstore. Jika Logstore yang Anda tentukan belum ada, Simple Log Service akan membuat Logstore secara otomatis.
  logstore: <SLS_LOGSTORE>

  # Konfigurasi Logtail.
  logtailConfig:
    # Nama konfigurasi Logtail.
    configName: spark

    # Jenis sumber data. Nilai file menentukan log teks.
    inputType: file

    # Konfigurasi input log.
    inputDetail:
      # Direktori tempat file log berada.
      logPath: /opt/spark/logs

      # Nama file log. Karakter wildcard didukung.
      filePattern: '*.log'

      # Pengkodean file log.
      fileEncoding: utf8

      # Tipe log.
      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

      # Kumpulkan log teks dari kontainer.
      dockerFile: true

      # Konfigurasi lanjutan.
      advanced:
        # Pratinjau metadata kontainer.
        collect_containers_flag: true

        # Konfigurasi Logtail di Kubernetes.
        k8s:
          # Saring Pod berdasarkan label.
          IncludeK8sLabel:
            sparkoperator.k8s.io/launched-by-spark-operator: "true"

          # Saring kontainer berdasarkan nama kontainer.
          K8sContainerRegex: "^spark-kubernetes-(driver|executor)$"

          # Konfigurasi tag log tambahan.
          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

      # Plugin pemrosesan log.
      plugin:
        processors:
        # Isolasi log.
        - type: processor_split_log_string
          detail:
            SplitKey: content
            SplitSep: ''

        # Urai bidang JSON.
        - type: processor_json
          detail:
            ExpandArray: false
            ExpandConnector: ''
            ExpandDepth: 0
            IgnoreFirstConnector: false
            SourceKey: content
            KeepSource: false
            KeepSourceIfParseError: true
            NoKeyError: false
            UseSourceKeyAsPrefix: false

        # Ekstraksi timestamp log.
        - type: processor_strptime
          detail:
            SourceKey: '@timestamp'
            Format: '%Y-%m-%dT%H:%M:%S.%fZ'
            KeepSource: false
            AdjustUTCOffset: true
            UTCOffset: 0
            AlarmIfFail: false

Terapkan konfigurasi:

kubectl apply -f aliyun-log-config.yaml

Untuk memverifikasi bahwa Logstore dan konfigurasi Logtail telah dibuat:

  1. Login ke Simple Log Service console.

  2. Pada bagian Projects, klik proyek Anda.

    image

  3. Pilih Log Storage \> Logstores. Klik ikon \> di sebelah Logstore target. Pilih Data Import \> Logtail Configurations.

    image

  4. Klik konfigurasi Logtail untuk melihat detailnya.

Langkah 4: Kirim pekerjaan Spark contoh

Buat file bernama spark-pi.yaml dengan konten berikut. Bidang sparkConfigMap mereferensikan ConfigMap yang dibuat pada Langkah 2, yang menyuntikkan konfigurasi Log4j2 ke dalam Pod Spark.

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

Kirim pekerjaan:

kubectl apply -f spark-pi.yaml

Setelah pekerjaan selesai, periksa 10 baris terakhir log Pod driver untuk memastikan output JSONL:

kubectl logs --tail=10 spark-pi-driver

Output yang diharapkan:

{"@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"}

Setiap entri log JSONL berisi bidang-bidang berikut:

FieldDescription
@timestampWaktu saat log dihasilkan
ecs.versionVersi ECS (Elastic Common Schema)
log.levelTingkat log, seperti INFO atau WARN
messagePesan log
process.thread.nameNama thread yang menghasilkan log
log.loggerNama logger yang mencatat log

Langkah 5: Verifikasi pengumpulan log

Setelah pekerjaan Spark selesai, pastikan log telah sampai ke Logstore Anda sebelum menggunakannya untuk analisis.

Login ke Simple Log Service console dan buka proyek Anda. Di Logstore, atur rentang waktu yang mencakup jendela eksekusi pekerjaan dan jalankan kueri. Anda seharusnya melihat entri dalam format JSONL dengan bidang ECS seperti yang dijelaskan di atas.

image

Jika tidak ada log yang muncul, periksa:

  • Konfigurasi Logtail aktif dan nama Logstore sesuai dengan <SLS_LOGSTORE> dalam AliyunLogConfig Anda.

  • Pod Spark memiliki label sparkoperator.k8s.io/launched-by-spark-operator: "true" (ditetapkan secara otomatis oleh Spark Operator).

  • File log ada di /opt/spark/logs/spark.log di dalam Pod driver atau executor.

Langkah 6: Jalankan kueri dan analisis log Spark

Dengan log yang mengalir ke Simple Log Service, gunakan fitur query and analysis untuk menyaring dan mengagregasi log pekerjaan Spark berdasarkan rentang waktu, tingkat log, nama aplikasi, atau role Spark (driver vs. executor).

(Opsional) Langkah 7: Bersihkan

Setelah pengujian, hapus sumber daya untuk menghindari biaya yang tidak perlu.

Hapus pekerjaan Spark:

kubectl delete -f spark-pi.yaml

Hapus konfigurasi Logtail:

kubectl delete -f aliyun-log-config.yaml

Hapus ConfigMap Log4j2:

kubectl delete -f spark-log-conf.yaml