弹性计算平台-Spark访问Kerberized-HDFS
概述
本文是笔者在前司建设的基于Kubernetes构建的弹性计算平台集成Spark的相关使用文档,我们是国内最早基于Kubernetes运行Spark计算任务的团队之一
Spark 计算目前读写都是在 non-Kerberized 集群上的,因为 HDFS 加固的需求,所以需要读写 Kerberized HDFS。之前通过弹性计算平台提交的 Spark 计算带上了 Keytab 相关几个 conf,还是会出现权限验证不通过的情况。
|
|
之前出现错误的信息如下:
错误的原因是因为 kinit
的问题,以及 Keytab 和 Principal 的理解。
以下是一个正常部署 KDC 的一个流程。
|
|
Proposal
Spark Client
HDFS 采用 Kerberos 进行安全验证了,那么 Spark 用户访问的方式就只有两种选择。
- Principal和密码,本地
kinit
之后TGT会被缓存起来,Spark Driver会去读取,并且透传到Executor - 每次spark-submit都通过conf指定Keytab相关选项
关于 Spark 如何去读取缓存的 TGT,Spark 的 HadoopKerberosKeytabResolverStep
有详细说明。
This step does all the heavy lifting for Delegation Token logic. This step assumes that the job user has either specified a principal and keytab or ran $kinit before running spark-submit. With a TGT stored locally, by running UGI.getCurrentUser you are able to obtain the current user, alternatively you can run UGI.loginUserFromKeytabAndReturnUGI and by running .doAs run as the logged into user instead of the current user. With the Job User principal you then retrieve the delegation token from the NameNode and store values in DelegationToken. Lastly, the class puts the data into a secret. All this is appended to the current HadoopSpec which in turn will append to the current DriverSpec.
简单说一句,这里就是读取缓存 TGT 的代码逻辑,依赖的是 Hadoop Common 里关于 Keytab 的 API。
Ticket 更新的问题。Kerberos 里,有两个概念特别容易让人糊涂,
- ticket_lifetime
- renew_lifetime。
打个比方,前者是2d,后者是7d。
意思是 kinit
了之后,这个缓存的 ticket 可以用2d,7天内 kinit -R
都可以刷新这个 ticket,然后这个 ticket 又获得有效期2d了。而 renew_lifetime 表示 kinit -R
这个操作7d内进行,超过7d,就没法 renew 了。那7d之后怎么办呢?可以再次 kinit
一下,获取新的 ticket。
因为 kinit -kt
是需要 keytab 的,kinit -R
是不需要的,所以才会有这样的区别。要记得,keytab 是永远不会过期的,里面存的是 KDC 数据库里的 principal 和 key。
|
|
Security
一些关于安全的 concerns:
- 每个用户提交任务都需要特定的Keytab,增加了DBA的工作量,而且管理也比较麻烦
- 统一账号不利于HDFS的审计
- Keytab封装在镜像中,用户也是有可能拿到Keytab,从而造成安全风险
关于 Keytab 的处置,调研到的一些方案。
- Embedded – have the container refresh the token itself
- Externalized – have an external service refresh the token in the container
- Sidecar – Refresh the token in a sidecar container, and share with the application container
讨论
在已有的镜像文件中,通过传递 Spark conf 是可以满足当前需求的(访问 Kerberized HDFS)。