「Kubernetes」- 使用 RBAC 授权

  CREATED BY JENKINSBOT

问题描述

该笔记将记录:在 Kubernetes Cluster 中,如何使用 RBAC 及 ServiceAccount 进行权限管理,以及常见问题处理。

解决方案

场景一、限制 kubectl 命令

当集群部署完成之后,使用 kubectl 命令能够控制整个集群,这是因为 ~/.kube/config 的凭证权限足够高。我们不能直接分发该凭证,应该创建新的碰正限制访问权限。

第一步、检查 RBAC 是否启用

# kubectl api-versions | grep -E '^rbac\.'
rbac.authorization.k8s.io/v1
rbac.authorization.k8s.io/v1beta1

启用 RBAC 授权:在启动 kube-apiserver 服务时,指定 –authorization-mode=Example,RBAC 选项

第二步、创建 ServiceAccount 对象

cat > udef-ServiceAccount-PodReader.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: pod-reader
EOF

kubectl apply -f udef-ServiceAccount-PodReader.yaml

ServiceAccount 相当于传统授权体系的账户。

第三步、创建 Role 对象

该 Role 仅具有读取 Pod 的权限:

cat > udef-Role-PodReader.yaml <<EOF
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: pod-reader
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
EOF

kubectl apply -f udef-Role-PodReader.yaml

Role 相当于传统授权体系中的角色

第四步、创建 RoleBinding 对象

cat > udef-RoleBinding-PodReader.yaml <<EOF
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
   name: pod-reader
subjects:
 - kind: ServiceAccount
   name: pod-reader
roleRef:
   kind: Role
   name: pod-reader
   apiGroup: rbac.authorization.k8s.io
EOF

kubectl apply -f udef-RoleBinding-PodReader.yaml

RoleBinding 相当于传统授权体系中的授权动作,将用户与角色绑定。

第五步、访问集群

获取访问集群 TOKEN 字符串:

SECRET_NAME=$(kubectl get -n default serviceaccount pod-reader -o jsonpath="{.secrets[0].name}")
TOKEN=$(kubectl get secrets $SECRET_NAME -o jsonpath="{.data.token}" | base64 -d)

我们需要在 .kube/config 中配置该 TOKEN(参考 Configure Access to Multiple Clusters 笔记),以使用 kubectl 管理集群。

查看命令空间 Pod 信息:

# kubectl get pods -n default
No resources found in default namespace.

如果查看其他命令空间的 Pod 将返回错误信息:

# kubectl get pods -n kube-system
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:pod-reader" cannot list resource "pods" in API group "" in the namespace "kube-system"

补充说明

1)其实,这里 TOKEN 也是访问 Kubernetes Dashboard 要输入的 TOKEN 参数

2)kubectl get 与 kubectl describe 输出的 token 并不相同,前者需要 base64 解码,否则提示:error: You must be logged in to the server (Unauthorized)

3)我们这里紧演示如何通过 RBAC 限制 kubectl 对集群的操作。实际上,Pod 启动时,会将 namespace 的 default ServiceAccount 挂载到 Pod 中,能够用来访问集群,参考 Use the Default Service Account to access the API server.Accessing the API from a Pod 文档。

4)限制仅能访问特定 Namespace 资源:我们的示例便是如此,只是赋予的 apiGroups 及 resources 是有限的。如果希望访问 Namesapce 的所有资源,使用:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: mynamespace-user-full-access
  namespace: mynamespace
rules:
- apiGroups: ["", "extensions", "apps"]
  resources: ["*"]
  verbs: ["*"]
- apiGroups: ["batch"]
  resources:
  - jobs
  - cronjobs
  verbs: ["*"]

Role and ClusterRole

Role – namespaced resource

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

官方文档给出一些 Role 示例:https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-examples

ClusterRole – non-namespaced resource

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: secret-reader
rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Secret
  # objects is "secrets"
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

Aggregated ClusterRoles

将多个 ClusterRole 聚合到同个中,通过 selector 与 label 进行匹配。

带有 aggregationRule 的资源:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # The control plane automatically fills in the rules

当定义如下 ClusterRole 资源时,由于设置“对应的标签”,该 ClusterRole 会被自动合并到上面的 ClusterRole 资源中:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring-endpoints
  labels:
    rbac.example.com/aggregate-to-monitoring: "true"
# When you create the "monitoring-endpoints" ClusterRole,
# the rules below will be added to the "monitoring" ClusterRole.
rules:
- apiGroups: [""]
  resources: ["services", "endpoints", "pods"]
  verbs: ["get", "list", "watch"]

官方文档还给了另外两个示例,将 CRD 资源的权限赋予 default user-facing roles,这也是通过 Aggregated ClusterRoles 实现的:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: aggregate-cron-tabs-edit
  labels:
    # Add these permissions to the "admin" and "edit" default roles.
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
rules:
- apiGroups: ["stable.example.com"]
  resources: ["crontabs"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: aggregate-cron-tabs-view
  labels:
    # Add these permissions to the "view" default role.
    rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: ["stable.example.com"]
  resources: ["crontabs"]
  verbs: ["get", "list", "watch"]

附加说明

限制访问子资源:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]

通过资源名进行限制:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: configmap-updater
rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing ConfigMap
  # objects is "configmaps"
  resources: ["configmaps"]
  resourceNames: ["my-configmap"]
  verbs: ["update", "get"]

RoleBinding and ClusterRoleBinding

RoleBinding

= a Role + Subjects (Users, Groups, Service Accounts)

apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "jane" to read pods in the "default" namespace.
# You need to already have a Role named "pod-reader" in that namespace.
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default

subjects:
# You can specify more than one "subject"
- kind: User
  name: jane # "name" is case sensitive
  apiGroup: rbac.authorization.k8s.io

roleRef:
  # "roleRef" specifies the binding to a Role / ClusterRole
  kind: Role #this must be Role or ClusterRole
  name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
  apiGroup: rbac.authorization.k8s.io

= a ClusterRole + Subjects (Users, Groups, Service Accounts)

apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "dave" to read secrets in the "development" namespace.
# You need to already have a ClusterRole named "secret-reader".
kind: RoleBinding
metadata:
  name: read-secrets
  #
  # The namespace of the RoleBinding determines where the permissions are granted.
  # This only grants permissions within the "development" namespace.
  namespace: development
subjects:
- kind: User
  name: dave # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

“dave” will only be able to read Secrets in the “development” namespace, because the RoleBinding’s namespace is “development”.

ClusterRoleBinding

apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

附加说明

创建 Binding 后,不可以修改它所引用的 Role/ClusterRole,如果尝试修改 Binding 的 roleRel 将产生错误。原因有二:
1)“可以为别人授权的用户”,可以在不修改 subjects,但是不影响 roleRef 参数;
2)防止错误调整为其他人意外赋予权限;

可以使用 kubectl auth reconcile 进行修改。

参考文献

Using RBAC Authorization
Using RBAC with Service Accounts in Kubernetes – DZone Cloud
Kubernetes and RBAC: Restrict user access to one namespace · Jeremie Vallee

章节列表

「Kubernetes」- 创建 TOKEN 凭证、管理集群、用户授权