经过了API对象自定义控制器两节的内容,可以自己实现一个编排对象,并为这个对象实现自己的控制器模式。

k8s项目,可以基于插件来完成这些工作而完全不需要修改任何代码。但是外部插件在k8s中新增和操作API对象,就需要先了解一下RBAC。

因为对k8s中任何API对象的操作都是通过访问kube-apiserver来完成的。需要APIServer来完成授权工作,k8s中授权工作的机制就是RBAC。

RBAC最基本的三个概念:

  • Role:角色。一组规则,定义了一组对k8s API对象的操作权限。
  • Subject:被作用者。可以是“人”,“机器”,也可以是k8s中定义的“用户”。
  • RoleBinding:定义了“被作用者”和用户之间的绑定关系。

k8s中Role就是一个API对象:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: mynamespace
  name: example-role
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

这个Role对象指定了能够作用的Namespace,Namespace 是 Kubernetes 项目里的一个逻辑管理单位。不同 Namespace 的 API 对象,在通过 kubectl 命令进行操作的时候,是互相隔离开的。默认的kubectl命令默认的Namespace是default。

这个角色就是允许“被作用者”,对 mynamespace 下面的 Pod 对象,进行 GET、WATCH 和 LIST 操作。

通过RoleBinding将角色与被作用者进行绑定,RoleBinding也是一个API对象:

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

而User只是一个逻辑概念,需要通过外部认证服务,例如keyStore来提供,或者直接给APIServer指定一个用户名,密码文件。

RoleBinding通过roleRef字段进行关系绑定。Role 和 RoleBinding 对象都是 Namespaced 对象(Namespaced Object),它们对权限的限制规则仅在它们自己的 Namespace 内有效,roleRef 也只能引用当前 Namespace 里的 Role 对象

对于非 Namespaced(Non-namespaced)对象(比如:Node),或者,某一个 Role 想要作用于所有的 Namespace 的时候,我们又该如何去做授权呢?

使用 ClusterRole 和 ClusterRoleBinding 这两个组合了

用法与Role 和 RoleBinding 完全一样。只不过,它们的定义里,没有了 Namespace 字段,

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: example-clusterrole
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
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

通过这两者组合授权的用户具有操作所有Namespace里对应对象的权限。

Role对象的rule字段也可以进一步细化,只对某一具体的对象进行权限设置。

rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["my-config"]
  verbs: ["get"]

在大多数时候,我们其实都不太使用“用户”这个功能,而是直接使用 Kubernetes 里的“内置用户”。通过一个具体的实例来为你讲解一下为 ServiceAccount 分配权限的过程.

首先定义一个 ServiceAccount:

apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: mynamespace
  name: example-sa

然后,我们通过编写 RoleBinding 的 YAML 文件,来为这个 ServiceAccount 分配权限:

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

接着,我们用 kubectl 命令创建这三个对象:

$ kubectl create -f svc-account.yaml
$ kubectl create -f role-binding.yaml
$ kubectl create -f role.yaml

查看创建的serverAccount可以发现,k8s自动为一个ServiceAccount创建并分配一个Secret对象,用来跟APIServer交互。

创建的Pod可以指定创建的ServiceAccount

apiVersion: v1
kind: Pod
metadata:
  namespace: mynamespace
  name: sa-token-test
spec:
  containers:
  - name: nginx
    image: nginx:1.7.9
  serviceAccountName: example-sa

这个ServiecAccount会自动挂载到容器的/var/run/secrets/kubernetes.io/serviceaccount 目录下,这样容器里的应用就可以通过目录中的授权文件来访问APIServer了。