Kubernetes——服务帐号管理与应用(ServiceAccount)
服务帐号管理与应用(ServiceAccount)
运行过程中,Pod 资源里的容器进程在某些场景需要调用 Kubernetes API 或其他类型的服务,而这些服务通常需要认证客户端身份,如调度器、Pod控制器或节点控制器,甚至是获取启动容器的镜像访问的私有仓库 Harbor 服务等。
服务帐号就是用于让 Pod 对象内的容器进程访问其他服务时提供身份认证信息的账户。
一个 Service Account 资源一般由用户名及相关的 Secret 对象组成。
一、Service Account 自动化
“kubectl describe pods” 命令显示的某 Pod 对象描述信息如下:
[root@k8s-master01-test-2-26 ~]# kubectl describe pods/metrics-server-59f8dbb485-df9tv -n kube-system
Name: metrics-server-59f8dbb485-df9tv
Namespace: kube-system
Priority: 2000000000
Priority Class Name: system-cluster-critical
Node: k8s-worker03-test-2-31/192.168.2.31
Start Time: Fri, 01 Jul 2022 10:13:40 +0800
Labels: k8s-app=metrics-server
pod-template-hash=59f8dbb485
Annotations: <none>
Status: Running
IP: 192.168.2.31
IPs:
IP: 192.168.2.31
Controlled By: ReplicaSet/metrics-server-59f8dbb485
Containers:
metrics-server:
Container ID: containerd://5e80f52bc7e19dea8f18cf7b5fd8a5035197086ecee1ae9aea78bcdfd47a92c6
Image: registry.cn-beijing.aliyuncs.com/kubesphereio/metrics-server:v0.4.2
Image ID: registry.cn-beijing.aliyuncs.com/kubesphereio/metrics-server@sha256:9ea12bd44276106240f36137877fc2c56f27c62f3d866813535e494f53f4c8bc
Port: 4443/TCP
Host Port: 4443/TCP
Args:
--cert-dir=/tmp
--secure-port=4443
--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
--kubelet-use-node-status-port
--kubelet-insecure-tls
State: Running
Started: Sat, 02 Jul 2022 13:37:27 +0800
Last State: Terminated
Reason: Error
Exit Code: 2
Started: Sat, 02 Jul 2022 13:36:53 +0800
Finished: Sat, 02 Jul 2022 13:37:24 +0800
Ready: True
Restart Count: 29
Liveness: http-get https://:https/livez delay=0s timeout=1s period=10s #success=1 #failure=3
Readiness: http-get https://:https/readyz delay=0s timeout=1s period=10s #success=1 #failure=3
Environment: <none>
Mounts:
/tmp from tmp-dir (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-dscjt (ro) #这里
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
tmp-dir:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
SizeLimit: <unset>
kube-api-access-dscjt:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt #这里
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: kubernetes.io/os=linux
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SandboxChanged 2m6s kubelet Pod sandbox changed, it will be killed and re-created.
Normal Killing 94s kubelet Container metrics-server failed liveness probe, will be restarted
Normal Created 86s (x2 over 2m1s) kubelet Created container metrics-server
Normal Pulled 86s (x2 over 2m4s) kubelet Container image "registry.cn-beijing.aliyuncs.com/kubesphereio/metrics-server:v0.4.2" already present on machine
Normal Started 85s (x2 over 2m) kubelet Started container metrics-server
……
挂载点目录中通常存在三个文件:ca.crt、namespace 和 token,其中,token 文件保存了 Service Account 的认证 token,容器中的进程使用它向 API Server 发起连接请求,进而由认证插件完成用户认证并将其用户传递给授权插件。
每个 Pod 对象都只有一个服务账户,若创建 Pod 资源时未予以明确指定,则名为 ServiceAccount 的准入控制器会为其自动附加当前名称空间中默认的服务账户,其名称通常为 default。
[root@mh-k8s-master-242-10 ~]# kubectl get sa -n mh-scrm-parent
NAME SECRETS AGE
default 1 68d
[root@mh-k8s-master-242-10 ~]# kubectl describe sa/default -n mh-scrm-parent
Name: default
Namespace: mh-scrm-parent
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: default-token-l4xlj
Tokens: default-token-l4xlj
Events: <none>
[root@mh-k8s-master-242-10 ~]#
Kubernetes 系统通过三个独立组件间的相互协作来实现服务账户的自动化,三个组件具体为:Service Account 准入控制器、令牌控制器(token controller) 和 Service Account 账户控制器。
- Service Account 控制器负责为名称空间管理相应的资源,并确保每个名称空间中都存在一个名为 "default" 的 Service Account 对象。
- Service Account准入控制器 是 API Server 的一部分,负责在创建和更新 Pod 时对其按需进行 Service Account 对象相关信息的修改,这包括如下操作:
- 若 Pod 没有明确定义使用的 ServiceAccount 对象,则将其设置为 "default"。
- 确保 Pod 明确引用的 ServiceAccount 已存在,否则请求将被拒绝。
- 若 Pod 对象中不包含 ImagePullSecrets,则把 Service Account 的 ImagePullSecrets 添加于其上。
- 为带有访问 API 的令牌的 Pod 添加一个存储卷。
- 为 Pod 对象的每个容器添加一个 volumeMounts,挂载至 /var/run/secrets/kubernetes.io/serviceaccount。
- 令牌控制器 是 Controller-manager 的子组件,工作于异步模式。其负责完成的任务具体如下:
- 监控 Service Account 的删除操作,并删除其相关的所有 Service Account 令牌密钥。
- 监控 Secret 对象的添加操作,确保其引用的 Service Account 已存在,并在必要时为 Secret 对象添加认证令牌。
- 监控 Secret 对象的删除操作,确保删除每个 Service Account 中对此 Secret 的引用。
需要注意的是,为确保完整性等,必须为 kube-controller-manager 使用 "--service-account-private-key-file" 选项指定一个私钥文件,以用于对生产的服务账户令牌进行签名,此私钥文件必须是 pem 格式。类似地,还要为 kube-apiserver 使用 "--service-account-key-file" 指定与前面的私钥配对儿的公钥文件,以用于在认证期间对认证令牌进行校验。
二、创建服务账户
Service Account 是 Kubernetes API 上的一种资源类型,它隶属于名称空间,用于让 Pod 对象内部的应用程序在与 API Server通信时完成身份认证。
事实上,每个名称空间都有一个名为 default 的默认资源对象,如下所示:
[root@k8s-master01-test-2-26 ~]# kubectl get serviceaccounts -A
NAMESPACE NAME SECRETS AGE
argocd argocd-application-controller 0 27h
argocd argocd-dex-server 0 27h
argocd argocd-notifications-bot 0 27h
argocd argocd-notifications-controller 0 27h
argocd argocd-server 0 27h
argocd default 0 27h
argocd devops-argocd-applicationset-controller 0 27h
argocd devops-argocd-repo-server 0 27h
default default 0 27h
etcd-cluster default 0 25h
etcd-cluster nfs-subdir-external-provisioner 0 19h
istio-system default 0 27h
istio-system istio-cni 0 27h
istio-system istio-ingressgateway-service-account 0 27h
istio-system istio-reader-service-account 0 27h
istio-system istiod-1-11-2 0 27h
istio-system istiod-service-account 0 27h
istio-system jaeger 0 25h
istio-system jaeger-operator 0 27h
istio-system kiali-operator 0 27h
istio-system kiali-service-account 0 27h
kube-node-lease default 0 27h
kube-public default 0 27h
kube-system attachdetach-controller 0 27h
kube-system bootstrap-signer 0 27h
kube-system calico-kube-controllers 0 27h
kube-system calico-node 0 27h
kube-system certificate-controller 0 27h
kube-system clusterrole-aggregation-controller 0 27h
kube-system coredns 0 27h
kube-system cronjob-controller 0 27h
kube-system daemon-set-controller 0 27h
kube-system default 0 27h
kube-system deployment-controller 0 27h
kube-system disruption-controller 0 27h
kube-system endpoint-controller 0 27h
kube-system endpointslice-controller 0 27h
kube-system endpointslicemirroring-controller 0 27h
kube-system ephemeral-volume-controller 0 27h
kube-system expand-controller 0 27h
kube-system generic-garbage-collector 0 27h
kube-system horizontal-pod-autoscaler 0 27h
kube-system job-controller 0 27h
kube-system kube-proxy 0 27h
kube-system metrics-server 0 27h
kube-system namespace-controller 0 27h
kube-system node-controller 0 27h
kube-system nodelocaldns 0 27h
kube-system openebs-maya-operator 0 27h
kube-system persistent-volume-binder 0 27h
kube-system pod-garbage-collector 0 27h
kube-system pv-protection-controller 0 27h
kube-system pvc-protection-controller 0 27h
kube-system replicaset-controller 0 27h
kube-system replication-controller 0 27h
kube-system resourcequota-controller 0 27h
kube-system root-ca-cert-publisher 0 27h
kube-system service-account-controller 0 27h
kube-system service-controller 0 27h
kube-system snapshot-controller 0 27h
kube-system statefulset-controller 0 27h
kube-system token-cleaner 0 27h
kube-system ttl-after-finished-controller 0 27h
kube-system ttl-controller 0 27h
kubekey-system default 0 27h
kubesphere-controls-system default 0 27h
kubesphere-controls-system kubesphere-cluster-admin 0 27h
kubesphere-controls-system kubesphere-router-serviceaccount 0 27h
kubesphere-devops-system default 0 27h
kubesphere-devops-system devops 0 27h
kubesphere-devops-system devops-jenkins 0 27h
kubesphere-devops-worker default 0 27h
kubesphere-logging-system default 0 27h
kubesphere-logging-system elasticsearch-logging-data 0 27h
kubesphere-logging-system elasticsearch-logging-master 0 27h
kubesphere-logging-system fluent-bit 0 27h
kubesphere-logging-system fluentbit-operator 0 27h
kubesphere-logging-system ks-events-exporter 0 27h
kubesphere-logging-system ks-events-operator 0 27h
kubesphere-logging-system ks-events-ruler 0 27h
kubesphere-logging-system kube-auditing-operator 0 27h
kubesphere-monitoring-federated default 0 27h
kubesphere-monitoring-system alertmanager-main 0 27h
kubesphere-monitoring-system default 0 27h
kubesphere-monitoring-system kube-state-metrics 0 27h
kubesphere-monitoring-system node-exporter 0 27h
kubesphere-monitoring-system notification-manager-sa 0 27h
kubesphere-monitoring-system prometheus-k8s 0 27h
kubesphere-monitoring-system prometheus-operator 0 27h
kubesphere-system default 0 27h
kubesphere-system ks-installer 0 27h
kubesphere-system ks-minio 0 27h
kubesphere-system kubesphere 1 27h
[root@k8s-master01-test-2-26 ~]#
每个 Pod 对象均可附加其所属名称空间中的一个 Service Account 资源,且只能附加一个。不过,一个 Service Account 资源可由其所属的名称空间中的多个 Pod 对象共享使用。
创建 Pod 资源时,用户可使用 "spec.serviceAccountName" 属性直接指定要使用的 Service Account 对象,或者省略此字段而由其自动附加当前名称空间中默认的 Service Account (default)。
可使用资源配置清单文件创建 Service Account 资源,也可以直接用命令行 "kubectl create serviceaccount" 命令进行创建,提供认证令牌的 Secret 对象会由命令自动创建完成。
下面的配置清单是一个 ServiceAccount 资源示例,它仅指定了创建名为 sa-demo 的服务帐号,其余的信息则交由系统自动生成:
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-demo
namespace: default
创建 Pod 对象时,可为 Pod 对象指定使用自定义的服务账户,从而实现自主控制 Pod 对象资源的访问权限。Pod 向 API Server 发出请求时,其携带的认证令牌在通过认证后将由授权插件来判定相关的 Service Account 是否有权限访问其所请求的资源。Kubernetes 支持多种授权插件,由管理员负责选定以及配置,RBAC 是目前较为主流的选择。
三、调用 imagePullSecret 资源对象
ServiceAccount 资源还可以基于 spec.imagePullSecret 字段附带一个由下载镜像专用的 Secret 资源组成的列表,用于在进行容器创建时,从某私有镜像仓库下载镜像文件之前进行服务认证。
下面的示例定义了一个有着从本地私有镜像仓库 harbor 中下载镜像文件时用于认证的 Secret 对象信息的 ServiceAccount:
apiVersion: v1
kind: ServiceAccount
metadata:
name: image-download-sa
imagePullSecrets:
- name: local-harbor-secret
local-harbor-secret 是 镜像仓库的 Secret 对象,由用户提前手动创建,它可以通过简直数据提供 docker 仓库服务器的地址、接入服务器的用户名、密码以及用户的电子邮箱等信息。认证通过后,引用了此 ServiceAccount 的 Pod 资源即可从指定的镜像仓库中下载由 image 字段指定的镜像文件。
kind: Secret
apiVersion: v1
metadata:
name: local-harbor-secret
namespace: mh-scrm-parent
annotations:
kubesphere.io/creator: 'xxxxxxxx'
data:
.dockerconfigjson: >-
省略
type: kubernetes.io/dockerconfigjson