【AICon】探索八个行业创新案例,教你在教育、金融、医疗、法律等领域实践大模型技术! >>> 了解详情
写点什么

Rancher 实战案例 | kube-api-auth 日志中出现大量错误信息怎么办?

  • 2020-05-25
  • 本文字数:3792 字

    阅读完需:约 12 分钟

Rancher实战案例 | kube-api-auth日志中出现大量错误信息怎么办?

为了让大家能够在实际应用场景中更顺利地使用 Rancher,我们推出 Rancher 实战案例系列。该系列的文章均为生产环境中遇到的实际问题,Rancher 研发团队将基于此问题的解决过程,写出问题排查思路。本文为该系列的第一篇,分享 Rancher kube-api-auth 组件的一个问题排查记录。

前言

业界应用最广泛的 Kubernetes 管理平台 Rancher 经过多年的发展,无论是在开源社区还是在商业体系中,都拥有了大量用户。但是,正如你所知,没有任何产品是十全十美的,在用户的业务落地实践中,我们的产品也存在一些缺陷。而在我们的技术团队的支持下,许多问题也得到了改善和解决。本文我们精选了实战问题处理案例,一是分享 Rancher 技术团队成熟的经验供大家参考,二是让更多用户参与进来共同探索切磋技艺,我们坚信寻找答案的路途永远没有终点。


本文,我们将分享 Rancher kube-api-auth 组件的一个问题排查记录。

排查记录

问题描述

某客户的托管集群在经历一些操作后(操作记录未能还原),在某托管集群的 system 项目中的 kube-api-auth Pod 中不断有错误日志输出,错误信息如下:



由于操作记录没有还原,我们未能找到精准的重现方式。而且客户的环境只能远程操作,排查问题也非常不方便。

基本原理

Rancher 是支持多集群管理的平台,用户可以通过 rancher-server API 访问到托管集群的 Kubernetes API。在访问过程中,需要 authentication 信息,authentication 方式由 Rancher 提供。但是,在实际使用中要考虑一些特殊场景:


  1. 如果 rancher-server 宕机无法访问,用户能够直接访问托管集群 api

  2. 考虑到地理远近访问,用户有时候希望不通过 rancher-server,而直接访问托管集群 api


解决以上问题,就是 kube-api-auth 存在的价值,Rancher 会在所有的创建 RKE 集群中部署 kube-api-auth。Kuerbnetes 的 authentication 有很多方式,Rancher 在对接自己用户体系时,采用的是 webhook-token 方式,参考:


https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication


官网中也对集群访问方式有详细描述:


https://rancher.com/docs/rancher/v2.x/en/cluster-admin/cluster-access/ace/


另外一张架构图也很好说明了这两种机制:一种是通过 Rancher server 和 agent 的 tunnel 访问托管集群的 API,authentication 在 Rancher server 已经实现;另一种是直接访问托管集群 API,这时 authentication 主要靠托管集群内的 kube-api-auth 实现。



我们通过 kubectl 来更具体了解 kube-api-auth 的作用。Rancher 本身由生成集群 kubeconfig 的功能,你登录一个用户,可以得到的 kubeconfig 大致如下:


apiVersion: v1kind: Configclusters:- name: "c1"  cluster:    server: "https://*****/k8s/clusters/c-cn2rq"    certificate-authority-data: "xxxx"- name: "c1-ip-172-31-24-41"  cluster:    server: "https://172.31.24.41:6443"    certificate-authority-data: "xxx"
users:- name: "c1" user: token: "kubeconfig-user-gc4s9.c-cn2rq:**********"
contexts:- name: "c1" context: user: "c1" cluster: "c1"- name: "c1-ip-172-31-24-41" context: user: "c1" cluster: "c1-ip-172-31-24-41"
current-context: "c1"
复制代码


我们可以看到几个关键信息:


  • User token 的格式,冒号分割的两部分,可以理解为 access key 和 secret

  • Context 包含两个,一个 rancher-server 入口,一个是托管集群 kube-api 入口;默认使用 rancher-server 入口


当我们用“c1”context 访问,使用 kubectl 随意获取一些资源,观察 kube-api-auth 的 logs,会发现没有任何输出。原因很简单,通过 rancher-server 入口访问,authentication 不走 webhook。它会在 rancher-server 中通过 tcp-proxy via websocket 方式访问托管集群 api,这种情况 authentication 没有走 webhook,直接内部证书授权方式。


当我们用“c1-ip-172-31-24-41” context 访问,观察 kube-api-auth 的 logs,会发现类似信息:


time="2020-02-18T05:30:53Z" level=info msg="Starting Rancher Kube-API-Auth service on 127.0.0.1:6440"time="2020-02-18T06:09:56Z" level=info msg="Processing v1Authenticate request..."time="2020-02-18T06:09:56Z" level=info msg="  ...looking up token for kubeconfig-user-gc4s9.c-cn2rq"time="2020-02-18T06:09:57Z" level=info msg="{\"apiVersion\":\"authentication.k8s.io/v1beta1\",\"kind\":\"TokenReview\",\"status\":{\"authenticated\":true,\"user\":{\"username\":\"user-gc4s9\"}}}"
复制代码


这种情况下,kube-api-auth 是起作用的,而且在 logs 我们也能看 user token 信息,它完全能和 kubeconfig 里面的对应上。user token 的校验信息实际上是存在托管集群的某个 CRD 里面,kube-api-auth 的逻辑就是从 reqeust 信息中获取 token,并和本地 CRD 数据对照:


# kubectl get clusterauthtokens -n cattle-systemNAME                            AGEkubeconfig-user-gc4s9.c-cn2rq   13d
# kubectl get clusterauthtokens kubeconfig-user-gc4s9.c-cn2rq -n cattle-system -o yamlapiVersion: cluster.cattle.io/v3enabled: truehash: $1:fad9a80a83333248:15:8:1:***********kind: ClusterAuthTokenmetadata: creationTimestamp: "2020-02-05T03:06:18Z" generation: 1 labels: cattle.io/creator: norman name: kubeconfig-user-gc4s9.c-cn2rq namespace: cattle-system resourceVersion: "1047" selfLink: /apis/cluster.cattle.io/v3/namespaces/cattle-system/clusterauthtokens/kubeconfig-user-gc4s9.c-cn2rq uid: 5ec4fc46-5030-45fb-b715-1117a5825b72userName: user-gc4s9
复制代码


这里我们需要注意 request user token 的格式,一定是冒号分割的两部分。一旦是非法格式,kube-api-auth 就会拒绝校验,并报出之前问题提到的 logs 信息:“found 1 parts of token”。

原因分析

根据上面分析的基本原理,我们可以知道触发 kube-api-auth 产生 error logs 有两个前提:


  • 通过 kube-api-auth 鉴权访问托管集群

  • 访问托管集群时 user-token 不合法


针对第一个前提,我们知道 Kubernetes 可以开启多种 authentication,在 RKE 中就支持了 X509 Client Certs/ServiceAccount/Webhook token 这些类型,多种 authentication 是可以并存的。Kubernetes 官方文档中有描述:


https://kubernetes.io/docs/reference/access-authn-authz/controlling-access/#authentication

Multiple authentication modules can be specified, in which case each one is tried in sequence, until one of them succeeds.


也就说对于某个 kube-api-client,如果 X509 Client Certs/ServiceAccount 的鉴权都失败,那么一定会走到 Webhook token。


X509 Client Certs 一般不会暴露用户使用,ServiceAccount 是常见的使用方式,ServiceAccount 的本质是会生成一个 secret(保存 JWT token),当 Pod 启动时,会放在固定目录下提供 kube-api-client 使用:


root@ip-172-31-24-41:~# ls -ahl /var/run/secrets/kubernetes.io/serviceaccounttotal 4.0Kdrwxrwxrwt 3 root root  140 Feb 18 09:49 .drwxr-xr-x 3 root root 4.0K Feb 18 09:49 ..drwxr-xr-x 2 root root  100 Feb 18 09:49 ..2020_02_18_09_49_08.912945351lrwxrwxrwx 1 root root   31 Feb 18 09:49 ..data -> ..2020_02_18_09_49_08.912945351lrwxrwxrwx 1 root root   13 Feb 18 09:49 ca.crt -> ..data/ca.crtlrwxrwxrwx 1 root root   16 Feb 18 09:49 namespace -> ..data/namespacelrwxrwxrwx 1 root root   12 Feb 18 09:49 token -> ..data/token
复制代码


假设一种场景,如果我们手动删除 ServiceAccount 对应的 secret,但不重建 Pod,这样导致 Pod 内的 secret 失效,然后观察 kube-api-auth 就可以看到大量 error log。这就是因为 secret 失效,导致 ServiceAccount 鉴权失败,进而 Kubernetes 尝试 Webhook token 鉴权,也就是通过 kube-api-auth。这时 kube-api-auth 获取 request token,而这个 token 是 kube-api-client 传过来失效的 secret JWT token,JWT token 和 webhook token 格式完全不同(没有冒号分割),就会看到“found 1 parts of token”。

解决方案

回到客户的问题本身,应该是某些造成了一些 serviceaccount 的 secret 被重建,比如:cattle serviceaccount,这个 serviceaccount 会用于运行 cluster-agent/node-agent/kube-auth-api 等组件。


这时,只要重建关键的 workload 就可以大概率解决。Rancher 托管的 workload 中,cluster-agent/node-agent/kube-auth-api 都关联了 cattle serviceaccount,重建这些 workload,让对应的 Pod 能够走默认的 serviceaccount 鉴权,就会减少报错概率。

总结

如前面所分析,Rancher 在 Kubernetes 中配置了多种鉴权模式,而 Kubernetes 在处理这些鉴权时,并没有严格固定的顺序。所以,只要 kube-auth-api 没有大批量日志错误是可以接受的,因为该请求后续可能被其他鉴权模式认证通过。反之,出现了大量 error log 则说明整个托管集群确实有问题,顺着本文思路排查,重建 cattle serviceaccount 大概率可以解决。另外,用户自己的 workload 如果依赖某个 serviceaccount,如果这个 serviceaccount 被重建,那么 workload 也会出现问题,这也是需要注意的。


2020-05-25 16:41925

评论

发布
暂无评论
发现更多内容

生产环境全链路压测建设历程 24:FAQ 5、6负载均衡、如何不影响正常业务?

数列科技杨德华

28天写作

28天带你玩转Kubernetes--第一天(课程介绍)

Java全栈封神

Kubernetes 云原生 k8s入门 28天写作 k8s教程

记一次JVM OOM 实战优化

AI乔治

Java 架构 JVM OOM

第2周课后练习-OOD的五大原则

潘涛

架构师训练营 4 期

三只猫

大作业一

fmouse

架构师训练营第 1 期

RocketMQ学习笔记

大刘

RocketMQ MQ 消息队列

序言 基层管理者技能修炼的九把刀

一笑

管理 28天写作

区块链挖矿系统APP软件开发

系统开发

单向链表合并实战

Andy

自下而上的问题清单

将军-技术演讲力教练

28天写作

SafePoint 与 Stop The World 全解(基于OpenJDK 11版本)

AI乔治

Java 架构 jdk JVM

架构师训练营大作业(二)

曾彪彪

「架构师训练营第 1 期」

解读《Java开发手册(泰山版)》- 会当凌绝顶,一览众山小

xcbeyond

Java Java开发手册 28天写作

学创业,读毛选 Jan 9, 2021

王泰

28天写作 读毛选,学创业

kill -9 导致 kafka 重启失败的惨痛经历!

AI乔治

Java kafka 架构

我们为什么要学习Springboot?

武哥聊编程

Java springboot SpringBoot 2 28天写作

架构师训练营第 1 期 - 大作业1

Anyou Liu

架构师训练营第 1 期

HDFS SHELL详解(1)

罗小龙

hadoop 28天写作 hdfs shell

我能加入写作训练营,一切都因为...

李忠良

个人成长 驱动力量 28天写作

架构师训练营大作业(一)

曾彪彪

「架构师训练营第 1 期」

Flink 自定义Avro序列化(Source/Sink)到kafka中

大数据老哥

大数据 flink hadoop

小心!你可能搞了个假的头脑风暴!

Justin

团队协作 28天写作 头脑风暴 群体迷思 创造性思维

区块链的前世今生(1)

抗哥

CSS10 - 盒子模型&常用无序列表样式

Mr.Cactus

html/css

第2周总结-架构中的设计模式

潘涛

架构师训练营 4 期

一致性Hash算法

Andy

期末大作业(一)

wanlinwang

视频号发展简史&第一天数据 | 视频号28天(02)

赵新龙

28天写作

关系中的密码:麻烦

熊斌

个人成长 28天写作 亲密关系

在 win 10 上安装 Elasticsearch 7.10.1

escray

elasticsearch elastic 28天写作 死磕Elasticsearch 60天通过Elastic认证考试

Rancher实战案例 | kube-api-auth日志中出现大量错误信息怎么办?_文化 & 方法_Rancher_InfoQ精选文章