并发 kinit 导致 kerberos GSS initiate failed 定位与解决

线上任务调度工具执行 Hadoop Hive 相关的任务会偶发任务执行失败的问题,日志报错为 Kerberos 认证失败。查看调度工具的运行逻辑:每次执行任务前先 kinit 认证,再执行任务,考虑到最近迁移任务量大,且多为单个租户的任务,怀疑是该租户并发 kinit 导致,经一系列的测试与验证,笔者确认了问题的原因,使用一种更优的方案解决了集群租户并发认证的问题。

1.问题发现

大数据平台 Hadoop 的安全认证是基于 Kerberos 实现的。 Kerberos 是一个网络身份验证协议,用户只需输入身份验证信息,验证通过获取票据即可访问多个接入 Kerberos 的服务。

Kerberos 认证方式有两种:

  1. 使用密码认证:使用用户密码通过 kinit 认证, 获取到的 TGT 存在本地凭证缓存当中, 供后续访问服务认证使用。一般在交互式访问中使用。
  2. 使用 keytab 认证:用户通过导出的 keytab 可以免密码进行用户认证, 后续步骤一致。一般在应用程序中配置使用。

目前大数据平台租户执行任务,主要采用第一种 kinit 的方式实现认证, 为了保证 kerberos 认证不过期,调度系统在每次执行任务时会先 kinit 认证刷新凭证 echo $passwd | kinit

这种方式简单可用,但最近总是频发认证失败的问题。报错如下:
GSS initiate failed: No valid credentials provided Failed to find any kerberos tgt

2.问题定位

每次执行前都会 kinit,怎么会还找不到 kerberos tgt,为了定位于解决问题,我们先来看下 kinit 的解释

kinit 命令用于获取和缓存 principal 的初始票证授予票证(凭证)。此票证用于 Kerberos 系统进行验证。只有拥有 Kerberos 主体的用户才可以使用 Kerberos 系统。有关 Kerberos 主体的信息,请参见 kerberos(5)。
当使用 kinit 而未指定选项时,实用程序将提示您输入 principal 和 Kerberos 口令,并尝试使用本地 Kerberos 服务器验证您的登录。如果需要,可以在命令行上指定 principal。
如果登录尝试通过了 Kerberos 的验证,kinit 将检索您的初始票证授予票证并将其放到票证高速缓存中。缺省情况下,票证存储在 /tmp/krb5cc_uid 文件中,其中 uid 表示用户标识号。票证将在指定的生命周期后过期,之后必须再次运行 kinit。高速缓存中的任何现有内容都将被 kinit 销毁。[1]

考虑到最近单个租户的并发任务量大(大量任务在调度系统配置同一时间,定时调度),怀疑是并发 kinit 导致 - kinit 操作会重新覆盖写 krb 文件 - 即并发场景下有 krb 文件不可读的情况。

为了验证猜想,做了如下测试:

  1. 删除用户的凭证文件: /tmp/krb5cc_uid,执行 hdfs 命令。报同样的认证错误
  2. 编写测试脚本,并发 kinit 后执行 hdfs 任务,此认证报错问题必现

3.问题解决

如何保证租户并发场景下,认证成功且不过期,想到两种解决思路:

  1. 认证失败后重试,重新 kinit,必须封装平台级 API 才行(并发依然可能出错)
  2. 不用每次执行任务都 kinit,改为定期按需进行 kinit 认证更新凭证 , 且保证并发的场景不出错

根据当前场景,采用第二种方案,简单快速,可实现,这种方案的优点如下:

  1. 按需 kinit,过滤绝对多数的重复的 kinit, Kerberos KDC 认证服务器的压力可以降低 90% 以上。
  2. 最小化代码入侵

解决过程如下:
首先通过 klist 查看 认证相关信息,如 ticket 的文件路径和名称,失效时间等

[chenyao_yy@CD/WJ2FD-L350-ZYC1Q-colletion-DELLR730-SV013 ~]$ klist
Ticket cache: FILE:/tmp/krb5cc_30022_3zIUZUTNbD
Default principal: chenyao_yy@KDC

Valid starting     Expires            Service principal
08/14/18 17:02:12  08/16/18 17:02:12  krbtgt/KDC@KDC
    renew until 08/21/18 17:02:12

每次执行任务前,klist 查看票据失效时间,当快要失效时(目前定义 2 hours),才进行 kinit,至此解决了按需 kinit 的问题;

并发的问题借鉴了锁的概念,通过锁互斥执行 kinit。保证一次只有一个进程能 kinit 成功。 经查询 linux 有文件锁的概念,经测试可用 - flock[2]

3.1 Linux flock 文件锁

简单说下使用:
flock -xn /tmp/${user}_kinit_lock -c "echo $passwd | kinit"

  • 参数说明:-x:独占锁 ;-n:未获取到锁立马退出,避免阻塞
  • 获取文件 /tmp/${user}_kinit_lock 独占锁,获取到才能执行 kinit,执行结束释放锁(租户的文件锁通过用户名来区分)。
  • 未获取到文件锁直接退出(跳过 -c 后的命令)

这里需要特殊说明是:未获取到锁或者 -c 命令执行失败都会返回 1($?=1)

3.2 kinit 脚本实现

具体实现脚本如下:

#!/bin/bash
# kinit helper - 解决单用户并发 kinit 报错问题
# 只有当 expiredTime 剩余时间小于 2 小时才进行 kinit 操作,且只允许一次 kinit
source /etc/profile

# 输入参数 $1=租户 $2=租户密码
proxyUser=$1
passwd=$2
# 是否需要 kinit (默认需要=0)
needKinit=0
# 过期剩余时间阈值 2 小时
let maxLeftTime=2*60*60

# 检查是否需要重新 kinit,存在如下两种情况:
# 1.krb 文件不存在
# 2.klist 过期时间,还剩不到 2 小时
check_if_need_kinit(){
  klist > /dev/null
  if [ $? -eq 0 ]; then

    # check principal is match
    principal=$(klist | awk '{print $3}' | sed -n '2p' | cut -d@ -f1)
    echo "default principal: $principal"
    if [ "$principal" != "${proxyUser}" ]; then
       echo "expect principal: $proxyUser, will re-kinit"
       return
    fi

    # check klist has renew info
    klist | grep renew
    if [ $? -eq 1 ]; then
       klist
       echo "klist info exception !"
       return
    fi

    expiredTime=$(klist | sed -n "5,1p" | awk '{print $2,$3}')
    expiredTimeFT=$(date -d "${expiredTime}" +"%Y-%m-%d %H:%M:%S")
    expiredTimestamp=$(date -d "$expiredTimeFT" +%s)
    currentTimestamp=$(date +%s)
    if [ $expiredTimestamp -gt $currentTimestamp ]; then
      let free=$expiredTimestamp-$currentTimestamp
      # 剩余时间大于所设阈值,则不需要 kinit
      if [ $free -gt $maxLeftTime ]; then
         nowTime=$(date "+%Y-%m-%d %H:%M:%S")
         echo "NowTime: $nowTime, ExpiredTime: $expiredTimeFT, no need to kinit!"
         needKinit=1
      fi
    fi
  else
    echo "krb file does not exist!"
  fi
}

# 传入参数检查
if [  $# != 2 -o "$proxyUser" = "" -o "$passwd" = "" ]; then
    echo "some curtionl params is null ! please check your prams"
    exit 1
fi

check_if_need_kinit
if [ $needKinit -eq 0 ]; then
  user=$(whoami)
  # 抢占独占锁,进行 kinit 操作
  echo "try to kinit, command: [ echo password | kinit $proxyUser ]"
  flock -xn /tmp/${user}_kinit_lock -c "echo '$passwd' | kinit $proxyUser"
  if [ $? -eq 0 ]; then
    echo "kinit success!"
  else
    echo "kinit faild: may be kinit by other concurrent process or password is incorret!"
  fi
fi

实际脚本中 考虑了认证用户错位 - principal 不匹配,认证 klist 信息不全认证失败等场景,较大程度提高了认证的可用性。

参考:
[1] https://docs.oracle.com/cd/E56344_01/html/E54075/kinit-1.html
[2] http://www.jusene.me/2017/02/22/flock/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容