CDH作为统一的企业级数据中心,往往是一个多租户的应用环境。在该环境中,不同用户会同时使用集群资源。如何保证用户数据不被任意篡改?如何保证任务的权限控制 (例如用户A不能任性地取消用户B的任务)?如何确保用户资源使用不超过他们的配额?
1. 开启HDFS权限检查 (默认是开启的)
"Check HDFS Permissions"选中
2. 在集群中创建新用户,以cloudera-dev为例
# 增加用户组 [root]$ groupadd cloudera-dev # 增加用户 [root]$ useradd -g cloudera-dev cloudera-dev # 查看用户 cloudera-dev 所属的所有组 [root]$ groups cloudera-dev # Hadoop 创建相应的用户目录 [root]$ sudo -u hdfs hdfs dfs -mkdir /user/cloudera-dev [root]$ sudo -u hdfs hdfs dfs -chown cloudera-dev:cloudera-dev /user/cloudera-dev |
一般而言,创建新用户会在集群中每台机器上都创建同样的用户。不过理论上,为了运行该案例,只需要在安装了资源管理器 (Resource Manager) 的机器上创建相应用户即可。CDH默认情况下使用 whoami获取用户的信息, bash -c groups xxx 获取用户与组之间的映射关系,并使用这两份信息进行ACL验证
3. 运行第一个MapReduce示例程序 "word count"
[root]$ su cloudera-dev [cloudera-dev]$ echo "Hello World Bye World" > file0 [cloudera-dev]$ echo "Hello Hadoop Goodbye Hadoop" > file1 [cloudera-dev]$ hdfs dfs -mkdir -p /user/cloudera-dev/wordcount/input [cloudera-dev]$ hdfs dfs -put file* /user/cloudera-dev/wordcount/input [cloudera-dev]$ hadoop jar /opt/cloudera/parcels/CDH/jars/hadoop-examples.jar wordcout wordcount/input wordcount/output [cloudera-dev]$ hdfs dfs -getmerge wordcount/output output.txt [cloudera-dev]$ cat output.txt Bye 1 Hadoop 2 Hello 2 Goodbye 1 World 2 |
4. 开启资源管理器ACL并设置相应的管理ACL (Admin ACL)
其中yarn.acl.enable默认值为true。而对于yarn.admin.acl默认值为*,意味着所有人都可以管理Resource Manager (比如运行yarn rmadmin)、管理已提交 (比如取消 kill) 的任务。格式为 "以逗号分隔的用户列表+空格+以逗号分隔的用户组列表",例如 "user1,user2 group1,group2"。如果只有组信息,需要在最前端加入一个空格,例如" group1,group2"。另外特别需要注意的是必须至少将" yarn"加入到用户列表中,默认安装CDH后,有关YARN服务的命令会以yarn用户的身份进行运行,若yarn不设置于yarn.admin.acl中,会出现权限相关的错误 (例如刷新动态资源池)。
在该示例中,yarn.admin.acl列表中包含一个用户yarn以及一个组cloudera-dev。博主注:配置在yarn.admin.acl中的用户、用户组并不能任意在资源池 (或者叫资源队列) 中提交任务。
5. 关闭未声明资源池的自动生成
默认情况下,"Allow Undeclared Pools"可选项是选中的,需要关闭。否则如果用户指定一个尚未声明的资源池时,比如prod,YARN将会自动生成一个prod资源池。配置文件修改后需要重新启动YARN服务,重新部署客户端配置。
6. 配置“若用户提交任务不指定特定的queue,就使用default queue”
默认情况下,“Fair Scheduler User As Default Queue”可选项是选中的,意味着如果用户提交任务时如果不指定特定的queue,就使用以用户命名的queue。
7. 进入动态资源池 (Dynamic Resource Pools) 配置页面
访问动态资源池管理页面
选择配置选项 (Configuration,右上角)
Resource Pools: 展示了当前资源池的分配情况,默认情况下,只有一个资源池 root.default。在该示例中,dev 是自定义的资源池。权重 (weight) 定义了资源池之间分配资源的比例。示例中,dev设置权重为4而 default 的权重为1,那么集群资源的 80% 会被分配给 dev。注意,这里提到的资源分配不是一个静态的概念,例如当前资源池 dev 中没有任务正在运行,那么资源池 default 是允许使用超过20%的集群资源,比如50%。博主注:资源池的配置信息会保存在fair-scheduler.xml文件中,Resource Manager会周期性读取该配置文件,因此资源池配置允许在线修改,即修改后不需要重新启动Yarn。
8. 为资源池 root 配置资源池 ACL
点击资源池 root 对应的 "Edit" 按钮
在通用 (General) 栏,设置资源池 root 的调度算法,一般使用默认的DRF (根据CPU、Memory资源进行调度)。博主注:队列的"Submission Access Control"与"Administrator Access Control"的配置会自动继承子队列中,比如在root的"Submission Access Control"中配置用户alex,那么即使root.test的"Submission Access Control"中配置为空,用户alex也可以向队列root.test提交Yarn应用程序。
在YARN栏,设置资源池权重,资源约束等
在提交访问控制 (Submission Access Control) 栏设置哪些用户或用户组可以向该资源池提交任务
在管理访问控制 (Administration Access Control) 栏设置哪些用户或用户组可以对资源池中的任务进行管理
9. 为资源池 dev 配置资源池 ACL
可以使用与 root 相同的ACL配置,也可以使用不同的配置,该示例假设使用相同的设置。
10. 测试
测试一:用户 root 向资源池 dev 提交 word count 任务
[root]$ hadoop jar wordcount-0.9.0.jar com.cloudera.example.WordCount -Dmapreduce.job.queuename=dev wordcount/input wordcount/output ... Exception in thread "main" java.io.IOException: Failed to run job: User root cannot submit applications to queue root.dev ... |
注意:这里的word count是自定义的,与CDH自带的word count示例的唯一区别在于,自定义word count的Mapper程序在运行时首先使用Thread.sleep (300 * 1000) 休眠5分钟。这主要是为了后续对资源池管理的测试
测试二:用户 root 取消用户 cloudera-dev 提交的、运行于资源池 dev 中的 word count 任务
用户cloudera-dev向资源池dev提交word count任务
[cloudera-dev]$ hadoop jar wordcount-0.9.0.jar com.cloudera.example.WordCount -Dmapreduce.job.queuename=dev wordcount/input wordcount/output ... |
用户root查询相应任务的id,假设获得任务id为job_1421512955131_0006
[root]$ hadoop job -list ... |
用户root取消 (kill) 该任务
[root]$ hadoop job -kill job_1421512955131_0006 ... Exception in thread "main" java.io.IOException: org.apache.hadoop.yarn.exceptions.YarnException: Java.security.AccessControlException: User root cannot perform operation MODIFY_APP on application_1421512955131_0006 ... |
测试三:用户 alex (属于组 cloudera-dev) 取消用户 cloudera-dev 提交的、运行于资源池 dev 中的 word count 任务
增加用户alex,设置所属组cloudera-dev
[root]$ useradd -g cloudera-dev alex |
用户cloudera-dev向资源池dev提交word count任务
[cloudera-dev]$ hadoop jar wordcount-0.9.0.jar com.cloudera.example.WordCount -Dmapreduce.job.queuename=dev wordcount/input wordcount/output ... |
用户alex查询相应任务的id,假设获得任务id为job_1421512955131_0006
[alex]$ hadoop job -list ... |
用户alex取消 (kill) 该任务
[alex]$ hadoop job -kill job_1421512955131_0006 ... INFO impl.YarnClientImpl: Killed application application_1421512955131_0006 Killed job job_1421512955131_0006 ... |
11. Placement Rules
通过参数mapreduce.job.queuename可以显示地指定一个Yarn应用程序运行所在的资源池 (每个应用程序的运行都必须在资源池)。如果没有显示指定资源池,Yarn会根据一系列的规则 (Placement Rule) 自动生成资源池的名字。这些规则可以通过Cloudera Manager进行配置,如下所示:
根据该规则:
Yarn首先检查用户alex (用户组dev) 是否显示指定了资源池,并且资源池已经预先定义好了:
是 -> 运行
否 -> 检查root.alex资源池是否已经预先定义好了:
是 -> 运行
否 -> 检查root.dev资源池是否已经预先定义好了:
是 -> 运行
否 -> 使用default资源池进行运行
另外,目前在Cloudera Manager上虽然可以定义"嵌套式用户队列" (Nested User Queue),但是尚未允许就嵌套式用户队列设置Placement Rule。因此如果需要使用该功能,只能通过直接编写XML的方式实现。