AWS-EKS-16--聊一聊ServiceAccount

摘要

聊一聊ServiceAccount

  • 网上关于ServiceAccount的介绍有很多,但大多都比较晦涩难懂,不好理解,这里我基于自己的理解聊一聊ServiceAccount。

  • ServiceAccount是k8s中的用户,其被定义在namespace下,可以被关联到pod上,使其获得相应的权限。

    • ServiceAccount可以与k8s中的Role或者ClusterRole进行绑定,以使其具有访问k8s内部资源的权限,当pod关联ServiceAccount后也就获得了相应的权限。参考AWS-EKS-12--部署 Dashboard UI
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # dashboard-adminuser.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
    name: admin-user
    namespace: kubernetes-dashboard
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
    name: admin-user
    roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: ClusterRole
    name: cluster-admin
    subjects:
    - kind: ServiceAccount
    name: admin-user
    namespace: kubernetes-dashboard
    1
    2
    3
    4
    5
    6
    7
    8
    $ eksctl create iamserviceaccount \
    --cluster=eks-lexing \
    --profile eks-us-west-2 \
    --namespace=kube-system \
    --name=aws-load-balancer-controller \
    --role-name AmazonEKSLoadBalancerControllerRole \
    --attach-policy-arn=arn:aws:iam::743263909644:policy/AWSLoadBalancerControllerIAMPolicy \
    --approve
  • ServiceAccount default 在 Kubernetes 中是默认存在的,它通常与运行在 Pod 内的应用程序关联,用于与 Kubernetes API 服务器进行身份验证和授权。default ServiceAccount 是每个命名空间中的默认 ServiceAccount,如果没有为 Pod 显式指定 ServiceAccount,则会自动关联到 default ServiceAccount。

  • default ServiceAccount的权限是由所分配的角色(Role)或集群角色(ClusterRole)定义的。在默认情况下,default ServiceAccount没有任何特权或访问权限。它只能访问其所在命名空间的一些基本资源,例如查看自身的 Pod、Service、Endpoints 等。

创建SA

1
2
3
4
5
6
7
8
9
10
11
12
# 方式1,使用kubectl命令行直接创建
$ kubectl create serviceaccount <serviceaccount-name> -n <namespace>

# 方式2,基于yaml
# sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: <serviceaccount-name>
namespace: <namespace>

$ kubectl apply -f sa.yaml

查询SA

1
2
3
4
5
$ k get sa -n kubernetes-dashboard
NAME SECRETS AGE
admin-user 0 8d
default 0 8d
kubernetes-dashboard 0 8d

SA与Role或者ClusterRole进行绑定

  • SA绑定Role

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-service-account
namespace: test
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: my-role
namespace: test # 与ClusterRole的区别就是Role要绑定到Namespace
rules:
- apiGroups: [""] # 限定API组,为空则为默认的 core API 组
resources: ["pods", "services", "configmaps"] # 要访问的资源
verbs: ["get", "list", "watch"] # 开放的权限
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: my-role-binding
subjects:
- kind: ServiceAccount
name: my-service-account
namespace: test
roleRef:
kind: Role
name: my-role
apiGroup: rbac.authorization.k8s.io
  • SA绑定ClusterRole

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-service-account
namespace: test
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: my-cluster-role
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: my-cluster-role-binding
subjects:
- kind: ServiceAccount
name: my-service-account
namespace: test
roleRef:
kind: ClusterRole
name: my-cluster-role
apiGroup: rbac.authorization.k8s.io

API组
Kubernetes中有许多常见的API组,每个API组都包含一组相关的资源。以下是一些常见的API组:

  • core:该API组是Kubernetes中的默认API组,包含核心资源,如pods、services、configmaps、secrets等。
  • apps:该API组包含应用程序相关的资源,如deployments、replicasets、daemonsets、statefulsets等。
  • batch:该API组包含批处理作业相关的资源,如jobs、cronjobs等。
  • extensions:这是Kubernetes早期版本中广泛使用的API组,现在已经被appsnetworking.k8s.io API组所取代。它包含一些资源,如replicationcontrollers、ingresses等。
  • networking.k8s.io:该API组包含与网络相关的资源,如ingresses、networkpolicies等。
  • storage.k8s.io:该API组包含存储相关的资源,如storageclasses、persistentvolumes、persistentvolumeclaims等。
  • autoscaling:该API组包含自动扩展相关的资源,如horizontalpodautoscalers。
  • rbac.authorization.k8s.io:该API组包含与角色和访问控制相关的资源,如roles、rolebindings、clusterroles、clusterrolebindings等。
    这只是一小部分常见的API组,实际上还有许多其他的API组,根据您的Kubernetes集群的版本和所使用的插件,可能会有其他自定义的API组。您可以使用kubectl api-resources命令查看集群中所有可用的API组和资源。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# 这里 APIVERSION 中版本中斜线前面的就是 API组名称 ,没有斜线的就是默认的 core 组
$ kubectl api-resources
NAME SHORTNAMES APIVERSION NAMESPACED KIND
bindings v1 true Binding
componentstatuses cs v1 false ComponentStatus
configmaps cm v1 true ConfigMap
endpoints ep v1 true Endpoints
events ev v1 true Event
limitranges limits v1 true LimitRange
namespaces ns v1 false Namespace
nodes no v1 false Node
persistentvolumeclaims pvc v1 true PersistentVolumeClaim
persistentvolumes pv v1 false PersistentVolume
pods po v1 true Pod
podtemplates v1 true PodTemplate
replicationcontrollers rc v1 true ReplicationController
resourcequotas quota v1 true ResourceQuota
secrets v1 true Secret
serviceaccounts sa v1 true ServiceAccount
services svc v1 true Service
mutatingwebhookconfigurations admissionregistration.k8s.io/v1 false MutatingWebhookConfiguration
validatingwebhookconfigurations admissionregistration.k8s.io/v1 false ValidatingWebhookConfiguration
customresourcedefinitions crd,crds apiextensions.k8s.io/v1 false CustomResourceDefinition
apiservices apiregistration.k8s.io/v1 false APIService
controllerrevisions apps/v1 true ControllerRevision
daemonsets ds apps/v1 true DaemonSet
deployments deploy apps/v1 true Deployment
replicasets rs apps/v1 true ReplicaSet
statefulsets sts apps/v1 true StatefulSet
tokenreviews authentication.k8s.io/v1 false TokenReview
localsubjectaccessreviews authorization.k8s.io/v1 true LocalSubjectAccessReview
selfsubjectaccessreviews authorization.k8s.io/v1 false SelfSubjectAccessReview
selfsubjectrulesreviews authorization.k8s.io/v1 false SelfSubjectRulesReview
subjectaccessreviews authorization.k8s.io/v1 false SubjectAccessReview
horizontalpodautoscalers hpa autoscaling/v2 true HorizontalPodAutoscaler
cronjobs cj batch/v1 true CronJob
jobs batch/v1 true Job
certificatesigningrequests csr certificates.k8s.io/v1 false CertificateSigningRequest
leases coordination.k8s.io/v1 true Lease
eniconfigs crd.k8s.amazonaws.com/v1alpha1 false ENIConfig
endpointslices discovery.k8s.io/v1 true EndpointSlice
ingressclassparams elbv2.k8s.aws/v1beta1 false IngressClassParams
targetgroupbindings elbv2.k8s.aws/v1beta1 true TargetGroupBinding
events ev events.k8s.io/v1 true Event
flowschemas flowcontrol.apiserver.k8s.io/v1beta3 false FlowSchema
prioritylevelconfigurations flowcontrol.apiserver.k8s.io/v1beta3 false PriorityLevelConfiguration
nodes metrics.k8s.io/v1beta1 false NodeMetrics
pods metrics.k8s.io/v1beta1 true PodMetrics
ingressclasses networking.k8s.io/v1 false IngressClass
ingresses ing networking.k8s.io/v1 true Ingress
networkpolicies netpol networking.k8s.io/v1 true NetworkPolicy
runtimeclasses node.k8s.io/v1 false RuntimeClass
poddisruptionbudgets pdb policy/v1 true PodDisruptionBudget
clusterrolebindings rbac.authorization.k8s.io/v1 false ClusterRoleBinding
clusterroles rbac.authorization.k8s.io/v1 false ClusterRole
rolebindings rbac.authorization.k8s.io/v1 true RoleBinding
roles rbac.authorization.k8s.io/v1 true Role
priorityclasses pc scheduling.k8s.io/v1 false PriorityClass
csidrivers storage.k8s.io/v1 false CSIDriver
csinodes storage.k8s.io/v1 false CSINode
csistoragecapacities storage.k8s.io/v1 true CSIStorageCapacity
storageclasses sc storage.k8s.io/v1 false StorageClass
volumeattachments storage.k8s.io/v1 false VolumeAttachment
securitygrouppolicies sgp vpcresources.k8s.aws/v1beta1 true SecurityGroupPolicy

SA与Deployment或者Pod关联

  • SA与Deployment关联

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
serviceAccountName: my-service-account # 指定sa名称
containers:
- name: my-container
image: my-image
  • SA与Pod关联

1
2
3
4
5
6
7
8
9
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: my-service-account # 指定sa名称
containers:
- name: my-container
image: my-image

小贴士

  • serviceAccount 和 serviceAccountName 是 Kubernetes YAML 配置中用于关联 Service Account 的两个属性,它们有一些区别:
  • serviceAccountName:这是一个字符串属性,用于指定要与 Pod 或 Deployment 关联的 Service Account 的名称。它是最常用的属性,只需提供 Service Account 的名称即可。示例:serviceAccountName: my-service-account
  • serviceAccount:这是一个对象属性,用于指定要与 Pod 或 Deployment 关联的 Service Account 的更详细信息。它可以提供 Service Account 的名称和命名空间。示例:
1
2
3
serviceAccount:
name: my-service-account
namespace: my-namespace

注意:namespace 字段是可选的,如果不指定,它将使用当前 Pod 或 Deployment 所在的命名空间。

  • 总结来说,serviceAccountName 是一种更简洁的方式,只需提供 Service Account 的名称。而 serviceAccount 则可以提供更多关于 Service Account 的详细信息,如名称和命名空间。在大多数情况下,使用 serviceAccountName 就足够了,除非需要更精细地控制 Service Account 的属性。

查询指定的SA被绑定到哪些角色

1
2
3
4
5
6
$ kubectl get rolebindings,clusterrolebindings -A \
-o 'custom-columns=KIND:.kind,NAMESPACE:.metadata.namespace,NAME:.metadata.name,ROLE-KIND:.roleRef.kind,ROLE:.roleRef.name, SUBJECT-KIND:.subjects[*].kind,SUBJECT-NAMESPACE:.subjects[*].namespace,SUBJECT-NAME:.subjects[*].name' \
| (head -n 1 && awk '{if ($8 == "kubernetes-dashboard") print}')
KIND NAMESPACE NAME ROLE-KIND ROLE SUBJECT-KIND SUBJECT-NAMESPACE SUBJECT-NAME
RoleBinding kubernetes-dashboard kubernetes-dashboard Role kubernetes-dashboard ServiceAccount kubernetes-dashboard kubernetes-dashboard
ClusterRoleBinding <none> kubernetes-dashboard ClusterRole kubernetes-dashboard ServiceAccount kubernetes-dashboard kubernetes-dashboard

查询指定的SA被关联到哪些deploy

1
2
3
4
5
6
$ k get deploy -A \
-o 'custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,SERVICEACCOUNT:.spec.template.spec.serviceAccountName' \
| (head -n 1 && awk '{if ($3 == "kubernetes-dashboard") print}')
NAMESPACE NAME SERVICEACCOUNT
kubernetes-dashboard dashboard-metrics-scraper kubernetes-dashboard
kubernetes-dashboard kubernetes-dashboard kubernetes-dashboard

查询指定的SA被关联到哪些pod

1
2
3
4
5
6
$ k get pod -A \
-o 'custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,SERVICEACCOUNT:.spec.serviceAccountName' \
| (head -n 1 && awk '{if ($3 == "kubernetes-dashboard") print}')
NAMESPACE NAME SERVICEACCOUNT
kubernetes-dashboard dashboard-metrics-scraper-7bc864c59-sqjq8 kubernetes-dashboard
kubernetes-dashboard kubernetes-dashboard-6c7ccbcf87-zb2hb kubernetes-dashboard

编辑SA

  • 比如我们要为已经创建好的SA关联AWS IAM角色,需要编辑SA,将IAM角色添加到SA的注释中。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ k edit sa -n kube-system aws-load-balancer-controller
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::743263909644:role/AmazonEKSLoadBalancerControllerRole
creationTimestamp: "2023-07-04T09:20:41Z"
labels:
app.kubernetes.io/managed-by: eksctl
name: aws-load-balancer-controller
namespace: kube-system
resourceVersion: "1707669"
uid: 857200a6-2e16-4939-bbbc-483dd579acbb
  • 也可以直接通过命令行添加注解

1
2
3
$ kubectl annotate serviceaccount aws-load-balancer-controller \
-n kube-system \
eks.amazonaws.com/role-arn=arn:aws:iam::743263909644:role/AmazonEKSLoadBalancerControll
  • ServiceAccount被修改过后,关联的pod需要重新启动才能生效。