Hadoop UserGroupInformation详解

下面大概了解下面Java的认证相关框架

JAAS 认证和授权框架,只要负责用户的认证和权限。

SASL client 和 server之间认证的框架

GSS 是sasl的一个provider,也就是实现了sasl框架

参考JAAS/GSS-API/SASL/Kerberos简介 | NoSQL漫谈

网上关于high level介绍的还比较多,可以搜索一些,但是要真正理解UserGroupInfomration的功能,还是需要研究 UserGroupInformaiton在 hadoop/hive等大数据系统中如何使用的。

介绍UserGroupInformation 之前,应该了解一下 JaaS框架里 Subject这个概念,简单理解就是代表了一个用户。当通过JAAS登录成功之后,会产生一个subject, 里面包含了一组 Principal, 和其他凭证信息,不如如果是Kerbos认证的话,就会有一个Kerbos身份的principal, 以及把tgt等Credentials的信息放到  privCredentials中。

CASE ONE, 客户端和服务端建立连接

当client 跟Server端建立连接的时候,一般会使用

UserGroupInfomation.doAs(action {

   建立连接的代码

}) 

doAs就会使用UserGroupInformation当前subject执行

这样在建立连接的过程中,就是用了登录后的subject 来建立链接,因为subject包含了kerbos的Principal, 并且拥有合法的Credentials,  sasl client和 sasl server在 建立连接的过程中就会使用到。 真实的底层使用的是Gss的实现。

doAs 里面的实现逻辑

@InterfaceAudience.Public
  @InterfaceStability.Evolving
  public <T> T doAs(PrivilegedAction<T> action) {
    if (LOG.isDebugEnabled()) {
      LOG.debug("PrivilegedAction [as: {}][action: {}]", this, action,
          new Exception());
    }
    //使用当前subject执行action,也就是建立连接的时候使用登录过的subject
    return Subject.doAs(subject, action);
  }

当然,如果没有使用UserGroupInformation.doAs的时候,

建立sasl连接的时候使用的就是当前安全上线文里的subject, 用户已经使用Jaas登录过的,登录之后,subject的信息已经存在AccessConect中了,所以也会使用登录后的subject。

CASE TWO 在服务端执行ACTION

连接到服务端之后,一般服务端有两个UGI,一个是服务本身的UGI,比如NN 一般是hdfs, 或者MetaStore, 一般是hive。 hdfs或者 hive用户是服务里的超级用户,客户端一般创建连接之后,执行的操作的用户是 client的用户,这时候就会用到UserGroupInformation里面 proxyUser的概念。

proxyUser顾名思义,就是代理一个用户执行操作。切记,被代理的用户在服务端是没有通过JAAS 认证过的用户,只是给一个用户名而已。 不过这个用户在客户端已经通过JAAS认证过了。

创建代理用户的代码如下:

/**
   * Create a proxy user using username of the effective user and the ugi of the
   * real user.
   * @param user
   * @param realUser
   * @return proxyUser ugi
   */
  @InterfaceAudience.Public
  @InterfaceStability.Evolving
  public static UserGroupInformation createProxyUser(String user,
      UserGroupInformation realUser) {
    if (user == null || user.isEmpty()) {
      throw new IllegalArgumentException("Null user");
    }
    if (realUser == null) {
      throw new IllegalArgumentException("Null real user");
    }
    Subject subject = new Subject();
    Set<Principal> principals = subject.getPrincipals();
    principals.add(new User(user, AuthenticationMethod.PROXY, null));
    principals.add(new RealUser(realUser));
    return new UserGroupInformation(subject);
  }

代理用户的UserGroupInformation里的subject是创建出来的,里面设置了一个 User的principal, 以及一个 RealUser的principal. 这个RealUser的principal是拥有kerbos认证过的,拥有kerbos秘钥。

代理用户的 subject里,没有任何秘钥信息。

如果用户被代理了,一般在服务端执行action的时候都会使用下面格式

UserGroupInformation.doAs

这样在需要权限认证的地方,就获取到的是代理用户的用户名。

切记,不能用代理用户创建 sasl的connection, 因为没有凭证,会失败的。

获取当前用户

UserGroupInformation.getCurrentUser

/**
   * Return the current user, including any doAs in the current stack.
   * @return the current user
   * @throws IOException if login fails
   */
  @InterfaceAudience.Public
  @InterfaceStability.Evolving
  public static UserGroupInformation getCurrentUser() throws IOException {
    ensureInitialized();
    AccessControlContext context = AccessController.getContext();
    Subject subject = Subject.getSubject(context);
    if (subject == null || subject.getPrincipals(User.class).isEmpty()) {
      return getLoginUser();
    } else {
      return new UserGroupInformation(subject);
    }
  }

从安全上下文获取当前的subject, 如果没有,就获取 getLoginUser, 这时候就触发登录操作。

注意1  里面有一个判断条件是 subject.getPrincipals(User.class).isEnpty()

也就是只有subject里有User这种principals才算是登录过的。

注意2,第一行执行了ensuerInitialized(),这个方法很重要,初始化了hadoop的安全环境.

登录

/**
   * Get the currently logged in user.  If no explicit login has occurred,
   * the user will automatically be logged in with either kerberos credentials
   * if available, or as the local OS user, based on security settings.
   * @return the logged in user
   * @throws IOException if login fails
   */
  @InterfaceAudience.Public
  @InterfaceStability.Evolving
  public static UserGroupInformation getLoginUser() throws IOException {
    ensureInitialized();
    UserGroupInformation loginUser = loginUserRef.get();
    // a potential race condition exists only for the initial creation of
    // the login user.  there's no need to penalize all subsequent calls
    // with sychronization overhead so optimistically create a login user
    // a
<think>好的,我现在需要帮助用户了解如何使用IntelliJ IDEA连接Hadoop集群。首先,我得理清用户的需求。他们可能是一个开发者,想要在IDEA中开发Hadoop应用程序,并连接到集群进行测试或运行。接下来,我需要考虑连接的基本步骤和可能的配置。 首先,我应该想到配置Hadoop环境。用户需要在IDEA项目中引入Hadoop的依赖,这可能通过Maven或手动添加JAR包。然后,设置Hadoop的配置文件,比如core-site.xml、hdfs-site.xml等,这些文件通常位于集群的配置目录中。这一步很重要,因为正确的配置信息才能让IDEA正确连接到集群。 接下来,用户可能需要配置Hadoop的类路径。在IDEA的运行配置中,设置HADOOP_HOME环境变量指向本地的Hadoop目录,这样IDEA可以找到必要的库文件。同时,需要确保Hadoop的用户名权限,避免权限问题导致连接失败。 然后,编写测试代码来验证连接。例如,使用FileSystem类获取HDFS实例,执行创建目录、上传文件等操作。如果出现异常,比如连接超时或权限错误,需要指导用户检查配置文件的地址、端口是否正确,网络是否通畅,以及集群的防火墙设置。 还可能涉及到身份验证的问题,特别是如果集群启用了Kerberos认证,用户可能需要额外的配置,比如krb5.conf文件和keytab。这时候需要提醒用户注意这些安全配置,避免认证失败。 另外,Maven依赖的版本兼容性也是一个需要注意的点。Hadoop的不同版本可能有不同的API或依赖冲突,用户需要确保项目中的Hadoop版本与集群一致。如果用户遇到类找不到或方法过时的错误,可能需要调整依赖版本。 最后,测试环节很重要。用户应该运行一个简单的HDFS或MapReduce任务来确认连接是否成功。如果测试失败,需要根据错误日志逐步排查,比如检查网络连接、配置文件路径、权限设置等。 总结下来,整个过程包括环境配置、依赖管理、代码编写、身份验证处理以及测试和调试。每个步骤都可能遇到问题,需要逐一检查和解决。用户可能需要查阅Hadoop和IDEA的官方文档,或者寻求社区支持来解决更复杂的问题。确保提供清晰的步骤和常见问题的解决方法,能帮助用户顺利连接Hadoop集群。</think>以下是通过IntelliJ IDEA连接Hadoop集群的步骤详解: --- ### 一、前置准备 1. **集群信息确认** - 获取HDFS的访问地址和端口,例如:`hdfs://namenode:8020` - 确认YARN ResourceManager地址,例如:`yarn.resourcemanager.address=rm-host:8032` - 确保本地机器与集群网络互通 2. **本地环境配置** ```xml <!-- 示例:core-site.xml 核心配置 --> <configuration> <property> <name>fs.defaultFS</name> <value>hdfs://namenode:8020</value> </property> </configuration> ``` --- ### 二、IDEA项目配置 1. **添加Hadoop依赖** ```xml <!-- Maven pom.xml 示例 --> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>3.3.6</version> <!-- 需与集群版本一致 --> </dependency> ``` 2. **加载配置文件** - 将集群的`core-site.xml`, `hdfs-site.xml`, `yarn-site.xml`复制到项目的`resources`目录 3. **设置运行环境变量** ```bash # 在IDEA的Run/Debug Configurations中添加: HADOOP_USER_NAME=hadoopuser HADOOP_CONF_DIR=/path/to/conf ``` --- ### 三、代码连接验证 ```java public class HadoopConnectDemo { public static void main(String[] args) throws IOException { Configuration conf = new Configuration(); conf.addResource(new Path("src/main/resources/core-site.xml")); FileSystem fs = FileSystem.get(conf); System.out.println("HDFS工作目录:" + fs.getWorkingDirectory()); // 创建测试目录 Path testDir = new Path("/user/hadoopuser/test"); if (!fs.exists(testDir)) { fs.mkdirs(testDir); System.out.println("目录创建成功"); } fs.close(); } } ``` --- ### 四、常见问题处理 #### 1. 连接超时 $$ \text{错误提示:} \quad \text{ConnectException: Connection refused} $$ - **解决方法**: - 检查防火墙设置:`telnet namenode 8020` - 确认配置文件中的主机名是否可解析(建议使用IP地址) #### 2. 权限拒绝 $$ \text{错误提示:} \quad \text{AccessControlException: Permission denied} $$ - **解决方法**: - 添加运行参数:`System.setProperty("HADOOP_USER_NAME", "hadoopuser")` - 在HDFS执行授权命令:`hdfs dfs -chmod 777 /target/path` #### 3. 类冲突问题 - **现象**:`NoSuchMethodError` 或 `ClassNotFoundException` - **解决方案**: 1. 使用`mvn dependency:tree`检查依赖树 2. 通过`<exclusion>`标签排除冲突依赖 --- ### 五、高级配置(Kerberos认证) 1. **配置krb5.conf** ```ini [libdefaults] default_realm = EXAMPLE.COM ``` 2. **代码集成** ```java UserGroupInformation.loginUserFromKeytab( "user@EXAMPLE.COM", "/path/to/user.keytab" ); ``` --- 通过上述步骤可实现IDEA与Hadoop集群的连接,建议首次使用时通过简单的文件操作验证基础功能,再逐步开发复杂应用。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值