Hadoop 组映射

概述

用户的组由组映射服务提供程序确定。Hadoop 支持各种组映射机制,由 hadoop.security.group.mapping 属性配置。其中一些,例如 JniBasedUnixGroupsMappingWithFallback,使用操作系统的组名解析,不需要配置。但 Hadoop 还通过 LDAP 和 LDAP 与操作系统组名解析的组合支持特殊的组映射机制,这需要额外的配置。hadoop.security.group.mapping 可以是以下之一

  • org.apache.hadoop.security.JniBasedUnixGroupsMappingWithFallback

    默认实现。它将确定 Java Native Interface (JNI) 是否可用。如果 JNI 可用,该实现将使用 hadoop 中的 API 为用户解析一组组。如果 JNI 不可用的,则使用基于 shell 的实现 ShellBasedUnixGroupsMapping

  • org.apache.hadoop.security.JniBasedUnixGroupsNetgroupMappingWithFallback

    类似于 JniBasedUnixGroupsMappingWithFallback。如果 JNI 可用,它将使用 Hadoop 本机 API 获取 netgroup 成员资格;否则使用 ShellBasedUnixGroupsNetgroupMapping

  • org.apache.hadoop.security.ShellBasedUnixGroupsMapping

    此实现使用 bash -c groups 命令(适用于 Linux/Unix 环境)或 net group 命令(适用于 Windows 环境)来解析用户的组列表。

  • org.apache.hadoop.security.ShellBasedUnixGroupsNetgroupMapping

    此实现类似于 ShellBasedUnixGroupsMapping,但它执行 getent netgroup 命令来获取 netgroup 成员资格。

  • org.apache.hadoop.security.LdapGroupsMapping

    一种备用实现,它直接连接到 LDAP 服务器以解析组列表。但是,此提供程序仅在所需组专门驻留在 LDAP 中且未在 Unix 服务器上实现时才应使用。LdapGroupsMapping 支持 SSL 连接和 POSIX 组语义。有关详细信息,请参阅 LDAP 组映射 部分。

  • org.apache.hadoop.security.CompositeGroupsMapping

    此实现组合其他组映射提供程序以确定组成员资格。这允许组合现有的提供程序实现并组合一个虚拟的新提供程序,而无需自定义开发来处理复杂的情况。有关详细信息,请参阅 复合组映射 部分。

对于 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 级。

绑定用户

如果 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 (LDAPS) 进行 LDAP。通过将 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 查询来解析用户的组名:第一个查询获取用户对象,第二个查询使用用户的专有名称来查找组。对于某些 LDAP 服务器(如 Active Directory),第一个查询中返回的用户对象还包含其 memberOf 属性中用户组的 DN,并且组的名称是其相对专有名称。因此,可以从第一个查询中推断出用户的组,而无需发送第二个查询,并且可以减少第二个查询导致的组名解析延迟。如果无法获取组名,它将回退到典型的两个查询方案,并发送第二个查询以获取组名。要启用此功能,请将 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.combinedtrue,则合并所有提供商返回的组;否则,返回第一个成功提供商中的组。有关示例配置,请参见以下部分。

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

此示例说明了 `CompositeGroupsMapping` 的典型用例,其中 Hadoop 身份验证使用信任 AD 域的 MIT Kerberos。在这种情况下,服务主体(例如 hdfs、mapred、hbase、hive、oozie 等)可以放置在 MIT Kerberos 中,但最终用户仅来自受信任的 AD。对于服务主体,可以使用 `ShellBasedUnixGroupsMapping` 提供程序高效地查询其组,而对于最终用户,可以使用 `LdapGroupsMapping` 提供程序。这避免了在仅使用 `LdapGroupsMapping` 提供程序时为服务主体在 AD 中添加组条目。如果涉及多个 AD 并且受 MIT Kerberos 信任,则 `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 等,方式与上面相同。