在k8s1.24之前的版本中,创建ServiceAccout时会自动为其创建一个对应的Secret,里边包含了集群的CA证书、ServiceAccount所在名称空间和访问API Server的token,创建Pod的时候这个Secret会作为存储卷被自动挂载到Pod中,用于Pod中的应用访问API Server时使用

但从1.24版本起不会自动创建这个Secret,如下,在1.24版本的环境中测试

创建一个ServiceAccount sa1

root@k8s-master01:~# kubectl create sa sa1
serviceaccount/sa1 created
root@k8s-master01:~# kubectl get sa
NAME      SECRETS   AGE
default   0         46h
my-sa     0         46h
sa1       0         4s

查询Secret资源,如下图,没有为sa1自动生成对应的Secret

root@k8s-master01:~# kubectl get secret
NAME                    TYPE                                  DATA   AGE
aliyun-image-registry   kubernetes.io/dockerconfigjson        1      44d
harbor-secret           kubernetes.io/dockerconfigjson        1      53d
k8s-cert                kubernetes.io/tls                     2      53d
mysql-root-password     Opaque                                1      26d
nginx-cert              kubernetes.io/tls                     2      45d
secret-basic-auth       kubernetes.io/basic-auth              2      53d
secret-for-my-sa        kubernetes.io/service-account-token   3      46h
root@k8s-master01:~#

现在我们手动创建一个Secret,和sa1绑定,yaml文件如下:

apiVersion: v1
kind: Secret
metadata:
  name: secret-for-sa1
  annotations:
    kubernetes.io/service-account.name: sa1		#指定Secret所属的SecviceAccount
type: kubernetes.io/service-account-token	#指定类型

创建之后,查看Secret内容,k8s会自动为其自动添加token数据

root@k8s-master01:~/resources-yaml# kubectl apply -f secret-for-sa1.yaml
secret/secret-for-sa1 created
root@k8s-master01:~/resources-yaml# kubectl get secret
NAME                    TYPE                                  DATA   AGE
secret-for-sa1          kubernetes.io/service-account-token   3      9s
root@k8s-master01:~/resources-yaml# kubectl describe secret/secret-for-sa1
Name:         secret-for-sa1
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: sa1
              kubernetes.io/service-account.uid: 2bfc1ddd-8d33-439c-a0eb-282a01191a4d

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1302 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6ImFRd0lqbGF0V2hsODRZZlF3UWdrQmFBckpDc0o0T2Z2OUc1c0hrY0hHNjQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InNlY3JldC1mb3Itc2ExIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6InNhMSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjJiZmMxZGRkLThkMzMtNDM5Yy1hMGViLTI4MmEwMTE5MWE0ZCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OnNhMSJ9.rSsUz2V0MIPt31Xt1UPCJlRVe32JI4X8SGbvigWqT-7VkWK-13JGJ3nLM5gO0tIECBMz1Rtoh7FMAI-qZlCq9PAtU1mfUIBVXtKbi-MZ8P5xUMeQWkxH4dqR0UA0nVDuXoeYYSBU_19iy8VzNaiSW_5iDU_DCSNhygw5Huj-zK2_pg2cdm9ZXwYQKZSZpEQGnmfPjIzlJCLsy6-3KjlpvYMlsAs9xCSSBQ03PiEu27lwW78k6R0NWvJ0NT7sRt5H2q_-yl6jn_x2r8FVGQNNzDxd6kxvvaJDaAFoLxX6O9TTKiMzNUZ2RH9gcWN4YhkqF23PjyrdVIeW6njANVyk2g
root@k8s-master01:~/resources-yaml#

注意:这里只添加了token,集群的CA和名称空间数据没有被添加,这和之前版本中Service Account对应Secret中的内容是不一样的

创建一个Pod引用sa1

apiVersion: v1
kind: Pod
metadata:
   name: testpod
spec:
  serviceAccountName: sa1
  containers:
  - name: ubuntu
    image: harbor-server.linux.io/base-images/ubuntu:20.04
    imagePullPolicy: IfNotPresent
    command:
    - /bin/sh
    - -c
    - "sleep 3600"

创建之后查看Pod挂载的卷,如下所示,可以看到Pod定义了一个卷kube-api-access-xxx,并且也挂载到容器内/var/run/secrets/kubernetes.io/serviceaccount 目录下的文件和之前的版本是一致的,但卷的数据来源并不是Secret,其中token是由kubelet到tokenRequest api去申请的token,且token的有效期为1小时;ca.crt来自configmap,这个kube-root-ca.crt在每个名称空间都存在,创建新namespace时k8s会自动在namespace下添加;namespace是通过downwardAPI插件获取Pod自身的字段值

root@k8s-master01:~# kubectl get pods/testpod -o yaml	#查看Pod的卷定义和卷挂载信息
......
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: kube-api-access-652fr
      readOnly: true
.......
  volumes:
  - name: kube-api-access-652fr
    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
root@k8s-master01:~# kubectl  exec pods/testpod -- ls /var/run/secrets/kubernetes.io/serviceaccount		#查看Pod的容器内挂载点下的文件
ca.crt
namespace
token

我们再对比一下Pod中的token和secret-for-sa1中的token是否是同一个

root@k8s-master01:~# kubectl  exec pods/testpod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
eyJhbGciOiJSUzI1NiIsImtpZCI6ImFRd0lqbGF0V2hsODRZZlF3UWdrQmFBckpDc0o0T2Z2OUc1c0hrY0hHNjQifQ.eyJhdWQiOlsiYXBpIiwiaXN0aW8tY2EiXSwiZXhwIjoxNjk3MzU4Mjk3LCJpYXQiOjE2NjU4MjIyOTcsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2YyIsImt1YmVybmV0ZXMuaW8iOnsibmFtZXNwYWNlIjoiZGVmYXVsdCIsInBvZCI6eyJuYW1lIjoidGVzdHBvZCIsInVpZCI6IjdhNzQ1ZGQ4LWIzZjEtNDQzNy1hNzM5LTQwNmVkMjEzOGYwZSJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoic2ExIiwidWlkIjoiMmJmYzFkZGQtOGQzMy00MzljLWEwZWItMjgyYTAxMTkxYTRkIn0sIndhcm5hZnRlciI6MTY2NTgyNTkwNH0sIm5iZiI6MTY2NTgyMjI5Nywic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6c2ExIn0.EdGMk4YYYxlnJFr1X-XfKUQ8pFFPe1MpNIkSKQYhlTAeHR-qN5mnsnc9xf9lvsl12qLHTk2cBY0hRk2M3LqBDHEUhGg22xYdmFEVX2qMbyz64Kuz9dAOIQHfDOp4VzIMHrsUPJpYF2yh9ZmZuE09VEAdt6QHYobQgUVp2m54Z5B-qDajVHkCovJCiDzUkfKYx38_HdPS8FAhx_o6jslfVD3QCxJ4azs6nFdiu1Rq5HEDYG53wuFRSWOCVe2MiNi38uwR1W_N_2Fdr5JebiJucGOIBqYy5VtGR00Ni80I9yzf4-cewhuhUlR7nVniG-yDyLrLgXdxOfWccohdEX5GrA
root@k8s-master01:~#
root@k8s-master01:~# kubectl get secret/secret-for-sa1 -o jsonpath={.data.token} |base64 -d
eyJhbGciOiJSUzI1NiIsImtpZCI6ImFRd0lqbGF0V2hsODRZZlF3UWdrQmFBckpDc0o0T2Z2OUc1c0hrY0hHNjQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InNlY3JldC1mb3Itc2ExIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6InNhMSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjJiZmMxZGRkLThkMzMtNDM5Yy1hMGViLTI4MmEwMTE5MWE0ZCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OnNhMSJ9.rSsUz2V0MIPt31Xt1UPCJlRVe32JI4X8SGbvigWqT-7VkWK-13JGJ3nLM5gO0tIECBMz1Rtoh7FMAI-qZlCq9PAtU1mfUIBVXtKbi-MZ8P5xUMeQWkxH4dqR0UA0nVDuXoeYYSBU_19iy8VzNaiSW_5iDU_DCSNhygw5Huj-zK2_pg2cdm9ZXwYQKZSZpEQGnmfPjIzlJCLsy6-3KjlpvYMlsAs9xCSSBQ03PiEu27lwW78k6R0NWvJ0NT7sRt5H2q_-yl6jn_x2r8FVGQNNzDxd6kxvvaJDaAFoLxX6O9TTKiMzNUZ2RH9gcWN4YhkqF23PjyrdVIeW6njANVyk2g
root@k8s-master01:~#

如上所示,两个token值是不一致的。将两个token在线解析(jwt.io)一下,查看有什么区别。
先查看Pod内的token,如下图所示,有效期为1年,但这个token在Pod内会1小时更新一次
在这里插入图片描述

再查看secre-for-sa1中的token,如下图,它没有过期时间,是永不过期的
在这里插入图片描述

综上所述:

  1. 1.24版本后创建ServiceAccount不再自动创建对应的Secret
  2. 可以手动创建Secret绑定到ServiceAccount,k8s会为其自动添加永久有效的token
  3. Pod中的应用使用ServiceAccount访问API Server的方式不变,依然可以通过/var/run/secrets/kubernetes.io/serviceaccount目录下的token文件、ca.crt文件和namespace文件访问API Server。但需要注意,token文件中的token每个小时会更新一次
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐