web-dev-qa-db-fra.com

Dois-je appeler ugi.checkTGTAndReloginFromKeytab () avant chaque action sur hadoop?

Dans mon application serveur, je me connecte au cluster Hadoop sécurisé Kerberos à partir de mon Java. J'utilise divers composants comme le système de fichiers HDFS, Oozie, Hive etc. Au démarrage de l'application, je fais appel

UserGroupInformation.loginUserFromKeytabAndReturnUGI( ... );

Cela me renvoie UserGroupInformation instance et je la conserve pour la durée de vie de l'application. Lorsque je fais une action privilégiée, je les lance avec ugi.doAs(action).

Cela fonctionne bien mais je me demande si et quand dois-je renouveler le ticket Kerberos dans UserGroupInformation? J'ai trouvé une méthode UserGroupInformation.checkTGTAndReloginFromKeytab() qui semble faire le renouvellement du ticket chaque fois qu'il arrive à expiration. J'ai également constaté que cette méthode est appelée par divers outils Hadoop comme WebHdfsFileSystem par exemple.

Maintenant, si je veux que mon application serveur (pouvant fonctionner pendant des mois, voire des années) ne subisse jamais d'expiration de ticket, quelle est la meilleure approche? Pour fournir des questions concrètes:

  1. Puis-je compter sur les différents clients Hadoop qu'ils appellent checkTGTAndReloginFromKeytab chaque fois que cela est nécessaire?
  2. Dois-je appeler jamais checkTGTAndReloginFromKeytab moi-même dans mon code?
  3. Si oui, devrais-je le faire avant chaque appel à ugi.doAs(...) ou plutôt configurer une minuterie et l'appeler périodiquement (à quelle fréquence)?
23
Jan Zyka

Committer Hadoop ici! Ceci est une excellente question.

Malheureusement, il est difficile de donner une réponse définitive à cela sans une plongée profonde dans les modèles d'utilisation particuliers de l'application. Au lieu de cela, je peux offrir des directives générales et décrire quand Hadoop gérerait automatiquement le renouvellement ou la reconnexion de billets à partir d'un fichier de clés pour vous, et quand il ne le ferait pas.

Le principal cas d'utilisation de l'authentification Kerberos dans l'écosystème Hadoop est la structure RPC de Hadoop, qui utilise SASL pour l'authentification. La plupart des processus démon de l'écosystème Hadoop gèrent cela en effectuant un seul appel unique à UserGroupInformation#loginUserFromKeytab au démarrage du processus. Les exemples incluent le HDFS DataNode, qui doit authentifier ses appels RPC au NameNode, et le YARN NodeManager, qui doit authentifier ses appels au ResourceManager. Comment se fait-il que des démons comme DataNode puissent effectuer une connexion unique au démarrage du processus, puis continuer à fonctionner pendant des mois, longtemps après les délais d'expiration des tickets typiques?

Comme il s'agit d'un cas d'utilisation courant, Hadoop implémente un mécanisme de reconnexion automatique directement à l'intérieur de la couche client RPC. Le code pour cela est visible dans le RPC Client#handleSaslConnectionFailure méthode:

          // try re-login
          if (UserGroupInformation.isLoginKeytabBased()) {
            UserGroupInformation.getLoginUser().reloginFromKeytab();
          } else if (UserGroupInformation.isLoginTicketBased()) {
            UserGroupInformation.getLoginUser().reloginFromTicketCache();
          }

Vous pouvez considérer cela comme une "évaluation paresseuse" de la reconnexion. Il ne ré-exécute la connexion qu'en réponse à un échec d'authentification sur une tentative de connexion RPC.

Sachant cela, nous pouvons donner une réponse partielle. Si le modèle d'utilisation de votre application consiste à se connecter à partir d'un fichier de clés, puis à effectuer des appels RPC Hadoop typiques, vous n'avez probablement pas besoin de générer votre propre code de reconnexion. La couche client RPC le fera pour vous. "RPC Hadoop typique" signifie la grande majorité des API Java pour interagir avec Hadoop, y compris le HDFS FileSystem API, le YarnClient et MapReduce Job soumissions.

Cependant, certains modèles d'utilisation des applications n'impliquent pas du tout Hadoop RPC. Un exemple de ceci serait les applications qui interagissent uniquement avec les API REST REST $, comme WebHDFS ou YARN REST API) ==. Dans ce cas, le modèle d'authentification utilise Kerberos via SPNEGO comme décrit dans la documentation Hadoop Authentification HTTP .

Sachant cela, nous pouvons ajouter plus à notre réponse. Si le modèle d'utilisation de votre application n'utilise pas du tout Hadoop RPC et se limite plutôt aux API REST, vous devez alors lancer votre propre logique de reconnexion. C'est exactement pourquoi WebHdfsFileSystem appelle UserGroupInformation#checkTGTAndReloginFromkeytab , comme vous l'avez remarqué. WebHdfsFileSystem choisit de passer l'appel juste avant chaque opération. C'est une bonne stratégie, car UserGroupInformation#checkTGTAndReloginFromkeytab ne renouvelle le ticket que s'il est "proche" de l'expiration. Sinon, l'appel est un no-op.

En tant que cas d'utilisation finale, considérons un processus interactif, ne se connectant pas à partir d'un keytab, mais obligeant plutôt l'utilisateur à exécuter kinit en externe avant de lancer l'application. Dans la grande majorité des cas, ces applications seront de courte durée, telles que les commandes CLI Hadoop. Cependant, dans certains cas, il peut s'agir de processus plus longs. Pour prendre en charge des processus plus longs, Hadoop démarre un thread d'arrière-plan pour renouveler le ticket Kerberos "proche" de l'expiration. Cette logique est visible dans UserGroupInformation#spawnAutoRenewalThreadForUserCreds . Il existe cependant une distinction importante par rapport à la logique de reconnexion automatique fournie dans la couche RPC. Dans ce cas, Hadoop n'a que la possibilité de renouveler le ticket et de prolonger sa durée de vie. Les billets ont une durée de vie renouvelable maximale, comme dicté par l'infrastructure Kerberos. Après cela, le billet ne sera plus utilisable. Dans ce cas, la reconnexion est pratiquement impossible, car cela impliquerait de demander à nouveau un mot de passe à l'utilisateur, et il s'est probablement éloigné du terminal. Cela signifie que si le processus se poursuit au-delà de l'expiration du ticket, il ne pourra plus s'authentifier.

Encore une fois, nous pouvons utiliser ces informations pour éclairer notre réponse globale. Si vous comptez sur un utilisateur pour se connecter de manière interactive via kinit avant de lancer l'application, et si vous êtes sûr que l'application ne fonctionnera pas plus longtemps que la durée de vie renouvelable maximale du ticket Kerberos, vous pouvez compter sur les internes Hadoop pour couvrir le renouvellement périodique pour vous.

Si vous utilisez une connexion basée sur des clés et que vous n'êtes tout simplement pas sûr que le modèle d'utilisation de votre application puisse s'appuyer sur la reconnexion automatique de la couche RPC Hadoop, alors l'approche conservatrice est de rouler la vôtre. @SamsonScharfrichter a donné une excellente réponse ici à propos de la vôtre.

Stratégie de renouvellement de connexion HBase Kerberos

Enfin, je devrais ajouter une note sur la stabilité de l'API. Le Apache Hadoop Compatibility les directives discutent en détail de l'engagement de la communauté de développement Hadoop à la rétrocompatibilité. L'interface de UserGroupInformation est annotée LimitedPrivate et Evolving. Techniquement, cela signifie que l'API de UserGroupInformation n'est pas considérée comme publique et qu'elle pourrait évoluer de manière incompatible en amont. En pratique, il y a déjà beaucoup de code dépendant de l'interface de UserGroupInformation, donc il n'est tout simplement pas possible pour nous de faire un changement de rupture. Certes, dans la ligne de version 2.x actuelle, je n'aurais aucune crainte que les signatures de méthode ne changent sous vous et ne cassent votre code.

Maintenant que nous avons toutes ces informations de base, revenons à vos questions concrètes.

Puis-je compter sur les différents clients Hadoop qu'ils appellent checkTGTAndReloginFromKeytab chaque fois que cela est nécessaire?

Vous pouvez vous y fier si le modèle d'utilisation de votre application consiste à appeler les clients Hadoop, qui à leur tour utilisent la structure RPC de Hadoop. Vous ne pouvez pas vous y fier si le modèle d'utilisation de votre application appelle uniquement les API Hadoop REST.

Dois-je appeler jamais checkTGTAndReloginFromKeytab moi-même dans mon code?

Vous devrez probablement le faire si le modèle d'utilisation de votre application consiste uniquement à appeler les API Hadoop REST au lieu d'appels RPC Hadoop. Vous ne bénéficieriez pas de la reconnexion automatique implémentée à l'intérieur Client RPC de Hadoop.

Si oui, devrais-je le faire avant chaque appel unique à ugi.doAs (...) ou plutôt configurer une minuterie et l'appeler périodiquement (à quelle fréquence)?

C'est bien d'appeler UserGroupInformation#checkTGTAndReloginFromKeytab juste avant chaque action qui doit être authentifiée. Si le ticket n'est pas proche de l'expiration, alors la méthode sera un no-op. Si vous pensez que votre infrastructure Kerberos est lente et que vous ne voulez pas que les opérations client paient le coût de latence de la reconnexion, ce serait une raison de le faire dans un thread d'arrière-plan distinct. Assurez-vous simplement de rester un peu en avance sur l'heure d'expiration réelle du billet. Vous pouvez emprunter la logique à l'intérieur de UserGroupInformation pour déterminer si un ticket est "proche" de l'expiration. Dans la pratique, je n'ai jamais personnellement vu la latence de la reconnexion être problématique.

72
Chris Nauroth