Интеграция Kyuubi и Spark Connect
Обзор
Spark Connect — это протокол, позволяющий клиентским приложениям взаимодействовать с удаленным сервером Spark через gRPC без необходимости размещать на клиенте драйвер Spark.
Kyuubi — это многопользовательский шлюз, позволяющий запускать задачи Spark и исполнять SQL-запросы в вычислительных движках по типу Spark, Hive и Flink.
Стандартный сервер Spark Connect не предоставляет возможностей изоляции пользователей и аутентификации. gRPC-канал между клиентским приложением Spark и Spark Connect остается незащищенным. В то же время эти функции предоставляет Kyuubi, поэтому для него была введена поддержка протокола Spark Connect.
Spark Connect поддерживает следующие способы аутентификации: KERBEROS, LDAP и NONE. Клиент отправляет запрос с заголовком аутентификации Authorization: Negotiate … для Kerberos/SPNEGO или Authorization: Basic … для LDAP. Если аутентификация проходит корректно, сервер выдает токен, действующий столько, сколько указано в параметре kyuubi.frontend.spark.connect.token.ttl компонента Kyuubi Server (по умолчанию — 24 часа).
Затем, клиент может отправлять различные запросы к Spark с выданным токеном (клиент указывает его в заголовке аутентификации Bearer при каждом запросе). Время жизни этого токена обновляется каждый раз при отправке запроса. Когда пользователь завершает сессию Spark (вызывая spark.stop()), клиент Spark вызывает RPC-метод ReleaseSession, и сервер автоматически инвалидирует токен.
Клиентские библиотеки
Для Python и Java/Scala доступны клиентские библиотеки.
Пакет Python содержит модуль, реализующий аутентификацию для Spark Connect. Также доступен соответствующий пакет PySpark. Эти библиотеки уже имеются на всех хостах ADH (в директориях /usr/lib/spark3/python и /opt/pyspark3-python), но перед запуском программ Python необходимо активировать нужную среду:
$ source /opt/pyspark3-python/bin/activate
Если вы используете стандартный пакет PySpark, RPC-метод ReleaseSession не будет вызван при исполнении spark.stop(). Таким образом, после завершения сессии Spark, токен аутентификации не будет отозван. Если уровень изоляции Kyuubi имеет значение CONNECTION, то сессия YARN останется активной даже после вызова spark.stop().
Также доступен пакет для Java/Scala.
Настройка
В ADCM добавьте в значение конфигурационного параметра kyuubi.frontend.protocols компонента Kyuubi Server значение SPARK_CONNECT и перезапустите сервис Kyuubi. Таким образом, итоговое значение параметра будет иметь вид, например, THRIFT_BINARY,SPARK_CONNECT.
Примеры
Python
Данный пример демонстрирует подключение к Kyuubi через Spark Connect из Python. В кластере ADH активирован SSL и Kerberos.
-
Подготовьте shell-скрипт, устанавливающий необходимую среду:
prepare_env.shsource /opt/pyspark3-python/bin/activate export GRPC_DEFAULT_SSL_ROOTS_FILE_PATH=/etc/ssl/certs/ca-certificates.crt -
Подготовьте программу Python:
spark_connect_client_kerberos.pyfrom kyuubi.spark_connect import KyuubiSessionBuilder HOST = "tsn-adh3-3.ru-central1.internal" PORT = 10199 spark = KyuubiSessionBuilder(f"sc://{HOST}:{PORT}/;use_ssl=true", auth="kerberos").getOrCreate() spark.sql("SELECT current_user()").show() spark.stop()Код для LDAP-аутентификации похож на представленный выше за исключением параметров, передаваемых для создания сессии:
spark = KyuubiSessionBuilder(f"sc://{HOST}:{PORT}/;use_ssl=true", auth="ldap", username="<ldap_username>", password="<ldap_password>").getOrCreate()где
<ldap_username>и<ldap_password>— имя пользователя и пароль пользователя в LDAP.Если вы не используете ни LDAP, ни Kerberos, опустите параметр
auth. -
Запустите программу Python:
$ python3 spark_connect_client_kerberos.pyОжидаемый вывод должен быть похож на следующий:
+--------------+ |current_user()| +--------------+ | stikhomirov| +--------------+
Java/Scala
-
Подготовьте программу Java:
SparkConnectClientKerberos.javaimport org.apache.spark.sql.SparkSession; import org.apache.spark.sql.kyuubi.KyuubiAuthType; import org.apache.spark.sql.kyuubi.KyuubiSessionBuilder; public class SparkConnectClientKerberos { public static void main(String[] args) { String url = System.getenv("KYUUBI_URL"); if (url == null || url.isEmpty()) { throw new IllegalArgumentException("KYUUBI_URL environment variable is required"); } String authStr = System.getenv().getOrDefault("KYUUBI_AUTH", "NONE"); KyuubiAuthType authType = KyuubiAuthType.valueOf(authStr.toUpperCase()); System.out.println("connection string: " + url); System.out.println("auth type: " + authType); SparkSession spark = new KyuubiSessionBuilder(url, authType).getOrCreate(); try { spark.sql("SELECT current_user()").show(); } finally { spark.stop(); } } } -
В файле pom.xml добавьте следующую зависимость:
<dependency> <groupId>org.apache.kyuubi</groupId> <artifactId>kyuubi-spark-connect-client-standalone_2.13</artifactId> <version>1.11.1.1-4.3.0-4</version> </dependency>pom.xml<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.apache.kyuubi.examples</groupId> <artifactId>kyuubi-spark-connect-client-jvm-examples</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.release>17</maven.compiler.release> <kyuubi.version>1.11.1.1-4.3.0-0</kyuubi.version> <spark.version>3.5.4</spark.version> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.5.0</version> <executions> <execution> <phase>package</phase> <goals><goal>shade</goal></goals> <configuration> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/versions/*/module-info.class</exclude> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>SparkConnectClientKerberos</mainClass> <manifestEntries> <Multi-Release>true</Multi-Release> </manifestEntries> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.apache.kyuubi</groupId> <artifactId>kyuubi-spark-connect-client-standalone_2.13</artifactId> <version>${kyuubi.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.36</version> </dependency> </dependencies> </project>С подготовленным POM-файлом сгенерируйте JAR-файл.
-
Подготовьте shell-скрипт, устанавливающий необходимые переменные среды и запускающий программу:
run.shexport KYUUBI_AUTH=kerberos export KYUUBI_URL = "sc://tsn-adh3-3.ru-central1.internal:10199/;use_ssl=true" java --add-opens=java.base/java.nio=ALL-UNNAMED -jar target/kyuubi-spark-connect-client-jvm-examples-1.0-SNAPSHOT.jar -
Запустите подготовленный скрипт:
$ source run.sh