Запуск задач Spark в Kubernetes с любого хоста с использованием CLI

В данной статье показано, как установить оператор Spark для Kubernetes и как запустить Spark-приложение в Kubernetes с помощью Arenadata Cloud CLI.

Требования

Для запуска приложений Spark в Kubernetes с помощью Arenadata Cloud CLI необходимы:

  • Кластер Kubernetes (версии 1.32 или более поздней) с настроенным доступом через kubectl.

  • CLI-утилита, извлеченная из offline-пакета.

  • HDFS и Hive Metastore, доступные из целевого пространства имен (необходимо, только если приложение обращается к данным, управляемым этими сервисами).

  • Файл с задачей (JAR или .py), доступный в подах Spark (локальный путь внутри образа или URI в HDFS/S3).

  • Извлеченные и загруженные в ваш репозиторий образы:

    • hub.arenadata.io/adc-enterprise/spark-operator:<version>

    • hub.arenadata.io/adh-enterprise/spark3-docker:<version> или hub.arenadata.io/adh-enterprise/spark4-docker:<version>

    Эти артефакты присутствуют в offline-пакете, который можно запросить у службы поддержки Arenadata.

Шаг 1. Установка оператора Spark

  1. Инициализируйте оператор Spark:

    $ ./adc init --spark-operator -o spark-operator.yaml

    Данная команда создаст файл spark-operator.yaml с шаблоном конфигурации.

  2. Отредактируйте конфигурационный файл:

    spark-operator.yaml
    apiVersion: adc.arenadata.io/v1alpha1
    kind: SparkOperator
    metadata:
      name: spark-operator
      namespace: spark-operator (1)
    spec:
      image: hub.arenadata.io/adc-enterprise/spark-operator:<tag> (2)
    
      # Number of replicas
      # replicas: 1
    
      resources:
        limits:
          cpu: 500m
          memory: 256Mi
    
      # Operator ServiceAccount. create: true (default) also creates the manager and per-payload-namespace Role/RoleBinding bound to it; create: false skips all three - name then refers to a ServiceAccount (and RBAC) managed entirely outside the CLI.
      serviceAccount: (3)
        create: true
        name: "spark-operator"
    
      # Whether the CLI creates the product namespace.
      # The namespace name is set in metadata.namespace.
      namespace:
        create: true
    
      # Create namespaces to run the payload.
      createPayloadNamespaces: true
    
      # List of namespaces to run the payload in.
      payloadNamespaces: (4)
        - spark-applications
    
      ## Image pull secret for a private registry.
      ## Set 'externalSecretName' to reference an existing Secret,
      ## or set 'credentials' and optionally 'secretName' to let the CLI create one.
      #imagePullSecret:
      #  # Use a Secret managed outside ADC.
      #  externalSecretName: existing-registry-secret
      #
      #  ## Or let ADC create the Secret.
      #  #secretName: custom-registry-secret
      #
      #  #credentials:
      #  #  registry: registry.example.com
      #  #  username: user
      #  #  password: pass
    
      ## Operator monitoring configuration. Supports product-specific metrics export and optional vmagent delivery to an external ADM.
      #monitoring:
      #  # Renders a namespace-scoped vmagent that sends metrics to an external ADM.
      #  vmagent:
      #    remoteWrite:
      #      url: http://vminsert.example.com/insert/0/prometheus/api/v1/write
      #    scrapeInterval: 15s
      #    image: hub.arenadata.io/adm-enterprise/vmagent:1.136.0-adm-5.0.0-x86_64
      #
      #    ## HTTPS settings used by vmagent when scraping product metrics.
      #    #tls:
      #    #  ## CA certificate source used to verify the metrics endpoint.
      #    #  #ca:
      #    #  #  # Use a Secret managed outside ADC.
      #    #  #  externalSecretName: existing-product-metrics-ca
      #    #  #
      #    #  #  ## Or let ADC create the Secret.
      #    #  #  #secretName: product-metrics-ca
      #    #  #
      #    #  #  # Key containing the CA certificate in the referenced Secret.
      #    #  #  certificateKey: ca.crt
      #    #  #
      #    #  #  ## Local CA certificate read by ADC to create the configured Secret.
      #    #  #  #files:
      #    #  #  #  certificatePath: /path/to/ca.crt
      #    #
      #    #  ## Server name used to verify the metrics endpoint certificate hostname.
      #    #  #serverName: metrics.example.com
      #    #
      #    #  # Skip verification of the metrics endpoint certificate. Do not use together with ca.
      #    #  insecureSkipVerify: true
    1 Настройки пространства имен.
    2 URL образа оператора Spark в вашем репозитории.
    3 Настройки сервисного аккаунта.
    4 Список пространств имен, доступных оператору Spark.
  3. Вы можете проверить конфигурацию перед ее применением, выполнив команду apply с флагом --dry-run:

    $ ./adc apply -f spark-operator.yaml --dry-run > spark-operator-render.yaml
    spark-operator-render.yaml
    ---
    apiVersion: v1
    kind: Namespace
    metadata:
      name: spark-operator
    spec: {}
    status: {}
    ---
    apiVersion: v1
    kind: Namespace
    metadata:
      name: spark-applications
    spec: {}
    status: {}
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: spark-operator
      namespace: spark-operator
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: spark-operator-spark-operator-manager
      namespace: spark-operator
    rules:
    - apiGroups:
      - events.k8s.io
      resources:
      - events
      verbs:
      - create
      - patch
    - apiGroups:
      - coordination.k8s.io
      resources:
      - leases
      verbs:
      - create
      - delete
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkapplications
      verbs:
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkapplications/status
      verbs:
      - get
      - patch
      - update
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkapplications/finalizers
      verbs:
      - update
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkhistoryservers
      verbs:
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkhistoryservers/status
      verbs:
      - get
      - patch
      - update
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkhistoryservers/finalizers
      verbs:
      - update
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkapplications
      verbs:
      - delete
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: spark-operator-spark-operator-manager
      namespace: spark-operator
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: spark-operator-spark-operator-manager
    subjects:
    - kind: ServiceAccount
      name: spark-operator
      namespace: spark-operator
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: spark-operator-spark-operator-payload
      namespace: spark-applications
    rules:
    - apiGroups:
      - events.k8s.io
      resources:
      - events
      verbs:
      - create
      - patch
    - apiGroups:
      - ""
      resources:
      - configmaps
      - services
      - pods
      - secrets
      verbs:
      - create
      - delete
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - apps
      resources:
      - statefulsets
      verbs:
      - create
      - delete
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - batch
      resources:
      - jobs
      verbs:
      - create
      - delete
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkapplications
      verbs:
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkapplications/status
      verbs:
      - get
      - patch
      - update
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkapplications/finalizers
      verbs:
      - update
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkhistoryservers
      verbs:
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkhistoryservers/status
      verbs:
      - get
      - patch
      - update
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkhistoryservers/finalizers
      verbs:
      - update
    - apiGroups:
      - spark.arenadata.io
      resources:
      - sparkapplications
      verbs:
      - delete
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: spark-operator-spark-operator-payload
      namespace: spark-applications
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: spark-operator-spark-operator-payload
    subjects:
    - kind: ServiceAccount
      name: spark-operator
      namespace: spark-operator
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app.kubernetes.io/component: operator
        app.kubernetes.io/managed-by: adc-cli
        arenadata.io/operator-type: spark
      name: spark-operator-spark-operator
      namespace: spark-operator
    spec:
      selector:
        matchLabels:
          app.kubernetes.io/component: operator
          app.kubernetes.io/managed-by: adc-cli
          app.kubernetes.io/name: spark-operator-spark-operator
      strategy: {}
      template:
        metadata:
          labels:
            app.kubernetes.io/component: operator
            app.kubernetes.io/managed-by: adc-cli
            app.kubernetes.io/name: spark-operator-spark-operator
        spec:
          containers:
          - args:
            - -ns=spark-applications
            image: hub.arenadata.io/adc-enterprise/spark-operator:<tag>
            imagePullPolicy: Always
            livenessProbe:
              httpGet:
                path: /healthz
                port: 8081
              initialDelaySeconds: 5
              periodSeconds: 10
            name: app
            readinessProbe:
              httpGet:
                path: /readyz
                port: 8081
              initialDelaySeconds: 5
              periodSeconds: 10
            resources:
              limits:
                cpu: 500m
                memory: 256Mi
              requests:
                cpu: 500m
                memory: 256Mi
            securityContext:
              allowPrivilegeEscalation: false
              capabilities:
                drop:
                - ALL
              readOnlyRootFilesystem: true
              runAsGroup: 10001
              runAsNonRoot: true
              runAsUser: 10001
          securityContext:
            fsGroup: 10001
            runAsGroup: 10001
            runAsNonRoot: true
            runAsUser: 10001
          serviceAccountName: spark-operator
          terminationGracePeriodSeconds: 10
    status: {}
  4. Если манифест корректный, примените конфигурацию и разверните оператор Spark:

    $ ./adc apply -f spark-operator.yaml

    Ожидаемый вывод содержит сообщение с подтверждением успеха:

    time="20260817083231UTC" level="info" msg="operator spark/spark-operator applied to namespace spark-operator"
  5. Проверьте работоспособность пода оператора Spark:

    $ kubectl get pods -n spark-operator

    Ожидаемый вывод должен быть похож на следующий:

    NAME                                             READY   STATUS    RESTARTS   AGE
    spark-operator-spark-operator-85d458c595-82qql   1/1     Running   0          2m25s

Шаг 2. Запуск приложения Spark

  1. Подготовьте файл hadoop_conf.yaml с настройками Hadoop (необходимо, только если приложение обращается к данным, управляемым этими сервисами; для самодостаточных JAR-приложений блок hadoop можно опустить):

    hadoop_conf.yaml
    sites:
        core:
          fs.defaultFS: ""
        hdfs:
          dfs.encrypt.data.transfer.cipher.suites: AES/CTR/NoPadding
        hive:
          hive.metastore.uris: ""
  2. Инициализируйте приложение Spark:

    $ ./adc init --spark-application --hadoop-file hadoop_conf.yaml -o spark-application.yaml

    Данная команда создаст файл spark-application.yaml с шаблоном конфигурации.

  3. Отредактируйте конфигурационный файл:

    spark-application.yaml
    apiVersion: adc.arenadata.io/v1alpha1
    kind: SparkApplication
    metadata:
      name: spark-application
      namespace: spark-applications (1)
    spec:
      image: hub.arenadata.io/adc-enterprise/spark3:<tag> (2)
    
      ## Image pull secret for a private registry.
      ## Set 'externalSecretName' to reference an existing Secret,
      ## or set 'credentials' and optionally 'secretName' to let the CLI create one.
      #imagePullSecret:
      #  # Use a Secret managed outside ADC.
      #  externalSecretName: existing-registry-secret
      #
      #  ## Or let ADC create the Secret.
      #  #secretName: custom-registry-secret
      #
      #  #credentials:
      #  #  registry: registry.example.com
      #  #  username: user
      #  #  password: pass
    
      hadoop: (3)
        core:
          fs.defaultFS: ""
        hdfs:
          dfs.encrypt.data.transfer.cipher.suites: AES/CTR/NoPadding
        hive:
          hive.metastore.uris: ""
    
      ## Kerberos configuration for authentication.
      #kerberos:
      #  principal: user@EXAMPLE.COM
      #
      #  # CLI reads the local files and creates the kerberos-ccache Secret on 'adc apply'.
      #  # Alternative - keytab mode: replace this block with:
      #  #   keytab:
      #  #     secretName: <name-of-existing-keytab-secret>
      #  ticketCache:
      #    #secretName: custom-ticket-cache
      #    externalSecretName: existing-ticket-cache
      #    #ticketPath: /tmp/krb5cc_1000
      #    #krb5ConfPath: /etc/krb5.conf
    
      ## Ranger plugin configuration.
      ## Uncomment and fill the lines below. adc apply derives the rest.
      #ranger:
      #  # fill ranger.plugin.spark.policy.rest.url below with Ranger endpoint, e.g. https://adps-adc.ru-central1.internal:6182
      #  # fill ranger.plugin.spark.service.name below with Ranger service name you want to use for product, e.g. adc_spark_id_1
      #  security:
      #    ranger.plugin.spark.policy.rest.url: ""
      #    ranger.plugin.spark.service.name: ""
      #
      #  # fill xasecure.audit.destination.solr.zookeepers below with Zookeepers endpoints to resolve solr service, e.g. adps-adc.ru-central1.internal:2181/Arenadata.Hadoop-2.solr.server
      #  audit:
      #    xasecure.audit.destination.solr.zookeepers: ""
      #
      #  # Local Ranger files 'adc apply' writes into the configs Secret.
      #  # Relative paths are resolved against the config file.
      #  files:
      #    jceksStorePath: /path/to/ranger.jceks
    
      ## Java KeyStore/TrustStore certificate configuration.
      ## Set externalSecretName to reference an existing Secret,
      ## or set files and optional secretName to have ADC create it.
      #ssl:
      #  ## Name of the Secret containing Java keystores.
      #  #secretName: custom-ssl-secret
      #  externalSecretName: existing-ssl-secret
      #
      #  # Key in the Secret containing the truststore file.
      #  trustStoreKey: truststore.jks
      #
      #  ## Password for the truststore (optional).
      #  #trustStorePassword: bigdata
      #
      #  ## Key in the Secret containing the keystore file (optional).
      #  #keyStoreKey: keystore.jks
      #
      #  ## Password for the keystore (optional).
      #  #keyStorePassword: bigdata
      #
      #  ## Local files 'adc apply' puts into the Secret named by ssl.secretName.
      #  ## Relative paths are resolved against the config file.
      #  #files:
      #  #  trustStorePath: /path/to/truststore.jks
      #  #  #keyStorePath: /path/to/keystore.jks
    
      ## Use an external Hadoop configs Secret instead of the one rendered by ADC.
      #hadoopConfigsSecret:
      #  # Use a Secret managed outside ADC.
      #  externalSecretName: existing-spark-hadoop-configs
      #
      #  ## Or let ADC create the Secret.
      #  #secretName: custom-spark-hadoop-configs
    
      ## Use an external Ranger configs Secret instead of the one rendered by ADC.
      #rangerConfigsSecret:
      #  # Use a Secret managed outside ADC.
      #  externalSecretName: existing-spark-ranger-configs
      #
      #  ## Or let ADC create the Secret.
      #  #secretName: custom-spark-ranger-configs
    
      # Spark application main resource (e.g. local:///opt/spark/examples/jars/spark-examples.jar).
      mainApplicationFile: "local:///opt/spark/examples/jars/spark-examples_2.13-3.5.4.4-4.3.0-2.jar" (4)
    
      ## HDFS or local directory for the Spark event log.
      ## When set, the CLI adds spark.eventLog.enabled=true, spark.eventLog.dir,
      ## spark.eventLog.rolling.enabled=true and spark.eventLog.rolling.interval=30s to sparkConf.
      #eventLogDir: ""
    
      ## Fully-qualified main class name. Required for Java/Scala applications.
      mainClass: "org.apache.spark.examples.SparkPi" (5)
    
      # ServiceAccount used by the Spark driver, also injected into
      # spark.kubernetes.authenticate.driver.serviceAccountName. The CLI creates it, plus a Role
      # and RoleBinding for Spark pods, by default (create: true). Set create: false to skip that
      # and only reference a ServiceAccount managed elsewhere.
      # The Role rules are managed by the CLI and cannot be customized.
      serviceAccount: (6)
        create: true
        name: spark-application
      job: (7)
        ## true (default) deletes the spark-submit Job pod after it finishes; set false to keep it for debugging.
        deleteOnTermination: false
    
        #resources:
        #  limits:
        #    cpu: "1"
        #    memory: 512Mi
        #  requests:
        #    cpu: 500m
        #    memory: 64Mi
    
        ## Component arguments. Key-value pairs passed to the component configuration.
        #args:
        #  executor-memory: 1g
        #  num-executors: "2"
    
      ## Application arguments appended after mainApplicationFile.
      args:
        - "100"
    
      # Spark configuration entries (spark.*).
      sparkConf: (8)
        spark.artifactory.dir.path: /tmp/artifacts
        spark.jars.ivy: /tmp/ivy
        spark.local.dir: /tmp/data
        spark.sql.catalog.spark_catalog: org.apache.iceberg.spark.SparkSessionCatalog
        spark.sql.extensions: org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions
        spark.sql.security.confblacklist: spark.sql.extensions
    
      ## Seconds after the application finishes (Succeeded, or Failed with no
      ## retries left) before the SparkApplication is deleted. Omit to keep it
      ## until explicit deletion.
      #ttlSecondsAfterFinished: 3600 (9)
    
      ## Celeborn remote shuffle service for Spark.
      ## tiers mirror the cluster's storage.tiers: local (SSD/HDD) and MEMORY advertise their name only,
      ## remote (S3/HDFS) also set dir (and, for S3, credentials). Ozone is an HDFS tier with an ofs:// dir.
      #celeborn:
      #  # Storage tiers mirroring the cluster's storage.tiers so the client advertises the same layers.
      #  # type: SSD, HDD, S3, HDFS, MEMORY. SSD/HDD and MEMORY are advertise-only here (no dir; worker-only
      #  # fields ignored); remote S3/HDFS set dir (s3a:// for S3; hdfs:// or ofs:// for Ozone on HDFS). Example:
      #  #   - type: MEMORY   # cache tier; pair with a durable tier below, no dir
      #  #   - type: SSD      # advertise-only on the client, no dir needed
      #  #   - dir: s3a://bucket/celeborn
      #  #     s3: { endpoint: https://s3:9878, region: us-east-1 }
      #  #     type: S3
      #  #   - dir: hdfs://nn/celeborn   # or ofs://om/volume/bucket/celeborn for Ozone
      #  #     type: HDFS
      #  tiers:
      #    - dir: s3a://shuffle/my-cluster
      #      s3:
      #        accessKey: <access-key>
      #        endpoint: https://s3.endpoint:443
      #        pathStyleAccess: true
      #        region: <region>
      #        secretKey: <secret-key>
      #      type: S3
      #  masterEndpoint: ""
      #  extraSparkConf:
      #    spark.sql.adaptive.enabled: "true"
      #
      #  # Enable TLS on the client's RPC connection to the Celeborn cluster.
      #  # When true the CLI renders spark.celeborn.ssl.* into the Spark conf
      #  # and requires the ssl section with trustStoreKey.
      #  rpcEncryption: false
      #
      #  # Enable TLS on the client's data module, which carries shuffle push/fetch
      #  # traffic between executors and workers. Requires the ssl section with trustStoreKey.
      #  dataEncryption: false
    
      ## YuniKorn scheduler configuration for queue selection and Gang scheduling.
      ## Uncomment the block to route the Spark job into a YuniKorn queue; the CLI renders the
      ## scheduler name, queue labels and gang annotations into sparkConf.
      #yunikorn:
      #  queue: root.analytics
      #  taskGroups:
      #    - minMember: 1
      #      minResource:
      #        cpu: "1"
      #        memory: 1433Mi
      #      name: spark-driver
      #    - minMember: 2
      #      minResource:
      #        cpu: "1"
      #        memory: 1433Mi
      #      name: spark-executor
    
      ## Monitoring configuration.
      #monitoring:
      #  # Enables Prometheus metrics export from this product's pods.
      #  exportMetrics: true
    1 Пространство имен, используемое приложением Spark.
    2 URL образа Spark в вашем репозитории.
    3 Настройки Hadoop, взятые из ранее созданного файла hadoop_conf.yaml.
    4 URL к файлу с задачей приложения (JAR или .py).
    5 Имя главного класса для приложений на Java/Scala.
    6 Настройки сервисного аккаунта.
    7 Настройки задачи. После завершения работы по умолчанию поды приложения удаляются автоматически. Чтобы поды задачи и драйвера не удалялись (например, для проверки логов), присвойте параметру deleteOnTermination значение false. Чтобы оставить executor-поды, присвойте параметру deleteOnTermination значение false в блоке spark.executor — он не включен в сгенерированную минимальную конфигурацию, поэтому его требуется добавить вручную.
    8 Настройки Spark.
    9 Период в секундах, после которого приложение Spark будет удалено вне зависимости от причины завершения работы.
  4. Вы можете проверить конфигурацию перед ее применением, выполнив команду apply с флагом --dry-run:

    $ ./adc apply -f spark-application.yaml --dry-run > spark-application-render.yaml
    spark-application-render.yaml
    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: spark-application-configs
      namespace: spark-applications
    stringData:
      core-site.xml: |-
        <configuration>
          <property>
            <name>dfs.encrypt.data.transfer.cipher.suites</name>
            <value>AES/CTR/NoPadding</value>
          </property>
          <property>
            <name>fs.defaultFS</name>
            <value></value>
          </property>
        </configuration>
      hive-site.xml: |-
        <configuration>
          <property>
            <name>hive.metastore.uris</name>
            <value></value>
          </property>
        </configuration>
    type: Opaque
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: spark-application
      namespace: spark-applications
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: spark-application
      namespace: spark-applications
    rules:
    - apiGroups:
      - ""
      resources:
      - pods
      - configmaps
      - persistentvolumeclaims
      - services
      - secrets
      verbs:
      - get
      - list
      - watch
      - create
      - update
      - patch
      - delete
      - deletecollection
    - apiGroups:
      - networking.k8s.io
      resources:
      - networkpolicies
      verbs:
      - get
      - list
      - watch
      - create
      - update
      - patch
      - delete
    - apiGroups:
      - events.k8s.io
      resources:
      - events
      verbs:
      - create
      - patch
      - update
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: spark-application
      namespace: spark-applications
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: spark-application
    subjects:
    - kind: ServiceAccount
      name: spark-application
      namespace: spark-applications
    ---
    apiVersion: spark.arenadata.io/v1alpha1
    kind: SparkApplication
    metadata:
      name: spark-application
      namespace: spark-applications
    spec:
      args:
      - "100"
      driver:
        metadata: {}
        spec:
          image: hub.arenadata.io/adc-enterprise/spark3:<tag>
          imagePullPolicy: Always
      executor:
        metadata: {}
        spec:
          image: hub.arenadata.io/adc-enterprise/spark3:<tag>
          imagePullPolicy: Always
      hadoopConfigsSecretName: spark-application-configs
      job:
        deleteOnTermination: false
        metadata: {}
        spec:
          image: hub.arenadata.io/adc-enterprise/spark3:<tag>
          imagePullPolicy: Always
      mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.13-3.5.4.4-4.3.0-2.jar
      mainClass: org.apache.spark.examples.SparkPi
      serviceAccountName: spark-application
      sparkConf:
        spark.artifactory.dir.path: /tmp/artifacts
        spark.jars.ivy: /tmp/ivy
        spark.kubernetes.authenticate.driver.serviceAccountName: spark-application
        spark.kubernetes.namespace: spark-applications
        spark.local.dir: /tmp/data
        spark.sql.catalog.spark_catalog: org.apache.iceberg.spark.SparkSessionCatalog
        spark.sql.extensions: org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions
        spark.sql.security.confblacklist: spark.sql.extensions
    status: {}
  5. Если манифест корректный, примените конфигурацию и запустите приложение Spark:

    $ ./adc apply -f spark-application.yaml

    Ожидаемый вывод содержит сообщение с подтверждением успеха:

    time="20260817085516UTC" level="info" msg="cluster spark-application applied to namespace spark-applications"
  6. Проверьте работоспособность подов приложения Spark:

    $ kubectl get pods -n spark-applications

    Ожидаемый вывод должен быть похож на следующий:

    NAME                                        READY   STATUS              RESTARTS   AGE
    spark-application-cdedc2a00f064f74-driver   1/1     Running             0          32s
    spark-application-fwpxp                     1/1     Running             0          92s
    spark-pi-cd8784a00f06622a-exec-1            0/1     ContainerCreating   0          28s
    spark-pi-cd8784a00f06622a-exec-2            0/1     ContainerCreating   0          28s

    После завершения работы executor-поды удаляются, а статус подов приложения меняется на Completed:

    NAME                                        READY   STATUS      RESTARTS   AGE
    spark-application-cdedc2a00f064f74-driver   0/1     Completed   0          74s
    spark-application-fwpxp                     0/1     Completed   0          2m14s
  7. Проверьте вывод в логах driver-пода:

    $ kubectl logs spark-application-cdedc2a00f064f74-driver -n spark-applications

    В логах должна быть следующая строка:

    Pi is roughly 3.1415831415831414

Удаление инстансов

ВАЖНО
Удалять оператор следует только после удаления всех управляемых им ресурсов.

Чтобы удалить приложение Spark, выполните следующую команду:

$ ./adc delete -f spark-application.yaml

Чтобы удалить оператор Spark, выполните следующую команду:

$ ./adc delete -f spark-operator.yaml
Нашли ошибку? Выделите текст и нажмите Ctrl+Enter чтобы сообщить о ней