RBAC 之所以一直没有写这个,一方面是因为它确实并不复杂,二来平常确实接触不多,今天就来顺路讲讲它
Role-Based Access Control 我们常说的 RBAC,我们知道在一个后台管理系统里面经常会有权限管理。而最常用的一种权限设计方式就是基于角色的权限设计,A 用户是管理员拥有所有的权限,B 是普通用户角色只有部分权限等等,而 k8s 也是如此,k8s 内部也有许许多多的资源,通过 RBAC 的权限设计进行管理授权工作。
其实非常好理解: 用户 -> 角色 -> 权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" 标明 core API 组
resources: ["pods"]
verbs: ["get", "watch", "list"]
这就是 k8s 里面的角色,这里定义了一个角色 pod-reader 这个角色可以对 default 命名空间中的 pod 资源进行 get watch list 操作
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# "namespace" 被忽略,因为 ClusterRoles 不受名字空间限制
name: secret-reader
rules:
- apiGroups: [""]
# 在 HTTP 层面,用来访问 Secret 对象的资源的名称为 "secrets"
resources: ["secrets"]
verbs: ["get", "watch", "list"]
ClusterRole 属于集群范围,所以整个集群对应的资源都可以被使用
apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定允许 "jane" 读取 "default" 名字空间中的 Pods
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
# 你可以指定不止一个“subject(主体)”
- kind: User
name: jane # "name" 是区分大小写的
apiGroup: rbac.authorization.k8s.io
roleRef:
# "roleRef" 指定与某 Role 或 ClusterRole 的绑定关系
kind: Role # 此字段必须是 Role 或 ClusterRole
name: pod-reader # 此字段必须与你要绑定的 Role 或 ClusterRole 的名称匹配
apiGroup: rbac.authorization.k8s.io
有了角色自然就是将用户绑定到对应的角色上去了,这个没有什么好说的,很容易理解
apiVersion: rbac.authorization.k8s.io/v1
# 此集群角色绑定允许 “manager” 组中的任何人访问任何名字空间中的 secrets
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager # 'name' 是区分大小写的
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
同样的 ClusterRoleBinding 也是类似
其实 User 不多,其实我们更多的使用 k8s 里的内置用户也就是 ServiceAccount,这个 ServiceAccount 会生成一个 secrets 利用这个可以跟 APIServer 进行交互
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: mynamespace
name: example-sa
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
apiVersion: v1
kind: Pod
metadata:
namespace: mynamespace
name: sa-token-test
spec:
containers:
- name: nginx
image: nginx:1.7.9
serviceAccountName: example-sa
通过 serviceAccountName 指定对应的 ServiceAccount 就可以使用了
如果只是上面那样有点空,也有点虚,不如直接开官网文档来的快。下面就直接使用实际的案例来看看 rbac 到底是怎么样作用的。
我们的目标是创建一个用户,然后绑定对应的权限,有了对应的权限之后,创建的对应的 deployment 使用对应的用户,然后获取到对应的资源,我们使用 client-go 直接获取对应的资源信息看看。
这里我们使用 ClusterRole,并且直接绑定已有的角色 cluster-admin, 然后创建需要使用的 ServiceAccount
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: admin
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: admin
namespace: my-namespace
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin
namespace: my-namespace
labels:
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
package main
import (
"context"
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
//
// Uncomment to load all auth plugins
// _ "k8s.io/client-go/plugin/pkg/client/auth"
//
// Or uncomment to load specific auth plugins
// _ "k8s.io/client-go/plugin/pkg/client/auth/azure"
// _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
// _ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
// _ "k8s.io/client-go/plugin/pkg/client/auth/openstack"
)
func main() {
config, err := rest.InClusterConfig()
if err != nil {
panic(err.Error())
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
fmt.Printf("all namespaces: ")
nsList, err := clientset.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
if err != nil {
panic(err.Error())
}
for _, item := range nsList.Items {
fmt.Printf("%s ", item.Name)
}
fmt.Println()
fmt.Printf("all deployments in default namespace: ")
deployments, err := clientset.AppsV1().Deployments("default").List(context.TODO(), metav1.ListOptions{})
if err != nil {
panic(err.Error())
}
for _, item := range deployments.Items {
fmt.Printf("%s ", item.Name)
}
select {}
}
因为我们的应用运行在 k8s 内部,所以使用 client-go 非常容易,使用 rest.InClusterConfig() 就可以获取到对应配置
只要当前 deployment 有对应的权限,就可以获取到对应的资源 pod 或者 namespace 等
apiVersion: apps/v1
kind: Deployment
metadata:
name: rabc-test
namespace: my-namespace
labels:
app: rabc-test
spec:
replicas: 1
selector:
matchLabels:
app: rabc-test
template:
metadata:
labels:
app: rabc-test
spec:
containers:
- name: rabc-test
image: linkinstars.com/rabc-test:latest
serviceAccountName: admin
创建 deployment 使用 serviceAccountName 指定刚才创建的 ServiceAccount admin 这里需要注意缩进,它是 template 下的 spec 的一个属性
运行后查看日志则可以获取到对应的所有的 namespace 列表和 default 下的所有 deployment
参考文档:https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有