程序锅

  • 首页
  • 分类
  • 标签
  • 归档
  • 关于

  • 搜索
基础知识 Etcd LeetCode 计算机体系结构 Kubernetes Containerd Docker 容器 云原生 Serverless 项目开发维护 ELF 深入理解程序 Tmux Vim Linux Kernel Linux numpy matplotlib 机器学习 MQTT 网络基础 Thrift RPC OS 操作系统 Clang 研途 数据结构和算法 Java 编程语言 Golang Python 个人网站搭建 Nginx 计算机通用技术 Git

Kubernetes APIServer-ServiceAccount 和 Token

发表于 2023-10-18 | 分类于 Kubernetes | 0 | 阅读次数 3485

基本原理

Pod 中的进程在访问 API Server 的时候,通常使用 ServiceAccount 来表明自己的身份。ServiceAccount 为运行在 Pod 中的进程提供一个安全、自动化的身份验证机制,使得这些进程可以与 Kubernetes API Server 进行交互。

1.24 及之后的版本,ServiceAccount 的大致原理是:

  • 当创建 Pod 的时候,在 admission 阶段,serviceaccount admission 会通过 projected 方式为 Pod 挂载一个 token,挂载的路径是 /var/run/secrets/kubernetes.io/serviceaccount。

    如下所示,

    apiVersion: v1
    kind: Pod
    metadata:
      name: calico-node-ffkx6
      namespace: kube-system
    spec:
      containers:
      - #...
        volumeMounts:
        - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
          name: kube-api-access-mnxtg
          readOnly: true
      volumes:
      #...
      - name: kube-api-access-mnxtg
        projected:
          defaultMode: 420
          sources:
          - serviceAccountToken:
              expirationSeconds: 3607
              path: token
          - configMap:
              items:
              - key: ca.crt
                path: ca.crt
              name: kube-root-ca.crt
          - downwardAPI:
              items:
              - fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.namespace
                path: namespace
    
  • Pod 被调度到 Node 上后,kubelet 中的 projected volume mounter 会根据 volumesMount 中的 volume 类型,为 Pod 挂载对应的文件。当发现存在 ServiceAccountToken 类型的 projected source 时,就会调用 apiserver 的 TokenRequest 接口,为当前 Pod 请求临时的 Token,之后将 token 挂载到相应的目录中。生成的 token 的有效期只有 3607s,同时 kubelet 会自动刷新这个 token 来保证它不会过期。

    我们可以通过下面命令获取到 Pod 中使用的 token,得到一个 JWT 结构的字符串,

    $ kubectl exec -it ${pod} -- cat /run/secrets/kubernetes.io/serviceaccount/token
    eyJhbGciOiJSUzI1NiIsImtpZCI6InFwbWtnTnM3Nk9HTjZwSU1PdVp2c3ZGY2VqX0JjQXE5bkcyRUZHd3NTZ00ifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjg4NzMxMzA1LCJpYXQiOjE2NTcxOTUzMDUsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJuczEiLCJwb2QiOnsibmFtZSI6InBvZDEiLCJ1aWQiOiIyNmFhNzQ4Ny02ODA5LTQwNmItODcyZi0wYjExZjFjZTg4YzQifSwic2VydmljZWFjY291bnQiOnsibmFtZSI6InNhMSIsInVpZCI6ImIzMDI0YWQzLWU2ZjItNGE1MC1iMjE4LWJlM2I5YjhkMGNiOSJ9LCJ3YXJuYWZ0ZXIiOjE2NTcxOTg5MTJ9LCJuYmYiOjE2NTcxOTUzMDUsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpuczE6c2ExIn0.bOQeFK-U4tvigUsbj_o7xfxrVBDyvdwQdxnd4ZGPb_m_P1EuffwJB80mOwIYPTijNpj6OzWdaGMedFZdv6TKcWFZ4DZWLB6UXtOS0rXIsl9OyKEU2RyCIssR0LKmx6L4mDznEk6jLv7tOY3eLRfX7FgjmCK_Y1Hipju9d2v92_poPb1oHHMP00OZs0XUfb-V0arIGcYm52kiJ_E4PuWpH9AzpAG916wmdnoIpnUxYsFhX020I5Pw8jLsxaPUAVc1AlOYr8IKgyvilqJljjivbZA9Sru_LjlsboEfUFqFQscu57kSR58WJos3gYJteAyM94pIdb-5RU0U75p3Ih6eLA
    

    之后将这个 token 复制到 https://jwt.io/ 进行解码,可以看到 token 中包含了三部分:Header、Payload 和 Signature,也就是 JWT 由这三部分组成。其中,

    • Payload 中包含了使用的 ServiceAccount、Pod 信息、有效时间和过期时间等。可以看到以下信息:

      • token 的过期时间(exp)为 1 年。
      • token 的有效时间为 3607,即在 1 个小时后会由 kubelet 重新申领一个新的 token(warnafter)。

      如果 pod 重新创建的话,则会重新申领 token,被删除的 pod 里的 token 立即过期。综上来说,token 的有效性由 pod 的生命周期(比如 Pod 删除了,token 就会失效了)、有效时间和过期时间决定。

    • 其中 Signature 相当于 Header + Signature 通过私钥加密后的内容(跟数字签名有点类似)。这里的私钥,其实就是之前提到的 kube-controller-manager 会配置的私钥,这个私钥的作用就是用于生成 Service Account Token 的 Signature。

      containers:
        - command:
          - kube-controller-manager
          # 对 service account token 进行加密的私钥文件的路径。kube-controller-manager 使用这个私钥生成相应 service account token,Pod 访问 kube-apiserver 的时候会使用这些 token,然后这些 token 会被 kube-apiserver 验证,由于 kube-apiserver 启动的时候指定了相应的公钥,因此它可以进行验证。
          - --service-account-private-key-file=/etc/kubernetes/pki/sa.key
      
  • Pod 中的程序在请求 API Server 的时候,也就是通过 client-go 库在请求 APIServer 的时候,client-go 会默认搜索 /var/run/secrets/kubernetes.io/serviceaccount 这个路径,然后使用这个 token 向 API Server 发起请求。

  • API Server 在收到这个 token 后,根据 JWT 的规范对内容进行完整性校验,这里的校验就包括使用 kube-apiserver 启动时配置的 service account token 的公钥对 token 的 signature 进行解密,验证内容是否篡改。同时校验有效性等。校验通过后根据 token 中的 service account 进行认证鉴权。

    containers:
      - command:
        - kube-apiserver
        # 用于验证 service account token 的公钥
        - --service-account-key-file=/etc/kubernetes/pki/sa.pub
    

版本变化

1.20 版本及之前

  • 创建 serviceaccount 的时候,会自动创建一个 secret。这个 secret 会包含一个 token,这个 token 是永远不过期的。
  • 如果 Pod 中使用了相应的 serviceaccount,那么 Pod 中被挂载的 token 跟上述自动创建的 secret 中的 token 内容是一模一样的。

1.21-1.23

  • 创建 serviceaccount 的时候,会自动创建一个 secret。这个 secret 会包含一个 token,这个 token 是永远不过期的。
  • 如果 Pod 中使用了相应的 serviceaccount,那么 Pod 中被挂载的 token 并不会使用上述自动创建的 secret 中的token,而是由 kubelet 发送一个 tokenRequest 请求创建的。

1.24

  • 创建 serviceaccount 的时候,不会再自动创建一个 secret。
  • 如果 Pod 中使用了相应的 serviceaccount,那么 Pod 中被挂载的 token 是由 kubelet 发送一个 tokenRequest 请求创建的。

相关链接

服务账户service account在kubernetes1.24中的变化:https://blog.csdn.net/lduan_001/article/details/125667733

卷死我
dawnguo 微信支付

微信支付

dawnguo 支付宝

支付宝

  • 本文作者: dawnguo
  • 本文链接: /archives/246
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
# Kubernetes
Kubernetes APIServer-Kubernetes 证书
Kubernetes APIServer-审计
  • 文章目录
  • 站点概览
dawnguo

dawnguo

215 日志
24 分类
37 标签
RSS
Creative Commons
© 2018 — 2025 程序锅
0%