Hadoop 用户组映射

概述

用户的组别由组映射服务提供者决定。Hadoop支持多种组映射机制,通过hadoop.security.group.mapping属性进行配置。其中一些机制(如JniBasedUnixGroupsMappingWithFallback)使用操作系统的组名解析,无需额外配置。但Hadoop也支持通过LDAP以及LDAP与操作系统组名解析组合的特殊组映射机制,这些机制需要额外配置。hadoop.security.group.mapping可以是以下选项之一:

  • org.apache.hadoop.security.JniBasedUnixGroupsMappingWithFallback

    默认实现。它会判断Java本地接口(JNI)是否可用。如果JNI可用,该实现将使用hadoop内部的API来解析用户的组列表。如果JNI不可用,则使用基于shell的实现ShellBasedUnixGroupsMapping

  • org.apache.hadoop.security.JniBasedUnixGroupsNetgroupMappingWithFallback

    类似于JniBasedUnixGroupsMappingWithFallback。如果JNI可用,它会使用Hadoop原生API获取网络组成员信息;否则使用ShellBasedUnixGroupsNetgroupMapping

  • org.apache.hadoop.security.ShellBasedUnixGroupsMapping

    该实现在Linux/Unix环境下使用bash -c groups命令,或在Windows环境下使用net group命令来解析用户的组列表。

  • org.apache.hadoop.security.ShellBasedUnixGroupsNetgroupMapping

    该实现与ShellBasedUnixGroupsMapping类似,不同之处在于它执行getent netgroup命令来获取网络组成员信息。

  • org.apache.hadoop.security.LdapGroupsMapping

    另一种实现方式,直接连接LDAP服务器来解析组列表。但请注意,仅当所需组完全存在于LDAP中且未在Unix服务器上具体化时,才应使用此提供程序。LdapGroupsMapping支持SSL连接和POSIX组语义。详情请参阅LDAP组映射章节。

  • org.apache.hadoop.security.CompositeGroupsMapping

    该实现通过组合其他群组映射提供者来确定群组成员关系。这允许结合现有的提供者实现,无需定制开发即可组合出虚拟的新提供者来处理复杂情况。详情请参阅章节Composite Groups Mapping

对于HDFS,用户到用户组的映射是在NameNode上执行的。因此,NameNode的主机系统配置决定了用户的用户组映射关系。

请注意,HDFS将文件或目录的用户和组存储为字符串;不像Unix系统中那样将用户和组标识号进行转换。

静态映射

可以通过在hadoop.user.group.static.mapping.overrides中以user1=group1,group2;user2=;user3=group2格式定义映射来静态地将用户映射到组。此属性会覆盖任何组映射服务提供程序。如果用户的组在其中定义,则直接返回这些组而无需进一步查找;否则,将使用hadoop.security.group.mapping中定义的服务提供程序来查找组。默认情况下定义了dr.who=;,因此虚拟用户dr.who将不会有任何组。

缓存/负缓存

由于组映射解析依赖于外部机制,NameNode的性能可能会受到影响。为了减少因重复查找带来的影响,Hadoop会缓存服务提供商返回的组信息。缓存失效时间可通过hadoop.security.groups.cache.secs进行配置,默认值为300秒。

使用默认的缓存实现时,在hadoop.security.groups.cache.secs缓存条目过期后,下一个请求组成员身份的线程将查询组映射服务提供者以查找用户的当前组。在此查找过程中,发起该请求的线程将被阻塞,而其他请求相同用户组的线程将检索先前缓存的值。如果刷新失败,执行刷新的线程将抛出异常,并且该过程将在下一个请求查找该值的线程上重复。如果查找反复失败且缓存未更新,在hadoop.security.groups.cache.secs * 10秒后,缓存条目将被驱逐,所有线程都将阻塞,直到成功执行重新加载。

为了避免缓存条目过期时线程被阻塞,请将hadoop.security.groups.cache.background.reload设置为true。这将启用一个由hadoop.security.groups.cache.background.reload.threads指定的小型线程池,默认包含3个线程。启用此设置后,当查询缓存中的过期条目时,系统会立即返回过期结果,并在后台排队任务以刷新缓存。如果后台刷新失败,下一次对该缓存的请求会重新排队刷新操作,直到达到hadoop.security.groups.cache.secs * 10时限时,该缓存条目将被驱逐,此时所有相关线程将对该用户保持阻塞状态,直到成功重新加载为止。

为了避免向NameNode发送过多未知用户的请求,Hadoop采用了负缓存机制:当查询结果为空时,直接返回空用户组而不再执行更多用户组映射查询。缓存失效时间可通过hadoop.security.groups.negative-cache.secs进行配置,默认值为30秒。这意味着如果用户组映射服务提供商未返回某用户的用户组信息,则在30秒内不会对该用户重复执行查询。

LDAP 组映射

该提供程序支持使用JNDI API进行简单密码认证的LDAP。必须设置hadoop.security.group.mapping.ldap.url。这指的是用于解析用户组的LDAP服务器URL。它支持通过逗号分隔的列表配置多个LDAP服务器。

hadoop.security.group.mapping.ldap.base 配置LDAP连接的搜索基准。这是一个专有名称,通常是LDAP目录的根节点。获取给定用户名的组时,首先查找用户,然后查找用户结果对应的组。如果目录设置有不同的用户和组搜索基准,请使用hadoop.security.group.mapping.ldap.userbasehadoop.security.group.mapping.ldap.groupbase配置项。

在搜索和等待结果时可以设置最大时间限制。如果需要无限等待时间,请将hadoop.security.group.mapping.ldap.directory.search.timeout设置为0。默认值为10,000毫秒(10秒)。这是每个LDAP查询的限制时间。如果hadoop.security.group.mapping.ldap.search.group.hierarchy.levels设置为正值,则总延迟时间将受限于max(LDAP中的递归深度, hadoop.security.group.mapping.ldap.search.group.hierarchy.levels) * hadoop.security.group.mapping.ldap.directory.search.timeout

hadoop.security.group.mapping.ldap.base 配置了在解析组时向上遍历组层次结构的深度。默认情况下,限制为0时,用户必须明确在LDAP中被列为组成员才会被视为该组成员。否则,系统将向上遍历组层次结构hadoop.security.group.mapping.ldap.search.group.hierarchy.levels层。

可以通过配置hadoop.security.group.mapping.ldap.group.search.filter.pattern来使用带有不同参数的自定义组搜索过滤器,我们可以在此配置逗号分隔的值,配置的值将从LDAP属性中获取,并按照它们在此出现的顺序替换到组搜索过滤器中。例如,如果这里的第一个条目是uid,那么将从属性中获取uid,获取的值将用于替换组搜索过滤器中的{0},类似地,配置的第二个值将替换{1},依此类推。

注意:如果配置了hadoop.security.group.mapping.ldap.group.search.filter.pattern,无论其他参数如何设置,都将始终使用此组搜索过滤模式进行组搜索。

绑定用户

如果LDAP服务器不支持匿名绑定,请在hadoop.security.group.mapping.ldap.bind.user中设置绑定用户的专有名称。包含绑定用户密码的文件路径在hadoop.security.group.mapping.ldap.bind.password.file中指定。该文件应仅限运行守护进程的Unix用户可读。

多用户绑定

如果需要多个绑定用户,可以通过hadoop.security.group.mapping.ldap.bind.users指定。这些将代表用于连接LDAP时进行绑定的用户别名。然后每个别名都必须配置其专有名称和密码。这在必须重置绑定用户密码时非常有用。如果在连接LDAP时遇到AuthenticationException异常,LDAPGroupsMapping将切换到下一个绑定用户信息,并在必要时循环回退。

例如,如果:hadoop.security.group.mapping.ldap.bind.users=alias1,alias2,那么以下配置是有效的:hadoop.security.group.mapping.ldap.bind.users.alias1.bind.user=bindUser1 hadoop.security.group.mapping.ldap.bind.users.alias1.bind.password.alias=bindPasswordAlias1 hadoop.security.group.mapping.ldap.bind.users.alias2.bind.user=bindUser2 hadoop.security.group.mapping.ldap.bind.users.alias2.bind.password.alias=bindPasswordAlias2

Active Directory

默认配置支持与Active Directory服务器进行LDAP组名解析。

POSIX 用户组

如果LDAP服务器支持POSIX组语义(RFC-2307),Hadoop可以通过将hadoop.security.group.mapping.ldap.search.filter.user设置为(&(objectClass=posixAccount)(uid={0})),并将hadoop.security.group.mapping.ldap.search.filter.group设置为(objectClass=posixGroup)来执行LDAP组解析查询。

SSL

为确保连接安全,该实现支持通过SSL的LDAP(LDAPS)。通过将hadoop.security.group.mapping.ldap.ssl设置为true来启用SSL。此外,在hadoop.security.group.mapping.ldap.ssl.keystore中指定SSL连接的密钥库文件路径,并在hadoop.security.group.mapping.ldap.ssl.keystore.password中指定密钥库密码,同时确保hadoop.security.credential.clear-text-fallback为true。或者,将密钥库密码存储在文件中,并将hadoop.security.group.mapping.ldap.ssl.keystore.password.file指向该文件。出于安全考虑,该文件应仅对运行守护进程的Unix用户可读,并且为防止递归依赖,该文件应为本地文件。第一种方法即使用hadoop.security.group.mapping.ldap.ssl.keystore.password是强烈不建议的,因为它会在配置文件中暴露密码。

低延迟组映射解析

通常情况下,Hadoop通过执行两次LDAP查询来解析用户的组名:第一次查询获取用户对象,第二次查询使用用户的专有名称(Distinguished Name)查找所属组。对于某些LDAP服务器(如Active Directory),第一次查询返回的用户对象在其memberOf属性中已包含用户所属组的DN,而组名称就是其相对专有名称(Relative Distinguished Name)。因此,无需发送第二次查询即可从第一次查询结果推断出用户所属组,这可以减少由第二次查询引起的组名解析延迟。如果获取组名失败,系统将回退到典型的两阶段查询场景,发送第二次查询来获取组名。要启用此功能,请将hadoop.security.group.mapping.ldap.search.attr.memberof设置为memberOf,Hadoop将使用用户对象中的这个属性来解析组名。

如果LDAP服务器的证书不是由知名证书颁发机构签发的,请在hadoop.security.group.mapping.ldap.ssl.truststore中指定信任库的路径。与密钥库类似,在hadoop.security.group.mapping.ldap.ssl.truststore.password.file中指定信任库密码文件。

配置重试和具有故障转移功能的多个LDAP服务器

如果从LDAP服务器检索信息时遇到问题,请求将重试。要配置重试次数,请使用以下配置:

     <name>hadoop.security.group.mapping.ldap.num.attempts</name>
     <value>3</value>
     <description>
       This property is the number of attempts to be made for LDAP operations.
       If this limit is exceeded, LdapGroupsMapping will return an empty
       group list.
     </description>
    </property>

LDAP组映射还支持配置多个LDAP服务器和故障转移功能,以防特定实例不可用或出现异常。以下配置展示了如何配置3个LDAP服务器。此外,在切换到下一个服务器之前,每个服务器将尝试2次连接,总共尝试6次后才会最终失败。

<property>
  <name>hadoop.security.group.mapping.ldap.url</name>
  <value>ldap://server1,ldap://server2,ldap://server3</value>
  <description>
    The URL of the LDAP server(s) to use for resolving user groups when using
    the LdapGroupsMapping user to group mapping. Supports configuring multiple
    LDAP servers via a comma-separated list.
  </description>
</property>

<property>
  <name>hadoop.security.group.mapping.ldap.num.attempts</name>
  <value>6</value>
  <description>
    This property is the number of attempts to be made for LDAP operations.
    If this limit is exceeded, LdapGroupsMapping will return an empty
    group list.
  </description>
</property>

<property>
  <name>hadoop.security.group.mapping.ldap.num.attempts.before.failover</name>
  <value>2</value>
  <description>
    This property is the number of attempts to be made for LDAP operations
    using a single LDAP instance. If multiple LDAP servers are configured
    and this number of failed operations is reached, we will switch to the
    next LDAP server. The configuration for the overall number of attempts
    will still be respected, failover will thus be performed only if this
    property is less than hadoop.security.group.mapping.ldap.num.attempts.
  </description>
</property>

复合组映射

CompositeGroupsMapping 的工作原理是枚举 hadoop.security.group.mapping.providers 中的服务提供者列表。它会依次从列表中的每个提供者获取组信息。如果 hadoop.security.group.mapping.providers.combined 设置为 true,则合并所有提供者返回的组;否则返回第一个成功提供者的组信息。配置示例请参阅下一节。

多组映射提供程序配置示例

本示例展示了CompositeGroupsMapping的典型应用场景:当Hadoop认证使用信任AD域的MIT Kerberos时。在这种情况下,诸如hdfs、mapred、hbase、hive、oozie等服务主体可以存放在MIT Kerberos中,而终端用户仅来自受信任的AD域。对于服务主体,出于效率考虑可使用ShellBasedUnixGroupsMapping提供程序查询其所属群组;对于终端用户,则可采用LdapGroupsMapping提供程序。这样就能避免在仅使用LdapGroupsMapping提供程序时,需要为服务主体在AD中添加群组条目。若涉及多个被MIT Kerberos信任的AD域,可多次使用LdapGroupsMapping提供程序并配置不同AD域特定参数。本示例也演示了具体实现方法。以下是必要配置项。

  <name>hadoop.security.group.mapping</name>
  <value>org.apache.hadoop.security.CompositeGroupsMapping</value>
  <description>
    Class for user to group mapping (get groups for a given user) for ACL, which
    makes use of other multiple providers to provide the service.
  </description>
</property>

<property>
  <name>hadoop.security.group.mapping.providers</name>
  <value>shell4services,ad4usersX,ad4usersY</value>
  <description>
    Comma separated of names of other providers to provide user to group mapping.
  </description>
</property>

<property>
  <name>hadoop.security.group.mapping.providers.combined</name>
  <value>true</value>
  <description>
    true or false to indicate whether groups from the providers are combined or not. The default value is true
    If true, then all the providers will be tried to get groups and all the groups are combined to return as
    the final results. Otherwise, providers are tried one by one in the configured list order, and if any
    groups are retrieved from any provider, then the groups will be returned without trying the left ones.
  </description>
</property>

<property>
  <name>hadoop.security.group.mapping.provider.shell4services</name>
  <value>org.apache.hadoop.security.ShellBasedUnixGroupsMapping</value>
  <description>
    Class for group mapping provider named by 'shell4services'. The name can then be referenced
    by hadoop.security.group.mapping.providers property.
  </description>
</property>

<property>
  <name>hadoop.security.group.mapping.provider.ad4usersX</name>
  <value>org.apache.hadoop.security.LdapGroupsMapping</value>
  <description>
    Class for group mapping provider named by 'ad4usersX'. The name can then be referenced
    by hadoop.security.group.mapping.providers property.
  </description>
</property>

<property>
  <name>hadoop.security.group.mapping.provider.ad4usersY</name>
  <value>org.apache.hadoop.security.LdapGroupsMapping</value>
  <description>
    Class for group mapping provider named by 'ad4usersY'. The name can then be referenced
    by hadoop.security.group.mapping.providers property.
  </description>
</property>

<property>
<name>hadoop.security.group.mapping.provider.ad4usersX.ldap.url</name>
<value>ldap://ad-host-for-users-X:389</value>
  <description>
    ldap url for the provider named by 'ad4usersX'. Note this property comes from
    'hadoop.security.group.mapping.ldap.url'.
  </description>
</property>

<property>
<name>hadoop.security.group.mapping.provider.ad4usersY.ldap.url</name>
<value>ldap://ad-host-for-users-Y:389</value>
  <description>
    ldap url for the provider named by 'ad4usersY'. Note this property comes from
    'hadoop.security.group.mapping.ldap.url'.
  </description>
</property>

您还需要以与上述相同的方式为LDAP提供商配置其他属性,如hadoop.security.group.mapping.ldap.bind.password.file等。