对于资源对象的操作都是通过 APIServer 进行的,集群通过 RBAC(基于角色的权限控制)来判断请求是否合法。

通过 Kubernetes API 动态配置策略来启用RBAC,要在 kube-apiserver 中添加参数 —authorization-mode=RBAC,kubeadm 安装的集群默认开启。

  1. # 查看 Master 节点上 apiserver 的静态 Pod 定义文件:
  2. $ cat /etc/kubernetes/manifests/kube-apiserver.yaml
  3. ...
  4. - --authorization-mode=Node,RBAC
  5. ...

API对象

在 Kubernetes 集群中,一个 API 对象在 Etcd 里的完整资源路径,是由:Group(API 组)、Version(API 版本)和 Resource(API 资源类型)三个部分组成。树形结构表示如下:
image.png

命令查看集群中 API 组织形式

  1. $ kubectl get --raw /
  2. {
  3. "paths": [
  4. "/api",
  5. "/api/v1",
  6. "/apis",
  7. "/apis/",
  8. ......
  9. "/version"
  10. ]
  11. }

查询对象 /apis/batch/v1 数据
##方式一

  1. $ kubectl get --raw /apis/batch/v1 | python -m json.tool
  2. {
  3. "apiVersion": "v1",
  4. "groupVersion": "batch/v1",
  5. "kind": "APIResourceList",
  6. "resources": [
  7. {
  8. "categories": [
  9. "all"
  10. ],
  11. "kind": "Job",
  12. "name": "jobs",
  13. "namespaced": true,
  14. "singularName": "",
  15. "storageVersionHash": "mudhfqk/qZY=",
  16. "verbs": [
  17. "create",
  18. "delete",
  19. "deletecollection",
  20. "get",
  21. "list",
  22. "patch",
  23. "update",
  24. "watch"
  25. ]
  26. },
  27. {
  28. "kind": "Job",
  29. "name": "jobs/status",
  30. "namespaced": true,
  31. "singularName": "",
  32. "verbs": [
  33. "get",
  34. "patch",
  35. "update"
  36. ]
  37. }
  38. ]
  39. }

方式二

  1. # 开启端口
  2. $ kubectl proxy
  3. Starting to serve on 127.0.0.1:8001
  4. # 新打开一个终端窗口执行命令
  5. $ curl http://127.0.0.1:8001/apis/batch/v1
  6. {
  7. "kind": "APIResourceList",
  8. "apiVersion": "v1",
  9. "groupVersion": "batch/v1",
  10. "resources": [
  11. {
  12. "name": "jobs",
  13. "singularName": "",
  14. "namespaced": true,
  15. "kind": "Job",
  16. "verbs": [
  17. "create",
  18. "delete",
  19. "deletecollection",
  20. "get",
  21. "list",
  22. "patch",
  23. "update",
  24. "watch"
  25. ],
  26. "categories": [
  27. "all"
  28. ],
  29. "storageVersionHash": "mudhfqk/qZY="
  30. },
  31. {
  32. "name": "jobs/status",
  33. "singularName": "",
  34. "namespaced": true,
  35. "kind": "Job",
  36. "verbs": [
  37. "get",
  38. "patch",
  39. "update"
  40. ]
  41. }
  42. ]
  43. }

Kubernetes API 支持通过标准 HTTP POST、PUT、DELETE 和 GET 在指定 PATH 路径上创建、更新、删除和检索操作,并使用 JSON 作为默认的数据交互格式。

Deployment 对象YAML 文件的声明示例

  1. apiVersion: apps/v1
  2. kind: Deployment

Deployment 是 API 对象的资源类型(Resource),apps 是组(Group),v1 是版本(Version)。Resource、API Group、Version 就定义了一个唯一的 HTTP 路径,然后在 kube-apiserver 端对这个 url 进行了监听,把对应的请求传递给对应的控制器进行处理。

RBAC

Kubernetes 所有资源对象都是模型化的 API 对象,允许执行 CRUD(Create、Read、Update、Delete) 操作,如资源:

  • Pods
  • ConfigMaps
  • Deployments
  • Nodes
  • Secrets
  • Namespaces
  • ……

对于资源对象可存在的操作有:

  • create
  • get
  • delete
  • list
  • update
  • edit
  • watch
  • exec
  • patch

要在 Kubernetes 中通过 RBAC 来对资源进行权限管理,要了解的概念:

  • Rule:规则,是一组属于不同 API Group 资源上的一组操作的集合
  • Role 和 ClusterRole:角色和集群角色,两个对象都包含Rules 元素,二者的区别在于,在 Role 中,定义的规则只适用于单个命名空间,也就是和 namespace 关联的,而 ClusterRole 是集群范围内的,因此定义的规则不受命名空间的约束。
  • Subject:主题,对应集群中尝试操作的对象,集群中定义了3种类型的主题资源:
    • User Account:用户,由外部独立服务进行管理的,管理员进行私钥的分配
    • Group:组,用来关联多个账户的,集群中有一些默认创建的组,比如 cluster-admin
    • Service Account:服务帐号,通过 Kubernetes API 来管理的一些用户帐号,和 namespace 进行关联的,适用于集群内部运行的应用程序,需要通过 API 来完成权限认证
  • RoleBinding 和 ClusterRoleBinding:角色绑定和集群角色绑定,把声明的 Subject 和 Role 进行绑定的过程(给某个用户绑定上操作的权限),二者区别:RoleBinding 只会影响到当前 namespace 下面的资源操作权限,而 ClusterRoleBinding 会影响到所有的 namespace。

只能访问指定命名空间的普通用户

需求

创建一个 User Account,只能访问 kube-system 命名空间下的 pods 和 deployments,用户信息如下:

username: luo
group: mogul

创建用户凭证

Kubernetes 没有 User Account 的 API 对象,这里使用 OpenSSL 证书来创建一个 User

# 给用户 luo 创建一个私钥,命名成 luo.key
$ openssl genrsa -out luo.key 2048

# 用刚创建的私钥创建一个证书签名请求文件:luo.csr,要确保在-subj参数中指定用户名和组(CN表示用户名,O表示组)
$ openssl req -new -key luo.key -out luo.csr -subj "/CN=luo/O=mogul"

# 用集群证书目录 /etc/kubernetes/pki/ 下的ca.crt 和 ca.key两文件来批准上面的证书请求,有效期 500 天
$ openssl x509 -req -in luo.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out luo.crt -days 500

# 查看目录下生成的证书文件
$ ls
luo.crt  luo.csr  luo.key

# 用证书文件和私钥文件在集群中创建新的凭证和上下文(Context)
$ kubectl config set-credentials luo --client-certificate=luo.crt --client-key=luo.key

# 创建用户luo,设置Context,并指定一个namespace
$ kubectl config set-context luo-context --cluster=kubernetes --namespace=kube-system --user=luo

# 用户luo创建成功,因为还没给用户定义任何操作权限,故目前会报错
$ kubectl get pods --context=luo-context
Error from server (Forbidden): pods is forbidden: User "luo" cannot list resource "pods" in API group "" in the namespace "kube-system"

创建角色

创建一个允许用户操作 Deployment、Pod、ReplicaSets 的角色 (luo-role.yaml)

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: luo-role
  namespace: kube-system
rules:
- apiGroups: ["", "apps"]
  resources: ["deployments", "replicasets", "pods"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # 也可以使用['*']

应用
$ kubectl create -f luo-role.yaml

创建角色权限绑定

创建 RoleBinding 对象,将 luo-role 角色和用户 luo 进行绑定:(luo-rolebinding.yaml)

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: luo-rolebinding
  namespace: kube-system
subjects:
- kind: User
  name: luo
  apiGroup: ""
roleRef:
  kind: Role
  name: luo-role
  apiGroup: rbac.authorization.k8s.io  # 留空字符串也可以,则使用当前的apiGroup

应用
$ kubectl apply -f luo-rolebinding.yaml

验证

使用 luo-context 上下文操作集群

$ kubectl get pods --context=luo-context
NAME                              READY   STATUS    RESTARTS   AGE
coredns-6d56c8448f-qj99n          1/1     Running   1          86d
coredns-6d56c8448f-rqcjb          1/1     Running   0          60d
etcd-m1                           1/1     Running   1          86d
kube-apiserver-m1                 1/1     Running   1          86d
kube-controller-manager-m1        1/1     Running   2          86d
kube-flannel-ds-9mxqh             1/1     Running   2          86d
kube-proxy-cwcqt                  1/1     Running   1          86d
kube-scheduler-m1                 1/1     Running   2          86d
metrics-server-5d5df49765-76v2g   1/1     Running   0          3d2h

说明:
1、使用kubectl时没有指定命名空间,因为创建Context时就绑定了命名空间kube-system,所以默认查看的就是命名空间 kube-system 中的信息;
2、因为只授权了命名空间 kube-system 的资源权限,故其它ns下的资源都无法查看。

拥有指定命名空间权限的SA

需求

创建一个 Servcie Account,只能访问 kube-system 命名空间下的 pods 和 deployments 。

创建

创建 ServiceAccount 对象
$ kubectl create sa luo-sa -n kube-system

或者以 yaml 文件形式创建

apiVersion: v1
kind: ServiceAccount
metadata:
  name: luo-sa
  namespace: kube-system

创建 Role 对象 (luo-sa-role.yaml)

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: luo-sa-role
  namespace: kube-system
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

创建RoleBinding 对象,将 luo-sa 和角色 luo-sa-role 进行绑定:(luo-sa-rolebinding.yaml)

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: luo-sa-rolebinding
  namespace: kube-system
subjects:
- kind: ServiceAccount
  name: luo-sa
  namespace: kube-system
roleRef:
  kind: Role
  name: luo-sa-role
  apiGroup: rbac.authorization.k8s.io

应用
$ kubectl create -f luo-sa-rolebinding.yaml

验证

# 查找
$ kubectl get secret -n kube-system |grep luo-sa
luo-sa-token-nxgqx   kubernetes.io/service-account-token   3         47m

# 生成一串很长的base64后的字符串
$ kubectl get secret luo-sa-token-nxgqx -o jsonpath={.data.token} -n kube-system |base64 -d

将生成的字符串用来登陆 Dashboard ,进入页面可查看到命名空间 kube-system 下的 deployment 和 pod 资源。

拥有全局权限的SA

创建

ServiceAccount 对象 (luo-sa2.yaml)

apiVersion: v1
kind: ServiceAccount
metadata:
  name: luo-sa2
  namespace: kube-system

ClusterRoleBinding 对象(luo-clusterolebinding.yaml)

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: luo-sa2-clusterrolebinding
subjects:
- kind: ServiceAccount
  name: luo-sa2
  namespace: kube-system
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

此 ClusterRoleBinding 资源对象是作用于整个集群,故未指定 ns,也没有单独新建一个 ClusterRole 对象,而是使用的 cluster-admin 对象,这是 Kubernetes 集群内置的 ClusterRole 对象,此集群角色是拥有最高权限的集群角色。

应用

$ kubectl create -f luo-sa2.yaml
$ kubectl create -f luo-clusterolebinding.yaml

$ kubectl get secret -n kube-system |grep luo-sa2
luo-sa2-token-nxgqx     kubernetes.io/service-account-token   3         47m

# 会生成一串很长的base64后的字符串
$ kubectl get secret luo-sa2-token-nxgqx -o jsonpath={.data.token} -n kube-system |base64 -d

验证

将生成的字符串用来登陆 Dashboard ,进入页面可查看到所有资源。