本节我们来学习 kubernetes 里的认证与鉴权,这一部分我们要了解一下内容:
- Secret: 加密数据的保存
- Config: 配置的保存
- RBAC: 基于角色的访问控制(Role-Based Access Control)
1. Secret
Secret 的作用是把 Pod 想要访问的加密数据,存放到 Etcd 中。然后就可以通过在 Pod 的容器里挂载 Volume 的方式,访问到这些 Secret 里保存的信息了。
1.1 Secret 定义
Secret定义如下:
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
|
// Secret holds secret data of a certain type. The total bytes of the values in
// the Data field must be less than MaxSecretSize bytes.
type Secret struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Immutable, if set to true, ensures that data stored in the Secret cannot
// be updated (only object metadata can be modified).
// If not set to true, the field can be modified at any time.
// Defaulted to nil.
// +optional
Immutable *bool `json:"immutable,omitempty" protobuf:"varint,5,opt,name=immutable"`
// Data contains the secret data. Each key must consist of alphanumeric
// characters, '-', '_' or '.'. The serialized form of the secret data is a
// base64 encoded string, representing the arbitrary (possibly non-string)
// data value here. Described in https://tools.ietf.org/html/rfc4648#section-4
// +optional
Data map[string][]byte `json:"data,omitempty" protobuf:"bytes,2,rep,name=data"`
// stringData allows specifying non-binary secret data in string form.
// It is provided as a write-only input field for convenience.
// All keys and values are merged into the data field on write, overwriting any existing values.
// The stringData field is never output when reading from the API.
// +k8s:conversion-gen=false
// +optional
StringData map[string]string `json:"stringData,omitempty" protobuf:"bytes,4,rep,name=stringData"`
// Used to facilitate programmatic handling of secret data.
// More info: https://kubernetes.io/docs/concepts/configuration/secret/#secret-types
// +optional
Type SecretType `json:"type,omitempty" protobuf:"bytes,3,opt,name=type,casttype=SecretType"`
}
type SecretType string
const (
// SecretTypeOpaque is the default. Arbitrary user-defined data
SecretTypeOpaque SecretType = "Opaque"
SecretTypeServiceAccountToken SecretType = "kubernetes.io/service-account-token"
...
)
|
Secret 的字段中:
- Immutable: 指定 Secret 实例定义是否可变
- Data: 数据,必须是经过 Base64 转码的,以免出现明文密码的安全隐患
- Type: 指定 Data 中数据的格式
1
2
3
4
5
|
# base64 编码
$ echo -n 'admin' | base64
YWRtaW4=
$ echo -n '1f2d1e2e67df' | base64
MWYyZDFlMmU2N2Rm
|
需要注意的是,像这样创建的 Secret 对象,它里面的内容仅仅是经过了转码,而并没有被加密。在真正的生产环境中,你需要在 Kubernetes 中开启 Secret 的加密插件,增强数据的安全性。下面是一个 Secret 创建示例:
1
2
3
4
5
6
7
8
9
|
# 创建 Secret yaml 格式
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
user: YWRtaW4=
pass: MWYyZDFlMmU2N2Rm
|
也可以用命令行直接创建:
1
2
3
4
5
6
7
8
9
10
11
12
|
$ cat ./username.txt
admin
$ cat ./password.txt
c1oudc0w!
$ kubectl create secret generic user --from-file=./username.txt
$ kubectl create secret generic pass --from-file=./password.txt
$ kubectl get secrets
NAME TYPE DATA AGE
user Opaque 1 51s
pass Opaque 1 51s
|
2. ConfigMap
ConfigMap 与 Secret 类似,但保存的是不需要加密的、应用所需的配置信息
ConfigMap 定义如下:
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
|
type ConfigMap struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Immutable, if set to true, ensures that data stored in the ConfigMap cannot
// be updated (only object metadata can be modified).
// If not set to true, the field can be modified at any time.
// Defaulted to nil.
// +optional
Immutable *bool `json:"immutable,omitempty" protobuf:"varint,4,opt,name=immutable"`
// Data contains the configuration data.
// Each key must consist of alphanumeric characters, '-', '_' or '.'.
// Values with non-UTF-8 byte sequences must use the BinaryData field.
// The keys stored in Data must not overlap with the keys in
// the BinaryData field, this is enforced during validation process.
// +optional
Data map[string]string `json:"data,omitempty" protobuf:"bytes,2,rep,name=data"`
// BinaryData contains the binary data.
// Each key must consist of alphanumeric characters, '-', '_' or '.'.
// BinaryData can contain byte sequences that are not in the UTF-8 range.
// The keys stored in BinaryData must not overlap with the ones in
// the Data field, this is enforced during validation process.
// Using this field will require 1.10+ apiserver and
// kubelet.
// +optional
BinaryData map[string][]byte `json:"binaryData,omitempty" protobuf:"bytes,3,rep,name=binaryData"`
}
|
ConfigMap 的字段中:
- Data: 包含配置数据
- BinaryData: 包含二进制数据,binaryData 中存储的键不得与 data 字段中的键重叠
2.1 ConfigMap 创建
ConfigMap 可以用 yaml 创建:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# 查看这个ConfigMap里保存的信息(data)
$ kubectl get configmaps ui-config -o yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ui-config
...
data:
ui.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
|
也可以通过命令行创建:
1
2
3
4
5
6
7
8
9
|
# .properties文件的内容
$ cat example/ui.properties
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
# 从.properties文件创建ConfigMap
$ kubectl create configmap ui-config --from-file=example/ui.properties
|
3. ServiceAccount
3.1 ServiceAccount 定义
ServiceAccount定义如下:
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
type ServiceAccount struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use.
// Pods are only limited to this list if this service account has a "kubernetes.io/enforce-mountable-secrets" annotation set to "true".
// This field should not be used to find auto-generated service account token secrets for use outside of pods.
// Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created.
// More info: https://kubernetes.io/docs/concepts/configuration/secret
// +optional
// +patchMergeKey=name
// +patchStrategy=merge
Secrets []ObjectReference `json:"secrets,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,2,rep,name=secrets"`
// ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images
// in pods that reference this ServiceAccount. ImagePullSecrets are distinct from Secrets because Secrets
// can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet.
// More info: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod
// +optional
ImagePullSecrets []LocalObjectReference `json:"imagePullSecrets,omitempty" protobuf:"bytes,3,rep,name=imagePullSecrets"`
// AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted.
// Can be overridden at the pod level.
// +optional
AutomountServiceAccountToken *bool `json:"automountServiceAccountToken,omitempty" protobuf:"varint,4,opt,name=automountServiceAccountToken"`
}
// ObjectReference contains enough information to let you inspect or modify the referred object.
// ---
// New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs.
// 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage.
// 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular
// restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted".
// Those cannot be well described when embedded.
// 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen.
// 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity
// during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple
// and the version of the actual struct is irrelevant.
// 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type
// will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control.
//
// Instead of using this type, create a locally provided and used type that is well-focused on your reference.
// For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 .
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +structType=atomic
type ObjectReference struct {
// Kind of the referent.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
// +optional
Kind string `json:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"`
// Namespace of the referent.
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
// +optional
Namespace string `json:"namespace,omitempty" protobuf:"bytes,2,opt,name=namespace"`
// Name of the referent.
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
// +optional
Name string `json:"name,omitempty" protobuf:"bytes,3,opt,name=name"`
// UID of the referent.
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
// +optional
UID types.UID `json:"uid,omitempty" protobuf:"bytes,4,opt,name=uid,casttype=k8s.io/apimachinery/pkg/types.UID"`
// API version of the referent.
// +optional
APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,5,opt,name=apiVersion"`
// Specific resourceVersion to which this reference is made, if any.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
// +optional
ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,6,opt,name=resourceVersion"`
// If referring to a piece of an object instead of an entire object, this string
// should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
// For example, if the object reference is to a container within a pod, this would take on a value like:
// "spec.containers{name}" (where "name" refers to the name of the container that triggered
// the event) or if no container name is specified "spec.containers[2]" (container with
// index 2 in this pod). This syntax is chosen only to have some well-defined way of
// referencing a part of an object.
// TODO: this design is not final and this field is subject to change in the future.
// +optional
FieldPath string `json:"fieldPath,omitempty" protobuf:"bytes,7,opt,name=fieldPath"`
}
// LocalObjectReference contains enough information to let you locate the
// referenced object inside the same namespace.
// +structType=atomic
type LocalObjectReference struct {
// Name of the referent.
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
// TODO: Add other useful fields. apiVersion, kind, uid?
// +optional
Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"`
}
|
3.2 ServiceAccout 作用
Service Account
- Service Account 是 Kubernetes 系统内置的一种“服务账户”,它是 Kubernetes 进行权限分配的对象
- Service Account 的授权信息和文件,保存在它所绑定的一个特殊的 Secret 对象里的。这个特殊的 Secret 对象,叫作 ServiceAccountToken
- 任何运行在 Kubernetes 集群上的应用,都必须使用这个 ServiceAccountToken 里保存的授权信息,也就是 Token,才可以合法地访问 API Server
为了方便使用,Kubernetes 提供了一个默认“服务账户”(default Service Account)。并且,任何一个运行在 Kubernetes 里的 Pod,都可以直接使用这个默认的 Service Account,而无需显示地声明挂载 default Service Account 在容器内的路径是固定的,即:/var/run/secrets/kubernetes.io/serviceaccount。
这个实现依赖的是 Projected Volume 机制。Kubernetes 在每个 Pod 创建的时候,自动在它的 spec.volumes 部分添加上了默认 ServiceAccountToken 的定义,然后自动给每个容器加上了对应的 volumeMounts 字段。这个过程对于用户来说是完全透明的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# kubectl describe pod nginx-deployment-bb48f7f4-4djf7
Mounts:
/etc/podinfo from podinfo (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-8l6js (ro)
....
Volumes:
podinfo:
Type: Projected (a volume that contains injected data from multiple sources)
DownwardAPI: true
kube-api-access-8l6js:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
|
只要应用程序加载 /var/run/secrets/kubernetes.io/serviceaccount
下这些授权文件,就可以访问并操作 Kubernetes API 了。而且,如果你使用的是 Kubernetes 官方的 Client 包(k8s.io/client-go)的话,它还可以自动加载这个目录下的文件。这种把 Kubernetes 客户端以容器的方式运行在集群里,然后使用 default Service Account 自动授权的方式,被称作“InClusterConfig”。
3.3 ServiceAccount 创建和使用
1
2
3
4
5
|
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: mynamespace
name: example-sa
|
当我们创建 ServiceAccount 对象时 Kubernetes 会为 ServiceAccount 自动创建并分配一个 Secret 对象,这个 Secret,就是这个 ServiceAccount 对应的、用来跟 APIServer 进行交互的授权文件,我们一般称它为:Token。创建完之后,用户就可以声明使用这个 ServiceAccount
1
2
3
4
5
6
7
8
9
10
11
|
apiVersion: v1
kind: Pod
metadata:
namespace: mynamespace
name: sa-token-test
spec:
containers:
- name: nginx
image: nginx:1.7.9
serviceAccountName: example-sa
|
Pod 被创建后,这个 ServiceAccount 的 token,也就是一个 Secret 对象,被 Kubernetes 自动挂载到了容器的 /var/run/secrets/kubernetes.io/serviceaccount
目录下。
如果一个 Pod 没有声明 serviceAccountName,Kubernetes 会自动在它的 Namespace 下创建一个名叫 default 的默认 ServiceAccount,然后分配给这个 Pod。但在这种情况下,这个默认 ServiceAccount 并没有关联任何 Role。也就是说,此时它有访问 APIServer 的绝大多数权限。当然,这个访问所需要的 Token,还是默认 ServiceAccount 对应的 Secret 对象为它提供的。
4. RBAC
基于角色的访问控制,有以下三个核心概念:
- Role: 角色,一组规则,定义了一组对 Kubernetes API 对象的操作权限。
- Subject: 被作用者,既可以是“人”,也可以是“机器”,也可以是你在 Kubernetes 里定义的“用户”
- RoleBinding: 定义了“被作用者”和“角色”的绑定关系
Role 和 RoleBinding 对象都是 Namespaced 对象(Namespaced Object),它们对权限的限制规则仅在它们自己的 Namespace 内有效,roleRef 也只能引用当前 Namespace 里的 Role 对象。
对于非 Namespaced(Non-namespaced)对象(比如:Node),或者,某一个 Role 想要作用于所有的 Namespace 的时候 要使用 ClusterRole 和 ClusterRoleBinding。ClusterRole 和 ClusterRoleBinding 的用法跟 Role 和 RoleBinding 几乎一致。只不过,它们没有 Namespace 字段。
4.1 Role
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
29
30
31
32
33
|
// Role is a namespaced, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding.
type Role struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Rules holds all the PolicyRules for this Role
// +optional
Rules []PolicyRule `json:"rules" protobuf:"bytes,2,rep,name=rules"`
}
type PolicyRule struct {
// Verbs is a list of Verbs that apply to ALL the ResourceKinds contained in this rule. '*' represents all verbs.
Verbs []string `json:"verbs" protobuf:"bytes,1,rep,name=verbs"`
// APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of
// the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups.
// +optional
APIGroups []string `json:"apiGroups,omitempty" protobuf:"bytes,2,rep,name=apiGroups"`
// Resources is a list of resources this rule applies to. '*' represents all resources.
// +optional
Resources []string `json:"resources,omitempty" protobuf:"bytes,3,rep,name=resources"`
// ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed.
// +optional
ResourceNames []string `json:"resourceNames,omitempty" protobuf:"bytes,4,rep,name=resourceNames"`
// NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path
// Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding.
// Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both.
// +optional
NonResourceURLs []string `json:"nonResourceURLs,omitempty" protobuf:"bytes,5,rep,name=nonResourceURLs"`
}
|
在 Role 的定义中:
- meta.namespace 指定了 Role 能产生作用的 Namespace
- Rules 定义了权限的规则
- Verbs: 可执行的操作,全集包括:
["get", "list", "watch", "create", "update", "patch", "delete"]
- APIGroups: API 对象集合限定,对应 API 对象定义中的 ApiVersion
- Resources: 类型限定,对应 API 对象定义中的 Kind
- ResourceNames: 实例限定,对应 API 对象定义中 Name
1
2
3
4
5
6
7
8
9
10
|
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: mynamespace
name: example-role
rules:
- apiGroups: [""] # "" 表示所有对象
resources: ["pods"]
verbs: ["get", "watch", "list"]
|
4.2 RoleBinding
RoleBinding 定义如下:
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
|
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace.
// It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given
// namespace only have effect in that namespace.
type RoleBinding struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Subjects holds references to the objects the role applies to.
// +optional
Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"`
// RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace.
// If the RoleRef cannot be resolved, the Authorizer must return an error.
RoleRef RoleRef `json:"roleRef" protobuf:"bytes,3,opt,name=roleRef"`
}
// RoleRef contains information that points to the role being used
type RoleRef struct {
// APIGroup is the group for the resource being referenced
APIGroup string `json:"apiGroup" protobuf:"bytes,1,opt,name=apiGroup"`
// Kind is the type of resource being referenced
Kind string `json:"kind" protobuf:"bytes,2,opt,name=kind"`
// Name is the name of resource being referenced
Name string `json:"name" protobuf:"bytes,3,opt,name=name"`
}
|
RoleBinding:
- Subjects: 被作用者
- RoleRef: 关联的 Role 对象,通过 Name 引用 Role 对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-rolebinding
namespace: mynamespace
subjects:
- kind: User
name: example-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: example-role
apiGroup: rbac.authorization.k8s.io
|
4.3 ClusterRole
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
|
// ClusterRole is a cluster level, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding or ClusterRoleBinding.
type ClusterRole struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Rules holds all the PolicyRules for this ClusterRole
// +optional
Rules []PolicyRule `json:"rules" protobuf:"bytes,2,rep,name=rules"`
// AggregationRule is an optional field that describes how to build the Rules for this ClusterRole.
// If AggregationRule is set, then the Rules are controller managed and direct changes to Rules will be
// stomped by the controller.
// +optional
AggregationRule *AggregationRule `json:"aggregationRule,omitempty" protobuf:"bytes,3,opt,name=aggregationRule"`
}
// AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole
type AggregationRule struct {
// ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules.
// If any of the selectors match, then the ClusterRole's permissions will be added
// +optional
ClusterRoleSelectors []metav1.LabelSelector `json:"clusterRoleSelectors,omitempty" protobuf:"bytes,1,rep,name=clusterRoleSelectors"`
}
|
1
2
3
4
5
6
7
8
9
|
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-clusterrole
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
|
内置 ClusterRole
在 Kubernetes 中已经内置了很多个为系统保留的 ClusterRole,它们的名字都以 system: 开头。这些系统 ClusterRole,是绑定给 Kubernetes 系统组件对应的 ServiceAccount 使用的。
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
|
# kubectl describe clusterrole system:kube-scheduler
Name: system:kube-scheduler
Labels: kubernetes.io/bootstrapping=rbac-defaults
Annotations: rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
events [] [] [create patch update]
events.events.k8s.io [] [] [create patch update]
bindings [] [] [create]
endpoints [] [] [create]
pods/binding [] [] [create]
tokenreviews.authentication.k8s.io [] [] [create]
subjectaccessreviews.authorization.k8s.io [] [] [create]
leases.coordination.k8s.io [] [] [create]
pods [] [] [delete get list watch]
namespaces [] [] [get list watch]
nodes [] [] [get list watch]
persistentvolumeclaims [] [] [get list watch]
persistentvolumes [] [] [get list watch]
replicationcontrollers [] [] [get list watch]
services [] [] [get list watch]
replicasets.apps [] [] [get list watch]
statefulsets.apps [] [] [get list watch]
replicasets.extensions [] [] [get list watch]
poddisruptionbudgets.policy [] [] [get list watch]
csidrivers.storage.k8s.io [] [] [get list watch]
csinodes.storage.k8s.io [] [] [get list watch]
csistoragecapacities.storage.k8s.io [] [] [get list watch]
endpoints [] [kube-scheduler] [get update]
leases.coordination.k8s.io [] [kube-scheduler] [get update]
pods/status [] [] [patch update]
|
内置用户可用 ClusterRole
除此之外,Kubernetes 还提供了四个预先定义好的 ClusterRole 来供用户直接使用:cluster-admin;admin;edit;view。
1
2
3
4
5
6
7
8
9
|
# kubectl describe clusterrole cluster-admin -n kube-system
Name: cluster-admin
Labels: kubernetes.io/bootstrapping=rbac-defaults
Annotations: rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
*.* [] [] [*]
[*] [] [*]
|
4.4 ClusterRoleBinding
ClusterRoleBinding 定义如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
type ClusterRoleBinding struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Subjects holds references to the objects the role applies to.
// +optional
Subjects []Subject `json:"subjects,omitempty" protobuf:"bytes,2,rep,name=subjects"`
// RoleRef can only reference a ClusterRole in the global namespace.
// If the RoleRef cannot be resolved, the Authorizer must return an error.
RoleRef RoleRef `json:"roleRef" protobuf:"bytes,3,opt,name=roleRef"`
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-clusterrolebinding
subjects:
- kind: User
name: example-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: example-clusterrole
apiGroup: rbac.authorization.k8s.io
|
4.2 Subject
Subject 定义如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference,
// or a value for non-objects such as user and group names.
// +structType=atomic
type Subject struct {
// Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount".
// If the Authorizer does not recognized the kind value, the Authorizer should report an error.
Kind string `json:"kind" protobuf:"bytes,1,opt,name=kind"`
// APIGroup holds the API group of the referenced subject.
// Defaults to "" for ServiceAccount subjects.
// Defaults to "rbac.authorization.k8s.io" for User and Group subjects.
// +optional
APIGroup string `json:"apiGroup,omitempty" protobuf:"bytes,2,opt.name=apiGroup"`
// Name of the object being referenced.
Name string `json:"name" protobuf:"bytes,3,opt,name=name"`
// Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty
// the Authorizer should report an error.
// +optional
Namespace string `json:"namespace,omitempty" protobuf:"bytes,4,opt,name=namespace"`
}
|
从前面的 RoleBinding/ClusterRoleBinding 对象里我们可以看到,RoleBinding 关联的 Subject 的类型是 User。可是,在 Kubernetes 中,其实并没有一个叫作“User”的 API 对象。这里的 User 只是一个授权系统里的逻辑概念。它需要通过外部认证服务,比如 Keystone,来提供。或者,你也可以直接给 APIServer 指定一个用户名、密码文件。那么 Kubernetes 的授权系统,就能够从这个文件里找到对应的“用户”了。
在大多数私有的使用环境中,我们只要使用 Kubernetes 提供的内置“用户”,就是前面提到的:ServiceAccount。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-rolebinding
namespace: mynamespace
subjects:
- kind: ServiceAccount
name: example-sa
namespace: mynamespace
roleRef:
kind: Role
name: example-role
apiGroup: rbac.authorization.k8s.io
|
用户组
Kubernetes 还拥有“用户组”(Group)的概念,如果你为 Kubernetes 配置了外部认证服务的话,这个“用户组”的概念就会由外部认证服务提供。而对于 Kubernetes 的内置“用户”ServiceAccount 来说,上述“用户组”的概念也同样适用。实际上,一个 ServiceAccount,在 Kubernetes 里对应的“用户”的名字是:system:serviceaccount:<Namespace名字>:<ServiceAccount名字>
,它对应的内置“用户组”的名字,就是:system:serviceaccounts:<Namespace名字>
有了用户组,我们在 RoleBinding 里定义如下的 subjects,这就意味着这个 Role 的权限规则,作用于 mynamespace 里的所有 ServiceAccount。
1
2
3
4
|
subjects:
- kind: Group
name: system:serviceaccounts:mynamespace
apiGroup: rbac.authorization.k8s.io
|
下面的绑定规则则意味着 Role 的权限规则,作用于整个系统里的所有 ServiceAccount。
1
2
3
4
5
|
subjects:
- kind: Group
name: system:serviceaccounts
apiGroup: rbac.authorization.k8s.io
|