【K8s任务】为 Pod 配置服务账户

参考:https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-service-account/

使用默认的服务账户访问 API 服务器

当你创建 Pod 时,如果没有指定服务账户,Pod 会被指定给命名空间中的 default 服务账户。 如果你查看 Pod 的原始 JSON 或 YAML(例如:kubectl get pods/podname -o yaml), 你可以看到 spec.serviceAccountName 字段已经被自动设置了。

你可以使用自动挂载给 Pod 的服务账户凭据访问 API, 访问集群 中有相关描述。 服务账户的 API 许可取决于你所使用的 鉴权插件和策略。

在 1.6 以上版本中,你可以通过在服务账户上设置 automountServiceAccountToken: false 来实现不给服务账号自动挂载 API 凭据:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: build-robot
automountServiceAccountToken: false
...

在 1.6 以上版本中,你也可以选择不给特定 Pod 自动挂载 API 凭据:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  serviceAccountName: build-robot
  automountServiceAccountToken: false
  ...

如果 Pod 和服务账户都指定了 automountServiceAccountToken 值,则 Pod 的 spec 优先于服务帐户。

使用多个服务账户

每个命名空间都有一个名为 default 的服务账户资源。 你可以用下面的命令查询这个服务账户以及命名空间中的其他 ServiceAccount 资源:

kubectl get serviceAccounts

输出类似于:

NAME      SECRETS    AGE
default   1          1d

你可以像这样来创建额外的 ServiceAccount 对象:

kubectl create -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: build-robot
EOF

ServiceAccount 对象的名字必须是一个有效的 DNS 子域名.

如果你查询服务帐户对象的完整信息,如下所示:

kubectl get serviceaccounts/build-robot -o yaml

输出类似于:

apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: 2015-06-16T00:12:59Z
  name: build-robot
  namespace: default
  resourceVersion: "272500"
  uid: 721ab723-13bc-11e5-aec2-42010af0021e
secrets:
- name: build-robot-token-bvbk5

那么你就能看到系统已经自动创建了一个令牌并且被服务账户所引用。

你可以使用授权插件来 设置服务账户的访问许可。

要使用非默认的服务账户,将 Pod 的 spec.serviceAccountName 字段设置为你想用的服务账户名称。

Pod 被创建时服务账户必须存在,否则会被拒绝。

你不能更新已经创建好的 Pod 的服务账户。

手动创建服务账户 API 令牌

假设我们有一个上面提到的名为 "build-robot" 的服务账户,然后我们手动创建一个新的 Secret。

kubectl create -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: build-robot-secret
  annotations:
    kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token
EOF
secret/build-robot-secret created

现在,你可以确认新构建的 Secret 中填充了 "build-robot" 服务帐户的 API 令牌。

令牌控制器将清理不存在的服务帐户的所有令牌。

kubectl describe secrets/build-robot-secret

输出类似于:

Name:           build-robot-secret
Namespace:      default
Labels:         <none>
Annotations:    kubernetes.io/service-account.name=build-robot
                kubernetes.io/service-account.uid=da68f9c6-9d26-11e7-b84e-002dc52800da

Type:   kubernetes.io/service-account-token

Data
====
ca.crt:         1338 bytes
namespace:      7 bytes
token:          ...

说明: 这里省略了 token 的内容。

为服务账户添加 ImagePullSecrets

创建 ImagePullSecret

    1.创建一个 ImagePullSecret,如同为 Pod 设置 ImagePullSecret所述。

    kubectl create secret docker-registry myregistrykey --docker-server=DUMMY_SERVER \
              --docker-username=DUMMY_USERNAME --docker-password=DUMMY_DOCKER_PASSWORD \
              --docker-email=DUMMY_DOCKER_EMAIL

    2.确认创建成功:

    kubectl get secrets myregistrykey

    输出类似于:

    NAME             TYPE                              DATA    AGE
    myregistrykey    kubernetes.io/.dockerconfigjson   1       1d

将镜像拉取 Secret 添加到服务账号

接着修改命名空间的 default 服务帐户,以将该 Secret 用作 imagePullSecret。

kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'

你也可以使用 kubectl edit,或者如下所示手动编辑 YAML 清单:

kubectl get serviceaccounts default -o yaml > ./sa.yaml

sa.yaml 文件的内容类似于:

apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: 2015-08-07T22:02:39Z
  name: default
  namespace: default
  resourceVersion: "243024"
  uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
secrets:
- name: default-token-uudge

使用你常用的编辑器(例如 vi),打开 sa.yaml 文件,删除带有键名 resourceVersion 的行,添加带有 imagePullSecrets: 的行,最后保存文件。

所得到的 sa.yaml 文件类似于:

apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: 2015-08-07T22:02:39Z
  name: default
  namespace: default
  uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
secrets:
- name: default-token-uudge
imagePullSecrets:
- name: myregistrykey

最后,用新的更新的 sa.yaml 文件替换服务账号。

kubectl replace serviceaccount default -f ./sa.yaml

验证镜像拉取 Secret 已经被添加到 Pod 规约

现在,在当前命名空间中创建的每个使用默认服务账号的新 Pod,新 Pod 都会自动 设置其 .spec.imagePullSecrets 字段:

kubectl run nginx --image=nginx --restart=Never
kubectl get pod nginx -o=jsonpath='{.spec.imagePullSecrets[0].name}{"\n"}'

输出为:

myregistrykey

服务帐户令牌卷投射

FEATURE STATE: Kubernetes v1.20 [stable]

    说明:

    为了启用令牌请求投射,你必须为 kube-apiserver 设置以下命令行参数:

        --service-account-issuer
        --service-account-key-file
        --service-account-signing-key-file
        --api-audiences

kubelet 还可以将服务帐户令牌投影到 Pod 中。 你可以指定令牌的所需属性,例如受众和有效持续时间。 这些属性在默认服务帐户令牌上无法配置。 当删除 Pod 或 ServiceAccount 时,服务帐户令牌也将对 API 无效。

使用名为 ServiceAccountToken 的 ProjectedVolume 类型在 PodSpec 上配置此功能。 要向 Pod 提供具有 "vault" 用户以及两个小时有效期的令牌,可以在 PodSpec 中配置以下内容:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
    - mountPath: /var/run/secrets/tokens
      name: vault-token
  serviceAccountName: build-robot
  volumes:
  - name: vault-token
    projected:
      sources:
      - serviceAccountToken:
          path: vault-token
          expirationSeconds: 7200
          audience: vault

创建 Pod:

kubectl create -f https://k8s.io/examples/pods/pod-projected-svc-token.yaml

kubelet 组件会替 Pod 请求令牌并将其保存起来,通过将令牌存储到一个可配置的 路径使之在 Pod 内可用,并在令牌快要到期的时候刷新它。 kubelet 会在令牌存在期达到其 TTL 的 80% 的时候或者令牌生命期超过 24 小时 的时候主动轮换它。

应用程序负责在令牌被轮换时重新加载其内容。对于大多数使用场景而言,周期性地 (例如,每隔 5 分钟)重新加载就足够了。

posted @ 2021-08-04 16:35  Varden  阅读(552)  评论(0编辑  收藏  举报