Запуск задач Spark в Kubernetes

Предварительные требования

  • Установите кластер ADH с сервисами HDFS, Hive и Spark.

  • Создайте в HDFS отдельную директорию для загрузки тестовых данных. Пользователь, запускающий spark-submit, должен быть владельцем директории:

    $ sudo -u hdfs hdfs dfs -mkdir /user/<username>
    $ sudo -u hdfs hdfs dfs -chown <username>:<username> /user/<username>

Если у вас активирован плагин Ranger Spark3, выполните следующие шаги:

  1. Настройте Ranger UserSync для синхронизации пользователей и групп с LDAP.

  2. В настройках сервиса Spark в Ranger нажмите Manage Service → Edit Service. В секции Add New Configurations присвойте параметру userstore.download.auth.users значение *.

Настройка

Kubernetes

  1. Сгенерируйте файл kubeconfig на хосте с компонентом Spark Client.

  2. Объявите сервисный аккаунт и выполните привязку ролей, необходимых для запуска исполнителей Spark (измените пространство имен при необходимости) в файле sa.yaml.

    sa.yaml
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: spark-submit-sa
      namespace: default
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: spark-submit-sa-role
      namespace: default
    rules:
      - apiGroups:
          - ""
        resources:
          - pods
          - configmaps
          - persistentvolumeclaims
          - services
          - secrets
        verbs:
          - get
          - list
          - watch
          - create
          - update
          - patch
          - delete
          - deletecollection
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: spark-submit-sa-rb
      namespace: default
    subjects:
      - kind: ServiceAccount
        name: spark-submit-sa
        namespace: default
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: spark-submit-sa-role
  3. Создайте объявленный выше сервисный аккаунт:

    $ kubectl create -f sa.yaml

    Ожидаемый вывод:

    serviceaccount/spark-submit-sa created
    role.rbac.authorization.k8s.io/spark-submit-sa-role created
    rolebinding.rbac.authorization.k8s.io/spark-submit-sa-rb created
  4. Если активирован SSL, подготовьте секрет с сертификатами, создаваемыми во время активации SSL. Секрет должен содержать файл /etc/ssl/truststore.jks. Ожидается, что truststore.jks содержит все доверенные CA.

    ssl.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: ssl-secret
      namespace: default
    data:
      truststore.jks: base64 content of /etc/ssl/truststore.jks
    $ kubectl create -f ssl.yaml

Хост со Spark Client

  1. Если активирован Kerberos, сгенерируйте кеш для тикетов:

    $ kinit -k -c FILE:<krb5_ccache> -t <keytab>> <principal>
    $ kubectl create secret generic user-krb-cache --from-file=<krb5_ccache>

    где:

    • <krb5_ccache> — путь к кешу тикетов.

    • <keytab> — путь к keytab-файлу пользователя.

    • <principal> — имя принципала в формате <username>@<realm>.

  2. Настройте файлы Spark.

    Если активен плагин Ranger Spark3, допишите следующие строки в файл ranger-spark-security.xml (можно сделать с помощью параметра Spark Custom ranger-spark-security.xml в ADCM):

    <property>
    	<name>ranger.plugin.hive.use.rangerGroups</name>
    	<value>True</value>
    </property>
    <property>
    	<name>ranger.plugin.hive.use.only.rangerGroups</name>
    	<value>True</value>
    </property>

Запуск задачи

В качестве примера задачи используется следующий скрипт:

write-hdfs.py
from pyspark.sql import SparkSession

def main():
    spark = SparkSession.builder.appName("HDFSWriteExample").getOrCreate()

    data = [("row1", 1), ("row2", 2), ("row3", 3)]
    df = spark.createDataFrame(data, ["col1", "col2"])

    hdfs_output_path = "hdfs://hdfs/user/admin/tmp/test/"

    df.write.format("csv").mode("overwrite").save(hdfs_output_path)

    print(f"Data successfully written to {hdfs_output_path}")

    spark.stop()

if __name__ == "__main__":
    main()

Запустите spark-submit:

$ /bin/spark3-submit --deploy-mode cluster --master <master> --conf spark.kubernetes.container.image=<image> --conf spark.kubernetes.namespace=<namespace> --conf spark.kubernetes.authenticate.driver.serviceAccountName=<sa>  --conf spark.kubernetes.file.upload.path=<upload_path> write_hdfs.py

где:

  • <master> — эндпойнт Kubernetes API, доступный с хоста со Spark Client, например, k8s://https://10.92.14.35.

  • <image> — образ драйвера и исполнителя Spark. Он должен быть распакован из offline-пакета и загружен в реестр. Ссылку на образ в реестре необходимо привести в качестве значения данного параметра, например, hub.arenadata.io/adh-enterprise/spark3-docker:3.5.4_arenadata3-adh-4.2.0-x86_64.

  • <namespace> — пространство имен Kubernetes, в котором следует запустить драйвер и исполнитель, например, default.

  • <sa> — сервисный аккаунт Kubernetes, созданный на втором шаге.

  • <upload_path> — путь к директории HDFS/Ozone, например, hdfs://hdfs/user/admin/tmp/test/ или ofs://adhom/ozone/adh/apps/spark-submit/upload.

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

    • --conf spark.kubernetes.driver.secrets.<ssl-secret> — монтирование SSL к драйверу, где <ssl-secret> — название секрета, созданного на третьем шаге.

    • --conf spark.kubernetes.executor.secrets.<ssl-secret> — монтирование SSL к исполнителю, где <ssl-secret> — название секрета, созданного на третьем шаге.

    • --conf spark.driver.extraJavaOptions — опции для использования монтированного truststore для всех запросов, например -Djavax.net.ssl.trustStore=/etc/ssl/truststore.jks -Djavax.net.ssl.trustStorePassword=<password>, где <password> должен совпадать с паролем к truststore.

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

    • --conf spark.kerberos.access.hadoopFileSystems — разделенный запятыми список доступных файловых систем, например, hdfs://<hdfs_nameservice>,ofs://<ozone_mgr>/ozone, где <hdfs_nameservices> — значение параметра HDFS dfs.internal.nameservices; <ozone_mgr> — значение параметра Ozone Manager ozone.om.service.ids.

    • --principal — принципал Kerberos, соответствующий пользователю, например, user@RU-CENTRAL1.INTERNAL.

    • --keytab — keytab-файл Kerberos для пользователя, например, ./user.keytab.

    • --conf spark.kubernetes.kerberos.krb5.path — путь к файлу krb5.conf внутри контейнера, например, /etc/krb5.conf.

    • --conf spark.kubernetes.driverEnv.KRB5CCNAME — путь к кешу тикетов.

    • --conf spark.kubernetes.driverEnv.KRB5PRINCIPAL — имя принципала Kerberos в формате <username>@<realm>.

    • --conf spark.kubernetes.driver.secrets.<krb5_ccache_secret> — директория для монтирования кеша тикетов, созданного на первом шаге.

Вы можете отследить выполнение задачи в веб-интерфейсе Spark History Server.

Нашли ошибку? Выделите текст и нажмите Ctrl+Enter чтобы сообщить о ней