3
votes

Lors de l'exécution de Spark sur Kubernetes pour accéder au cluster Hadoop kerberisé, comment résoudre une erreur «L'authentification SIMPLE n'est pas activée» sur les exécuteurs?

J'essaie d'exécuter Spark sur Kubernetes, dans le but de traiter les données d'un cluster Hadoop Kerberisé. Mon application consiste en de simples transformations SparkSQL. Bien que je puisse exécuter le processus avec succès sur un seul module de pilote, je ne peux pas le faire lorsque j'essaie d'utiliser des exécuteurs. Au lieu de cela, j'obtiens:

org.apache.hadoop.security.AccessControlException: SIMPLE l'authentification n'est pas activée. Disponible: [TOKEN, KERBEROS]

Puisque l'environnement Hadoop est Kerberisé, j'ai fourni un keytab valide, ainsi que le core-site.xml, hive-site.xml, hadoop-site.xml, mapred-site.xml et yarn-site.xml et un fichier krb5.conf dans l'image docker.

J'ai configuré les paramètres d'environnement avec la méthode suivante:

--conf spark.kubernetes.kerberos.enabled=true ^
--conf spark.kubernetes.kerberos.krb5.path=/etc/krb5.conf ^
--conf spark.kubernetes.kerberos.keytab=/var/keytabs/USER123.keytab ^
--conf spark.kubernetes.kerberos.principal=USER123@REALM ^

Je passe également les fichiers * -site.xml par la méthode suivante: p>

spark-submit ^
--master k8s://https://kubernetes.example.environment.url:8443 ^
--deploy-mode cluster ^
--name mini-spark-k8 ^
--class org.spark.Driver ^
--conf spark.executor.instances=2 ^
--conf spark.kubernetes.namespace=<company-openshift-namespace> ^
--conf spark.kubernetes.container.image=<company_image_registry.image> ^
--conf spark.kubernetes.driver.pod.name=minisparkk8-cluster ^
--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark ^
local:///opt/spark/examples/target/MiniSparkK8-1.0-SNAPSHOT.jar ^
/opt/spark/mini-spark-conf.properties

Je lance tout le processus avec la commande spark-submit suivante:

trait SparkConfiguration {

  def createSparkSession(): SparkSession = {
    val spark = SparkSession.builder
    .appName("MiniSparkK8")
    .enableHiveSupport()
    .master("local[*]")
    .config("spark.sql.hive.metastore.version", ConfigurationProperties.hiveMetastoreVersion)
    .config("spark.executor.memory", ConfigurationProperties.sparkExecutorMemory)
    .config("spark.sql.hive.version", ConfigurationProperties.hiveVersion)
    .config("spark.sql.hive.metastore.jars",ConfigurationProperties.hiveMetastoreJars)
    spark.sparkContext.hadoopConfiguration.addResource(new Path(ConfigurationProperties.coreSiteLocation))
    spark.sparkContext.hadoopConfiguration.addResource(new Path(ConfigurationProperties.hiveSiteLocation))
    spark.sparkContext.hadoopConfiguration.addResource(new Path(ConfigurationProperties.hdfsSiteLocation))
    spark.sparkContext.hadoopConfiguration.addResource(new Path(ConfigurationProperties.yarnSiteLocation))
    spark.sparkContext.hadoopConfiguration.addResource(new Path(ConfigurationProperties.mapredSiteLocation))
  }
}

Les configurations ci-dessus sont suffisantes pour obtenir mon étincelle l'application s'exécutant et se connectant avec succès au cluster Kerberized Hadoop. Bien que la commande spark submit déclare la création de deux pods exécuteurs, cela ne se produit pas car j'ai défini master sur local [*] . Par conséquent, un seul pod est créé qui parvient à se connecter au cluster Kerberized Hadoop et à exécuter avec succès mes transformations Spark sur les tables Hive.

Cependant, lorsque je supprime .master (local [*]) , deux pods exécuteurs sont créés. Je peux voir dans les journaux que ces exécuteurs se connectent avec succès au module de pilotes et qu'ils se voient attribuer des tâches. Il ne faut pas longtemps après ce point pour que les deux échouent avec l'erreur mentionnée ci-dessus, ce qui entraîne l'arrêt des pods exécuteurs en échec. Ceci malgré que les exécuteurs aient déjà tous les fichiers nécessaires pour créer une connexion réussie au Hadoop Kerberisé dans leur image. Je crois que les exécuteurs n'utilisent pas le keytab, ce qu'ils feraient s'ils exécutaient le JAR. Au lieu de cela, ils exécutent les tâches qui leur sont confiées à partir du pilote.

Je peux voir dans les journaux que le pilote parvient à s'authentifier correctement avec le keytab de l'utilisateur, USER123 :

INFO SecurityManager: 54 - SecurityManager: authentification désactivée; ui acls désactivé; utilisateurs avec des autorisations d'affichage: Set (spark, USER123); groupes avec autorisations d'affichage: Set (); utilisateurs avec des autorisations de modification: Set (étincelle, USER123); groupes avec des autorisations de modification: Set ()

D'un autre côté, vous obtenez ce qui suit du journal de l'exécuteur, vous pouvez voir cet utilisateur, USER123 n'est pas authentifié:

INFO SecurityManager: 54 - SecurityManager: authentification désactivée; ui acls désactivé; utilisateurs avec des autorisations d'affichage: Set (spark); groupes avec des autorisations d'affichage: Set (); utilisateurs avec des autorisations de modification: Set (étincelle); groupes avec des autorisations de modification: Set ()

J'ai consulté diverses sources, y compris ici . Il mentionne que HIVE_CONF_DIR doit être défini, mais je peux voir à partir de mon programme (qui imprime les variables d'environnement) que cette variable n'est pas présente, y compris lorsque le pod pilote parvient à s'authentifier et à exécuter l'étincelle processus bien.

J'ai essayé de courir avec ce qui suit ajouté à la précédente commande spark-submit:

trait EnvironmentConfiguration {

def configureEnvironment(): Unit = {
  val conf = new Configuration
  conf.set("hadoop.security.authentication", "kerberos")
  conf.set("hadoop.security.authorization", "true")
  conf.set("com.sun.security.auth.module.Krb5LoginModule", "required")
  System.setProperty("java.security.krb5.conf", ConfigurationProperties.kerberosConfLocation)    
  UserGroupInformation.loginUserFromKeytab(ConfigurationProperties.keytabUser, ConfigurationProperties.keytabLocation)
  UserGroupInformation.setConfiguration(conf)
}

Mais cela n'a fait aucune différence.

Ma question est la suivante: comment puis-je faire en sorte que les exécuteurs s’authentifient avec le keytab qu’ils ont à leur image? J'espère que cela leur permettra d'exécuter leurs tâches déléguées.


0 commentaires

4 Réponses :


1
votes

Spark sur les k8 ne prend pas en charge les kerberos maintenant. Cela peut vous aider. https://issues.apache.org/jira/browse/SPARK-23257


2 commentaires

@ double bip c'est une réponse. Le lien sauvegarde un fait, donc la partie pertinente est incluse.


Il semble que cette fonctionnalité devrait fonctionner. Une chose que j'ai remarquée en comparant les journaux de leur demo est que mon processus ne crée pas un secret hadoop. Je me demande s'ils utilisent un successeur pour déclencher 2.4.0.



0
votes

Essayez de kinit votre keytab pour obtenir TGT de KDC à l'avance.

Par exemple, vous pouvez d'abord exécuter kinit dans le conteneur.


0 commentaires

0
votes

Si cela ne vous dérange pas d'exécuter Hive au lieu de SparkSQL pour vos analyses SQL (et d'avoir également à apprendre Hive), Hive sur MR3 offre une solution pour exécuter Hive sur Kubernetes tandis qu'un HDFS sécurisé (Kerberisé) sert de données distantes la source. En prime, à partir de Hive 3, Hive est beaucoup plus rapide que SparkSQL.

https://mr3.postech.ac.kr/hivek8s/home/


0 commentaires

2
votes

Commencez par récupérer le jeton de délégation de hadoop en utilisant la commande ci-dessous.

  1. Faites un kinit -kt avec votre keytab et votre principal
  2. Exécutez ce qui suit pour stocker le jeton de délégation hdfs dans un chemin tmp spark-submit --class org.apache.hadoop.hdfs.tools.DelegationTokenFetcher "" --renewer null /tmp/spark.token
  3. Faites votre soumission d'étincelle réelle avec l'ajout de cette configuration. --conf spark.executorEnv.HADOOP_TOKEN_FILE_LOCATION = / tmp / spark.token \

Voici comment les exécuteurs de fils s'authentifient. Faites de même pour les exécuteurs kubernetes.


3 commentaires

Je vous remercie! Je travaille en mode cluster, je dois donc l'envoyer au pilote, mais cela fonctionne là où l'envoi du keytab ne fonctionne pas.


les exécuteurs de kubernetes n'utilisent pas les keytabs fournis. c'est la raison. Le correctif sera dans Spark 3.0 mais cela peut prendre un certain temps à sortir


J'ai examiné un peu plus la question et j'ai trouvé un moyen alternatif d'obtenir ce jeton que je préfère mieux. Vous voudrez peut-être simplement mettre à jour votre réponse pour inclure l'alternative: hdfs fetchdt --renewer null hdfsdt.token