大数据运维及安全@IT·互联网大数据

kerberos体系下的应用(yarn,spark on yar

2017-08-04  本文已影响2470人  PunyGod

kerberos 介绍

阅读本文之前建议先预读下面这篇博客
kerberos认证原理---讲的非常细致,易懂

Kerberos实际上一个基于Ticket的认证方式。Client想要获取Server端的资源,先得通过Server的认证;而认证的先决条件是ClientServer提供从KDC获得的一个有ServerMaster Key进行加密的Session Ticket(Session Key + Client Info)

image.png

大体逻辑流程如下:

kerberos 中的几个概念

简单的说, principals 类似于多用户系统中的用户名,每个server都对应一个 principals

principals由几个部分的字符串构成。
例如:

component1 / component2 @ REALM

  1. @ 后面是一个 principals 必不可少的部分 REALM,为大写英文字符。
  2. @ 前面是一个 principals 的具体身份,它可能由多个部分组成,使用/ 分割。

reborn@EXAMPLE.COM
代表的是一个属于EXAMPLE.COM领域的用户reborn
这类principals 我们称之为 User Principals。
还有一类我们称之为 Service Principals。 它代表的不是具体的user,而是服务:
yarn/ctum2f0302002.idc.xxx-group.net@IDC.XXX-GROUP.NET
比如上面的这个, / 前面的部分为 yarn,说明它代表的是 yarn的服务,/ 后面的部分则是DNS域名,@后面的则是每个principals都必须有的 REALM

上面所提及的 Client通过获得TGT向KDC申请用于访问Server的Ticket 就是通过 Service Principals 来向KDC 来申请Ticket的。

每个 principals 都有自己的 Master key 用来证明自己就是 principals的拥有者。同时 在 ClientKDCServerTGTTicket加密。具体方式可才考开篇的 博客链接。
一般来说,User Principals的 key是用户密码,Service Principals的key是随机数串,他们都分别被存放在 KDC中一份,keytab 文件中一份。

keytab文件就是一个密码本,除非对该用户重新生成keytab,否则这个文件是不会过期的,使用该keytab即可以登录相应的principals

获取TGT

从上面的概念上大家可以看出,为了访问有kerberos认证的服务,作为Client首先要先向KDC发起请求获取TGT 得到 KDC的授权,才继而才能申请对 service 的Ticket。

在业务系统中访问需要kerberos认证的服务

这个比较简单,如上节例子中可以看到,只需要改变当前进程环境下的tgt即可,可以使用 命令行也可以在代码中实现。该部分暂时不讨论 tgt的过期问题,后续会扩展分析。

编写yarn application提交到kerberos认证的集群中

这类业务可能比较少,因为各种框架都自行实现了 xxx on yarn的代码,比如 spark on yarn、flink on yarn。但是也有一些热门的框架还没有来得及实现on yarn。 如 tf on yarn,storm on datax on yarn ,datax on yarn或者apache twill。我们可以自己动手去完成一个 yarn application的工程,继而可以推测 其他框架的on yarn是怎么去实现的。
官网的参考文件如下:
Hadoop: Writing YARN Applications
YARN应用开发流程
上述文章已经很详细的讲解了如何编写 yarn application,我们再这里不再累述,而我们的关注点在于提交到kerberos认证的集群

image.png

在上面这个图大概的描述了我们的 yarn application的逻辑流程,这里需要注意的是:

也就是说这三次的rpc通讯,我们的应用是需要与Yarn进行通讯的,在kerberos认证的系统中,换句话说,我们需要与yarn service 进行通讯的Ticket

也就是说这三次的rpc通讯,我们的应用是需要与HDFS进行通讯的,在kerberos认证的系统中,换句话说,我们需要与hdfs service 进行通讯的Ticket

还有一个问题需要注意的是,在应用中,我们发起RPC通讯 可能在不同的机器上这个时候如何进行构造相同的环境是我们这里需要表述的东西;

image.png

可以看到 AM端的 初始UserGroupInformation是不带要tgt的, 也就是说,没办法进行kerberos认证流程,AM端不管是与yarn还是 hdfs的通讯都应该是使用Token的。在图片中Token列表中,我们看到出现了一个 名字叫 YARN_AM_RM_TOKEN ,这个并不是我们Client加进去的,但是可以确信的是AM使用该token与RM进行通讯,这个token哪里来的呢?

带着这个疑问,我们需要从Client开始扒拉一下代码了,在client端我们使用 YarnClient 将我们的启动的信息提交给了RM,这个YarnClient是经过kerberos认证的连接,那么我们可以看下RM端是怎么来处理这个 启动ApplicationMaster请求的。我们提交给RM的是一个名叫ApplicationSubmissionContext, RM要从中创建出ContainerLaunchContext

image.png

这RM端的createAMContainerLaunchContext中,我们查到了我们的疑问之处,这里出现了

  // Finalize the container
  setupTokens(container, containerID);

进去看看这个方法做了什么?:

image.png image.png

我们看到了我们想要的东西,container中新的tokens除了我们老的ContainerLaunchContext中我们从client传递过来的tokens,还额外添加了AMRMToken,到了这里我们解决了我们上面的一个疑问:

AM和RM通讯是使用Token来认证的,这个AMRMToken是RM端启动am的container的时候加塞进来的。

现在整理一下我们逻辑,启动之后AM使用** YARN_AM_RM_TOKEN来和RM通讯,使用 HDFS_DELEGATION_TOKEN**来和hdfs filesystem通讯,那么,AM是怎么通知NN来启动自己的 excutor的呢?不妨再看一下代码。

image.png

上面的图很明了了,nmTokens由RM提供给AM,在AM创建NMClientAsync的时候,

image.png
从单例 NMTokenCache 中获取到 nmTokens来进行连接NN。

到此,AM中的认证问题,我们已经整明白了,那边由AM,启动的其他的container的认证呢?,其实套路是一样的!

          LOG.info("Launching a new container."
                  + ", containerId=" + container.getId()
                  + ", containerNode=" + container.getNodeId().getHost()
                  + ":" + container.getNodeId().getPort()
                  + ", containerNodeURI=" + container.getNodeHttpAddress()
                  + ", containerResourceMemory="
                  + container.getResource().getMemory()
                  + ", containerResourceVirtualCores="
                  + container.getResource().getVirtualCores()
                  + ", command: " + command);
          ContainerLaunchContext ctx = ContainerLaunchContext.newInstance(
                  localResources, env, Lists.newArrayList(command), null, setupTokens(), null);
          appMaster.addContainer(container);
          appMaster.getNMClientAsync().startContainerAsync(container, ctx);

只需要把AM中的token做传递即可。

长任务在kerberos系统中执行,以spark为例子

什么是长任务? 就是long-running services,长时间运行的任务,可能是流也可以不是。
那么为什么,要把长任务单独来说呢,因为从上述的yarn应用的描述,我们知道,am和excutor中使用的是token来访问hdfs和rm 的,token是有时效性的我们是知道的,那么,长时间运行,token肯定会失效,如果token失效的话,肯定就不能访问hdfs了。所以这个就是 long-running 任务需要考虑的东西。
spark on yarn模式,分为两种: 一种是 yarn client模式,一种是yarn cluster模式。一般来说业务上都会使用yarn cluster模式来执行,但是随着分析类工具的推出,比如zeppelin,jupter的使用, 常驻的yarn client 所以这两种模式都很重要。为了把事情讲清楚,我们两种方式分类来说明,本章节源码(1.6.0)通读可以较多。

yarn clientyarn cluter 说到底都是yarn application,那么client 和 cluster的区别到底区别在哪呢?-- Spark Driver是在本地运行还是在AM中来执行

扩展阅读
过往记忆
kerberos_and_hadoop

yarn cluster 模式

image.png

至此,实际上启动的过程大概就是这样,那么现在我们需要对我们关心的问题来具体分析:

建立的saslRPC连接只有空闲时间超过10s中,连接才会被关闭,如果我们的AM保持着对RM的心跳,也就不需要重新与RM建立连接(读者可以推演一下RM发生准备切换的情景)。

yarn client 模式

image.png

这里只讲一下和 yarn cluster的不同之处:


我们上面所说的 hdfs的token刷新都是在用户使用 --keytab的方式提交的,如果不是以这种方式提交的长任务,token肯定会失效,会报错。

上一篇 下一篇

猜你喜欢

热点阅读