问题描述
该笔记将记录:在 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 相当于传统授权体系中的授权动作,将用户与角色绑定。
第五步、访问集群
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) # 创建 pod-reader 用户 kubectl config set-credentials "pod-reader" --token=$TOKEN # 创建 Context 来绑定“用户”与“集群” # 用户:我们刚才创建的 # 集群:需要查看 ~/.kube/config 文件的 clusters 属性中的 name 字段 kubectl config set-context "pod-reader" --cluster="kubernetes" --user="pod-reader" # 切换到 Context kubectl config use-context "pod-reader"
查看命令空间 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 进行修改。
相关文章
「Kubernetes」- 容器资源管理
「Kubernetes Objects」- CronJob(学习笔记)
「Kubernetes」- 使用存储(学习笔记)
「Kubernetes Objects」- PodSecurityPolicy
「Kubernetes Objects」- Deployment
参考文献
Using RBAC Authorization
Using RBAC with Service Accounts in Kubernetes - DZone Cloud
Kubernetes and RBAC: Restrict user access to one namespace · Jeremie Vallee