首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

ServiceAccount Token 在不同 K8s 版本中的使用

ServiceAccount 为 Pod 中运行的进程提供了一个身份,Pod 内的进程可以使用其关联服务账号的身份,向集群的 APIServer 进行身份认证。

当创建 Pod 的时候规范下面有一个 的属性用来指定该 Pod 使用哪个 ServiceAccount,如果没有指定的话则默认使用 default 这个 sa。然后通过投射卷,在 Pod 的目录 下有一个 令牌文件。我们通过 RBAC 对该 sa 授予了什么权限,那么容器里的应用拿着这个 token 后,就具备了对应的权限。

但是需要注意的是不同的 K8s 版本对该 文件的使用是不一样的,所以我们这里分别进行下简单说明。

<=1.20 版本

使用 kind 快速创建一个小于等于 版本的集群:

我们先创建一个字为 的 ServiceAccount 对象:

我们可以看到创建 sa 后自动生成了一个 secret,格式为 ,比如我们创建了一个名字为 的 sa 之后,系统自动创建了一个名字为 的 secret,这个 secret 里就包含了一个 token。

可以看到自动生成的这个 secret 对象里面包含一个 token,我们也可以通过下面的命令来获取:

这个 token 是 结构的,我们可以把这个 token 复制到 网站进行解码。

右侧部分显示了 token 被解码之后的内容,其中 PAYLOAD 部分是 token 里包含的 的信息,可以看到里面没有过期时间,也说明了该 token 是永不过期的。

现在我们使用上面我们创建的 sa 来运行一个 Pod:

直接创建该 Pod 即可:

Pod 创建后我们可以看到会自动将指定 sa 对应的 secret 挂载到容器的 目录下去,所以现在该目录下面肯定包含对应的 token 文件,我们可以查看该值来验证下:

可以看到 Pod 里通过投射卷所挂载的 token 跟 sa-demo 对应的 secret 包含的 token 是模一样的,这个 token 是永不过期的,所以即使删除了 Pod 之后重新创建,Pod 里的 token 仍然是不变的,因为 secret 对象里面的 token 数据并没有变化。

如果需要在 Pod 中去访问 K8s 集群的资源对象,现在就可以为使用的 sa 绑定上相应的权限,然后在 Pod 应用中使用该对应的 token 去和 APIServer 进行通信就可以了,这个时候的 token 就能识别到对应的权限了。

>=1.21 版本 && <= 1.23 版本

接下来我们基于 版本的 K8s 集群进行测试。

这里我们使用 kind 快速创建一个 版本的集群:

同样首先创建一个名为 的 ServiceAccount 对象:

同样可以看到创建 sa 后系统也自动创建了一个对应的 secret 对象,和以前版本没什么区别,我们也可以通过下面的命令来获得该 secret 对象里面包含的 token 值:

同样将该 token 值拷贝到 网站进行解码。

从解码后的值可以看到该 token 值里面同样不包含任何过期时间,也说明了我们创建 sa 之后,所对应的 token 是永不过期的。

同样我们再次使用上面的 sa 来创建一个 Pod,如下所示:

直接创建该 Pod:

当 Pod 创建后查看对应的资源对象,可以看到和之前的版本已经有一个很大的区别了,并不是将上面自动创建的 secret 挂载到容器的 目录。我们可以查看下 Pod 中的 token 值来和 secret 包含的 token 值进行对比:

可以很明显看到现在 Pod 中的 token 值和自动创建 secret 的 token 值不一样了,同样在 解码该 token 值。

可以看到该 token 值解码后的 数据中包含了很多不同的数据,其中的 字段表示该 token 的过期时间,可以看到过期时间是 1 年。

这里我们可以总结下在 v1.21 到 v1.23 版本的 K8s 集群,当创建 ServiceAccount 对象后,系统仍然会自动创建一个 secret 对象,该 secret 对象里面包含的 token 仍然是永不过期的,但是 Pod 里面并不会使用该 secret 的 token 值了。

从上面查看创建后的 Pod 资源清单可以看出,现在创建 Pod 后,Kubernetes 控制平面会自动添加一个投射卷到 Pod,此卷包括了访问 Kubernetes API 的 token,该清单片段定义了由三个数据源组成的投射卷,这三个数据源是:

:包含 kubelet 从 kube-apiserver 获取的令牌,kubelet 使用 TokenRequest API 获取有时间限制的令牌。为 TokenRequest 服务的这个令牌会在 Pod 被删除或定义的生命周期(默认为 1 小时)结束之后过期。该令牌绑定到特定的 Pod, 并将其 audience(受众)设置为与 kube-apiserver 的 audience 相匹配。 这种机制取代了之前基于 Secret 添加卷的机制,之前 Secret 代表了针对 Pod 的 ServiceAccount 但不会过期。

:ConfigMap 包含一组证书颁发机构数据,Pod 可以使用这些证书来确保自己连接到集群的 kube-apiserver(而不是连接到中间件或意外配置错误的对等点上)。

:用于查找包含 Pod 的名字空间的名称,并使该名称信息可用于在 Pod 内运行的应用程序代码。

所以我们应该要指定现在版本的 K8s 集群创建的 Pod 里面包含的 token 不是使用 ServiceAccount 自动关联的 secret 对象里面的 token 了,而是 kubelet 会向 发送一个请求,申请一个新的 token 放在 Pod 的 里。这个 token 会在 1 个小时后由 kubelet 重新去申领一个新的 token,所以 1 小时之后再次查看这个 token 的话会发现 token 的内容是变化的,如果删除此 Pod 重新创建的话,则会重新申领 token,被删除 Pod 里的 token 会立即过期。

而且我们还可以手动使用 命令来请求 ServiceAccount 的 token,可以指定有效期等:

>=1.24 版本

现在我们再来看下 v1.24 版本以上的 K8s 集群中的 ServiceAccount token 是如何工作的。这里我们使用 kind 快速创建一个 版本的集群:

同样创建一个名为 的 ServiceAccount:

我们可以看到该 ServiceAccount 创建后并没有创建对应的 Secret 对象。同样接下来创建一个如下所示的 Pod:

创建上面的 Pod 后查看详情:

可以看到创建 Pod 后同样会自动添加一个投射卷到 Pod,此卷包括了访问 Kubernetes API 的令牌,和 表现是一致的。同样我们可以下查看 Pod 中的 token 值来进行验证:

我们可以把上面输出的 token 值拷贝到 里进行解码。

从上面的数据可以看到这里的 token 的有效期也为 1 年,这个 token 在 Pod 里也是每 1 小时会更新一次,如果 Pod 被删除重建,那么会重新申领一个新的 token,被删除 Pod 里的 token 立即过期。

需要注意的没有特定的机制使通过 签发的令牌无效,如果你不再信任为某个 Pod 绑定的 ServiceAccount 令牌,你可以删除该 Pod,删除 Pod 将使其绑定的令牌过期。

总结

我们可以简单总结下不同版本的 K8s 集群下面的 ServiceAccount Token 是如何工作的。

1.20(含 1.20)之前的版本,在创建 sa 时会自动创建一个 secret,然后这个会把这个 secret 通过投射卷挂载到 pod 里,该 secret 里面包含的 token 是永久有效的。

1.21~1.23 版本,在创建 sa 时也会自动创建 secret,但是在 pod 里并不会使用 secret 里的 token,而是由 kubelet 到 TokenRequest API 去申请一个 token,该 token 默认有效期为一年,但是 pod 每一个小时会更新一次 token。

1.24 版本及以上,在创建 sa 时不再自动创建 secret 了,只保留由 kubelet 到 TokenRequest API 去申请 token。

当然我们仍然可以手动创建 Secret 来保存 ServiceAccount 令牌,例如在你需要一个永不过期的令牌的时候。一旦手动创建一个 Secret 并将其关联到 ServiceAccount,Kubernetes 控制平面就会自动将令牌填充到该 Secret 中。

尽管存在手动创建长久 ServiceAccount 令牌的机制,但还是推荐使用 TokenRequest 获得短期的 API 访问令牌。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230112A02JVH00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券