【kubernetes系列】Kubernetes之RBAC

news2025/4/26 23:32:31

概述

k8s的权限控制在实际工作中不那么经常使用,但是却是很重要的,我们需要深入理解才能很好的解决某些问题。在我们现目前的了解中,常用的授权插件有以下几种:
Node(节点认证)
ABAC(基于属性的访问控制)
RBAC(基于角色的访问控制)
Webhook(基于http回调机制的访问控制)

kubernetes 集群相关所有的交互都需要通过apiserver来完成,对于这样集中式管理的系统来说,权限管理尤其重要,Kubernetes的授权是基于插件形式的,在1.5版的时候引入了基于角色的访问控制(Role-Based Access Control, 即”RBAC”)来实现授权决策,允许管理员通过Kubernetes API动态配置策略。
RBAC的理解大概如下:让一个用户(Users)扮演一个角色(Role),角色拥有权限,从而让用户拥有这样的权限,随后在授权机制当中,只需要将权限授予某个角色,此时用户即可获取对应角色的权限,从而实现角色的访问控制。如图:
在这里插入图片描述

实际使用中,要启用RBAC,需要在 apiserver 中添加参数–authorization-mode=RBAC,如果使用的kubeadm安装的集群,1.6+版本都默认开启了RBAC。RBAC引入了4个新的顶级资源对象 :Role、ClusterRole、RoleBinding和 ClusterRoleBinding。 同其他 API 资源对象 一样,用户可以通过kubectl 或者 API 调用等方式操作这些资源对象。

在k8s的授权机制当中,采用RBAC的方式进行授权,其工作流程是把对对象的操作权限定义到一个角色当中,再将用户绑定到该角色,从而使用户得到对应角色的权限。此种方式仅作用于当前空间,这是什么意思呢?当User1绑定到Role角色当中,User1就获取了对该NamespaceA的操作权限,但是对NamespaceB是没有权限进行操作的,如get,list,watch等操作。

此外,k8s为此还有一种集群级别的授权机制,就是定义一个集群角色(ClusterRole),对集群内的所有资源都有可操作的权限,从而将User2,User3通过ClusterRoleBinding到ClusterRole,从而使User2、User3拥有集群的操作权限,如下。
在这里插入图片描述
这里有2种绑定ClusterRoleBinding、RoleBinding。但是也可以使用RoleBinding去绑定ClusterRole。

当使用这种方式进行绑定时,用户仅能获取当前名称空间的所有权限。为什么这么绕呢??举例有10个名称空间,每个名称空间都需要一个管理员,而该管理员的权限都是一致的。那么此时需要去定义这样的管理员,使用RoleBinding就需要创建10个Role,这样显得更加繁重。为此当使用RoleBinding去绑定一个ClusterRole时,该User仅仅拥有对当前名称空间的集群操作权限,换句话说,此时只需要创建一个ClusterRole就解决了以上的需求。(注意:RoleBinding仅仅对当前名称空间有对应的权限)

在RBAC API中,一个角色就是一组权限的集合, 权限以纯粹的累加形式累积(没有”否定”的规则)。 角色由命名空间(namespace)内的Role对象定义,而整个Kubernetes集群范围内有效的角色则通过ClusterRole对象实现。

示例

下面我们分别说明每个资源对象

角色(Role)

一个角色就是一组权限的集合,这里的权限都是许可形式的,不存在拒绝的规则。在一个命名空间中,可以用角色来定义一个角色,如果是集群级别的,就需要使用ClusterRole了。角色只能对当前命名空间内的资源进行授权,以下示例描述了”default”命名空间中定义的一个Role对象,用于授予对pod的读访问权限:

[root@k8s-m1 tmp]# cat default-role.yml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" 空字符串,表示核心 API 群
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

[root@k8s-m1 tmp]# kubectl apply -f default-role.yml 
role.rbac.authorization.k8s.io/pod-reader created

role中的参数说明如下

  • apiGroups:支持的 API 组列表,关于当前版本支持RBAC的apiGroups有哪些可以通过kubectl api-versions |grep -i rbac查看
  • resource:支持的资源对象列表,例如 pods、deployments、jobs 等。
  • verbs:对资源对象的操作方法列表,例如 get, list, watch, create, update, patch, delete,deletecollection 。

集群角色(Cluster Role)

集群角色除了具有和角色一致的名称空间内资源的管理能力,因其集群级别的范围,还可以用于以下特殊元素的授权。

  • 集群范围的资源(例如 Node(节点))
  • 非资源型的路径(例如 /healthz)
  • 包含全部名称空间的资源,例如 pods(用于 kubectl get pods -A 这样的操作授权)。
    下面的集群角色可以让用户有权访问任意一个或所有命名空间的 configmaps(取决于其绑定方式):
[root@k8s-m1 tmp]# cat default-clusterrole.yml 
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: configmaps-reader
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "watch", "list"]
 #鉴于ClusterRole是作用于整个集群范围对象,所以这里不需要定义"namespace"字段

[root@k8s-m1 tmp]# kubectl apply  -f default-clusterrole.yml 
clusterrole.rbac.authorization.k8s.io/configmaps-reader created

RoleBinding与ClusterRoleBinding

角色绑定(Role Binding)和集群角色绑定用于将一个角色中定义的各种权限绑定到一个目标上。 该目标可以是User(用户)、Group(组)或者Service Account。 在命名空间中可以通过RoleBinding对象授予权限,而集群范围的权限授予则通过ClusterRoleBinding对象完成。

RoleBinding可以引用在同一命名空间内定义的Role对象。 下面示例中定义的RoleBinding对象在”default”命名空间中将”pod-reader”角色授予用户”margu”。 这一授权将允许用户”margu”从”default”命名空间中读取pod。

以下角色绑定定义将允许用户"margu"从"default"命名空间中读取pod。(rolebinding+role)

[root@k8s-m1 tmp]# cat  default-rolebinding.yml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User               # 赋予用户margu pod-reader角色权限
  name: margu
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role               # 此字段必须是 Role 或 ClusterRole
  name: pod-reader         # 此字段必须与你要绑定的 Role 或 ClusterRole 的名称匹配,也就是说此 Role 或 ClusterRole必须存在
  apiGroup: rbac.authorization.k8s.io

[root@k8s-m1 tmp]# kubectl apply -f  default-rolebinding.yml
rolebinding.rbac.authorization.k8s.io/read-pods created

RoleBinding也可以引用ClusterRole进行授权。
RoleBinding对象也可以引用一个ClusterRole对象,用于在RoleBinding所在的命名空间内授予用户对所引用的ClusterRole中 定义的资源的访问权限。这一点允许管理员在整个集群范围内首先定义一组通用的角色,然后再在不同的命名空间中复用这些角色。(这样做的目的是创建一个通用权限的ClusterRole,如果需要创建10个名称空间管理员的时候只需要用RoleBinding和ClusterRole绑定即可,不用创建十个role和十个RoleBinding,只需要一个ClusterRole和十个RoleBinding就搞定了)

例如,尽管下面示例中的RoleBinding引用的是一个ClusterRole对象,但是用户”dave”(即角色绑定主体)还是只能读取”当前命名空间中的secret(即RoleBinding所在的命名空间)。

以下角色绑定允许用户"margu"读取"com-prod"命名空间中的configmap。(rolebinding+clusterrole)

[root@k8s-m1 tmp]# cat  default-rolebinding-clusterrole.yml 
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-configmaps
  namespace: com-prod   # 集群角色中,只有在development命名空间中的权限才能赋予dave
subjects:
- kind: User
  name: margu
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: configmaps-reader # 引用上面定义的clusterRole 名称(clusterRole没有指定命名空间,默认可以应用所有,但是在rolebinding时,指定了命名空间,所以只能读取本命名空间的文件)
  apiGroup: rbac.authorization.k8s.io

[root@k8s-m1 tmp]# kubectl apply -f  default-rolebinding-clusterrole.yml 
rolebinding.rbac.authorization.k8s.io/read-configmaps created

以下ClusterRoleBinding对象允许在用户组"manager"中的任何用户都可以读取集群中任何命名空间中的secret。(clusterrolebinding+clusterrole)

可以使用ClusterRoleBinding在集群级别的所有名称空间中授予权限。下面示例中所定义的ClusterRoleBinding 允许在用户组”manager”中的任何用户都可以读取集群中任何名称空间中的configmap。

[root@k8s-m1 tmp]# cat  default-clusterrole-clusterrolebinding.yml 
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-configmaps-global
subjects:
- kind: Group
  name: manager
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: configmaps-reader
  apiGroup: rbac.authorization.k8s.io

[root@k8s-m1 tmp]# kubectl apply -f  default-clusterrole-clusterrolebinding.yml 
clusterrolebinding.rbac.authorization.k8s.io/read-configmaps-global created

下图展示了上述对Pod的get/watch/list操作进行授权的Role和RoleBinding逻辑关系。
在这里插入图片描述

对资源的引用

大多数资源由代表其名字的字符串表示,例如”pods”,就像它们出现在相关API endpoint的URL中一样。然而,有一些Kubernetes API还包含了下级子资源”,比如pod的日志logs。在Kubernetes中,pod logs endpoint的URL格式为:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
在这种情况下,”pods”是命名空间资源,而”log”是pods的子资源。为了在RBAC角色中表示出这一点,我们需要使用斜线来划分资源 与子资源。如果需要主体绑定角色去读取pods以及pod log,需要配置resources为一个数组:

[root@k8s-m1 tmp]# cat  log-reader-role.yml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]   # 根据上面意思表示授予读取pods和pods下log的权限
  verbs: ["get", "list"]

[root@k8s-m1 tmp]# kubectl apply -f  log-reader-role.yml
role.rbac.authorization.k8s.io/pod-and-pod-logs-reader created

以上都是对某类资源的整体控制,对某些资源还可以进行更细的控制。如可以通过名字(ResourceName)进行引用(这里指的是资源实例的名子)。在指定ResourceName后,使用get、delete、update和patch动词的请求,就会被限制在这个资源实例的范围内。

[root@k8s-m1 tmp]# cat oneresource-role.yml 
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: configmap-updater
rules:
- apiGroups: [""]
  resources: ["configmap"]
  resourceNames: ["appvars-cm "]
  verbs: ["update", "get"]
#只对default命名空间下的appvars-cm这个configmap有update和get的权限

常用的角色(Role)示例

以下示例均为从 Role 或 ClusterRole 对象中截取出来,这里只展示其 rules 部分
1)允许读取core API Group中定义的资源”pods”:

rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

2)允许读写在”extensions”和”apps” API Group中定义的”deployments”:

rules:
- apiGroups: ["extensions", "apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

3)允许读取”pods”以及读写“extensions”和“batch” API Group中jobs”:

rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["batch", "extensions"]
  resources: ["jobs"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

4)允许读取一个名为”app-config”的ConfigMap实例(需要将其通过RoleBinding绑定从而限制针对某一个命名空间中定义的一个ConfigMap实例的访问):

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

5)允许读取core API Group中的”nodes”资源(由于Node是集群级别资源,所以此ClusterRole定义需要与一个ClusterRoleBinding绑定才能有效):

rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]

6)允许针对非资源端点 “/healthz” 及其所有子路径的”GET”和”POST”请求(此ClusterRole定义需要与一个ClusterRoleBinding绑定才能有效):

rules:
- nonResourceURLs: ["/healthz", "/healthz/*"]   # 在非资源URL中,'*'代表后缀通配符
  verbs: ["get", "post"]

角色绑定主体(Subject)

RoleBinding或者ClusterRoleBinding将角色绑定到角色绑定主体(Subject)。 从上面知道可以绑定的主体(kind指定)可以是用户组(Group)、用户(User)或者服务账户(Service Accounts)。

用户由字符串表示。可以是纯粹的用户名,例如”margu”、电子邮件风格的名字,如 “margu@example.com” 或者是用字符串表示的数字id。由Kubernetes管理员配置认证模块以产生所需格式的用户名。对于用户名,RBAC授权系统不要求任何特定的格式。然而,前缀system:是 为Kubernetes系统使用而保留的,所以管理员应该确保用户名不包含这个前缀。

Kubernetes中的用户组信息由授权模块提供。用户组与用户一样由字符串表示。Kubernetes对用户组字符串没有格式要求,但前缀system:同样是被系统保留的。

服务账户(serviceAccount)拥有包含 system:serviceaccount:前缀的用户名,并属于拥有system:serviceaccounts:前缀的用户组。
说明:

  • system:serviceaccount: (单数)是用于服务账户用户名的前缀;
  • system:serviceaccounts: (复数)是用于服务账户组名的前缀。
    角色绑定例子
    以下示例中,下面的例子中只包含subjects部分的内容。

1)一个名为”margu@example.com”的用户:

subjects:
- kind: User
  name: "margu@example.com"
  apiGroup: rbac.authorization.k8s.io

2)一个名为”frontend-admins”的用户组:

subjects:
- kind: Group
  name: "frontend-admins"
  apiGroup: rbac.authorization.k8s.io

3)kube-system命名空间中的默认服务账户:
subjects:

  • kind: ServiceAccount
    name: default
    namespace: kube-system
    4)对于任何名称空间中的 “qa” 组中所有的服务账户:
subjects:
- kind: Group
  name: system:serviceaccounts:qa
  apiGroup: rbac.authorization.k8s.io

5)对于 “com-prod” 名称空间中 “dev” 组中的所有服务帐户:

subjects:
- kind: Group
  name: system:serviceaccounts:dev
  apiGroup: rbac.authorization.k8s.io
  namespace: com-prod

6)在集群中的所有服务账户:

subjects:
- kind: Group
  name: system:serviceaccounts
  apiGroup: rbac.authorization.k8s.io

7)所有认证过的用户:

subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io 

8)所有未认证的用户:

subjects:
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io

9)所有用户:

subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io

注意:在创建Rolebinding 或是Clusterrolebinding时如果是ServiceAccount则需指定Namespace字段,如未指定会报如下错误:
error: serviceaccount must be :

[root@k8s-m1 tmp]# kubectl create rolebinding test  --role=pods-reader   --serviceaccount=kube-sysem:admin --dry-run -o yaml
W0707 11:25:06.364669   10869 helpers.go:553] --dry-run is deprecated and can be replaced with --dry-run=client.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: null
  name: test
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pods-reader
subjects:
- kind: ServiceAccount
  name: admin
  namespace: kube-sysem
#这里的admin必须是真实存在于kubectl get sa -n kube-system中的serviceaccount

默认的角色和角色绑定

API Server 创建了一系列的默认 ClusterRole 和 ClusterRoleBinding 对象, 其中许多对象以 “system:” 前缀开头,代表其中绑定的资源是作为基础设施适用和占有的。修改这些资源会导致整个集群不可用。一个例子是 system:node 。这个ClusterRole角色拥有一系列的kubelet权限,如果这个集群角色被修改了,可能会让kubelet出现异常。

所有默认的集群角色 (ClusterRole) 和其角色绑定(role binding)都带有如下标记

Labels:       kubernetes.io/bootstrapping=rbac-defaults

自动协商
每次启动时,API Server都会更新默认ClusterRole所缺乏的各种权限,并更新默认ClusterRoleBinding所缺乏的各个角色绑定主体。 这种自动更新机制允许集群修复一些意外的修改。由于权限和角色绑定主体在新的Kubernetes释出版本中可能变化,这也能够保证角色和角色 绑定始终保持是最新的。

如果需要禁用自动更新,请将默认ClusterRole以及ClusterRoleBinding的rbac.authorization.kubernetes.io/autoupdate 设置成为false。 请注意,缺乏默认权限和角色绑定主体可能会导致非功能性集群问题。而当集群RBAC鉴权机制(RBAC Authorizer)处于开启状态时,则自动协商功能默认是被启用的。

下面对一些常见的默认ClusterRole和ClusterRoleBinding对象进行说明。

对系统角色的说明如下表所示:

默认的ClusterRole默认的ClusterRoleBinding描述
system:basic-usersystem:authenticated和system:unauthenticated组让用户能够读取自身的信息
system:discoverysystem:authenticated和system:unauthenticated组对API发现Endpoint的只读访问,用于API级别的发现和协商

对用户角色的说明如下表所示:

默认的ClusterRole默认的ClusterRoleBinding描述
cluster-adminsystem:masters组让超级用户可以对任何资源执行任何操作。如果在ClusterRoleBinding中使用,则影响的是整个集群的所有namespace中的任何资源;如果使用的是RoleBinding,则能控制这一绑定的namespace中的资源,还包括namespace本身。
adminNone允许admin访问,可以限制在一个namespace中使用RoleBinding。如果在RoleBinding中使用,则允许对namespace中大多数资源进行读写访问,其中包含创建角色和角色绑定的能力。这一角色不允许操作namespace本身,也不能写入资源限额。
editNone允许对命名空间内的大多数资源进行读写操作,不允许查看或修改角色,以及角色绑定。
viewNone允许对多数对象进行只读操作,但是对角色、角色绑定及secret是不可访问的。

注:有些默认角色不是以"system:"为前缀的,这部分角色是针对用户的。其中包含超级用户角色(cluster-admin),还有针对namespace的角色(admin,edit,view)。

对核心Master组件角色的说明如下表所示:

默认的ClusterRole默认的ClusterRoleBinding描述
system:kube-schedulersystem:kube-scheduler用户能够访问kube-scheduler组件所需的资源
system:kube-controller-managersystem:kube-controller-manager用户能够访问kube-controller-manager组件所需的资源,不同的控制所需的不同权限参见下表。
system:nodesystem:nodes组允许访问kubelet所需的资源,包括对secret的读取,以及对Pod的写入。未来会把上面的两个权限限制在分配到本Node的对象上。今后的鉴权过程,kubelet必须以system:node及一个system:node形式的用户名进行。
system:node-proxiersystem:kube-proxy用户允许访问kube-proxy所需的资源
system:kube-schedulersystem:kube-scheduler用户能够访问kube-scheduler组件所需的资源

对其他组件角色的说明如下表所示:

默认的ClusterRole默认的ClusterRoleBinding描述
system:auth-delegatorNone允许对授权和认证进行托管,通常用于附加的API服务器
system:heapsterNoneHeapster组件的角色
system:kube-aggregatorNonekube-aggregator的角色
system:kube-dns在kube-system namespace中kube-dns的Service Accountkube-dns角色
system:node-bootstrapperNone允许访问kubelet TLS启动所需的资源
system:node-problem-detectorNone允许访问node-problem-detector组件所需的资源
system:persistent-volume-provisionerNone允许访问多数动态卷供给所需的资源

对Controller角色的说明如下表所示:

Controller角操作对象
system:controller:attachdetach-controllerattachdetach
system:controller:certificate-controller证书控制器
system:controller:cronjob-controllercronjob控制器
system:controller:daemon-set-controllerdaemonset控制器
system:controller:deployment-controllerdeployment控制器
system:controller:disruption-controller中断
system:controller:endpoint-controllerendpoint
system:controller:generic-garbage-collector普通垃圾
system:controller:horizontal-pod-autoscaler水平伸缩
system:controller:job-controllerjob
system:controller:namespace-controller命名空间
system:controller:node-controllernode
system:controller:persistent-volume-binder永久存储卷
system:controller:pod-garbage-collector有关pod的垃圾
system:controller:replicaset-controllerRS
system:controller:replication-controllerRC
system:controller:route-controllerroute
system:controller:service-account-controllerservice account
system:controller:service-controllerservice
system:controller:statefulset-controllerstatefulset
system:controller:ttl-controllerttl

#上述的某些资源不清楚可以自行查看相关源码说明

K8s Controller Manager负责的是核心控制流。如果启用–user-service-account-credentials(kubeadm部署默认是启用了的,可以查看文件/etc/kubernetes/manifests/kube-controller-manager.yaml),则每个控制过程都会使用不同的Service Account启动。因此就有了对应各个控制过程的角色,前缀是system:controller。如果未启用这一功能,则将使用各自的凭据运行各个控制流程,这就需要为该凭据授予所有相关角色。

示例:创建User Account访问Kubernetes集群

role+rolebinding

创建一个只能读取default命名空间下的角色margu,可用于防止某些人员的误操作和减小权限,此方法可以用于除运维人员外的其他人员需要查看集群的某些信息。
此步骤在/etc/kubernetes/pki路径下执行,因为需要用到Kubernetes CA证书

生成证书

[root@k8s-m1 ~]# cd /etc/kubernetes/pki/

[root@k8s-m1 pki]# openssl genrsa -out margu.key 2048
Generating RSA private key, 2048 bit long modulus
..................+++
...+++
e is 65537 (0x10001)
[root@k8s-m1 pki]# openssl req -new -key margu.key -subj "/CN=margu" -out margu.csr
[root@k8s-m1 pki]# openssl x509 -req -in margu.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out margu.crt -days 3650
Signature ok
subject=/CN=margu
Getting CA Private Key

#验证证书信息
[root@k8s-m1 pki]# openssl x509 -in margu.crt -text -noout

授权流程( Role –>Rolebinding)

##role定义
[root@k8s-m1 pki]# cat test-role.yml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" 空字符串,表示核心 API 群
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

[root@k8s-m1 tmp]# kubectl apply -f test-role.yml 
role.rbac.authorization.k8s.io/pod-reader created

##rolebinding定义
[root@k8s-m1 tmp]# cat  test-rolebinding.yml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User               # 赋予用户margu pod-reader角色权限
  name: margu
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role               # 此字段必须是 Role 或 ClusterRole
  name: pod-reader         # 此字段必须与你要绑定的 Role 或 ClusterRole 的名称匹配,也就是说此 Role 或 ClusterRole必须存在
  apiGroup: rbac.authorization.k8s.io

[root@k8s-m1 pki]# kubectl apply -f  test-rolebinding.yml
rolebinding.rbac.authorization.k8s.io/read-pods created

###上面的yaml文件可以通过下面的方法先初步生成yaml文件再进行修改
#[root@k8s-m1 pki]# kubectl create role pod-reader --verb=get,list,watch --resource=pods --dry-run=client -o yaml > test-role.yaml
#[root@k8s-m1 pki]# kubectl create rolebinding read-pods --role=pod-reader --user=margu --dry-run=client -o yaml > test-rolebinding.yaml

[root@k8s-m1 pki]# kubectl get role
NAME                      CREATED AT
pod-reader                2023-07-07T00:45:42Z
[root@k8s-m1 pki]# kubectl describe  role pod-reader 
Name:         pod-reader
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  pods       []                 []              [get watch list]  #此处已经定义了pods-reader这个角色对pods资源拥有get、list、watch的权限

[root@k8s-m1 pki]# kubectl describe  rolebindings.rbac.authorization.k8s.io read-pods 
Name:         read-pods
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  Role
  Name:  pod-reader
Subjects:
  Kind  Name   Namespace
  ----  ----   ---------
  User  margu  

添加用户认证进行测试使用

[root@k8s-m1 pki]#  kubectl config set-credentials margu --client-certificate=./margu.crt --client-key=./margu.key --embed-certs=true
User "margu" set.

[root@k8s-m1 pki]# kubectl config set-context margu@kubernetes --cluster=kubernetes --user=margu
Context "margu@kubernetes" created.

[root@k8s-m1 pki]# kubectl config view 
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.2.250:8443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
- context:
    cluster: kubernetes
    user: margu
  name: margu@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: margu
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

[root@k8s-m1 pki]#  kubectl config use-context margu@kubernetes         #切换margu这个用户,并使用get获取pods资源信息
Switched to context "margu@kubernetes". 
[root@k8s-m1 pki]# kubectl get pod
NAME                        READY   STATUS      RESTARTS   AGE
cm-env-pod-all              0/1     Completed   0          23h
configmap-subpath           1/1     Running     217        9d
configmap-volume-pod        1/1     Running     24         24h
init-demo                   1/1     Running     0          4d
init-pod1                   1/1     Running     96         4d
liveness-exec-pod-1         1/1     Running     66         2d18h


[root@k8s-m1 pki]# kubectl get cm
Error from server (Forbidden): configmaps is forbidden: User "margu" cannot list resource "configmaps" in API group "" in the namespace "default"
[root@k8s-m1 pki]# kubectl get pod -n kube-system
Error from server (Forbidden): pods is forbidden: User "margu" cannot list resource "pods" in API group "" in the namespace "kube-system"
#可以看到查看当前命名空间的其他资源如configmap,或者其他命名空间的资源都是禁止的。

由于margu账户不具备创建的权限,这也说明普通用户是无法进行创建K8S资源的,除非进行更多授权。如下,我们另开一个终端,将配置到一个普通用户test上,使其使用margu账户进行通信。注意linux的登录账户和k8s的管理账户名可以不一样。

以下步骤在root权限下执行

[root@k8s-m1 ~]# useradd test
[root@k8s-m1 ~]# cp -rp .kube/ /home/test/
[root@k8s-m1 ~]# chown -R test.test /home/test/
[root@k8s-m1 ~]# su - test
#以下步骤在普通用户test下执行,是因为test用户已经切换到margu这个管理账号。
[test@k8s-m1 ~]$ kubectl  config  view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.2.250:8443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
- context:
    cluster: kubernetes
    user: margu
  name: margu@kubernetes
current-context: margu@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: margu
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
[test@k8s-m1 ~]$ kubectl create ns test
Error from server (Forbidden): namespaces is forbidden: User "margu" cannot create resource "namespaces" in API group "" at the cluster scope
#发现登录test账号使用k8s中的margu用户管理k8s时,不能创建namespace。其次,我们可以将以上配置文件中关于kubernetes-admin的相关部分删除,这样即使其他人可以切换到kubernetes-admin账号,但是相关操作也是需要账号密码的。

##也可以直接用root切换测试
[root@k8s-m1 ~]$ kubectl config use-context margu@kubernetes
Switched to context "margu@kubernetes".

以下步骤在kubernetes-admin的权限下执行

[root@k8s-m1 ~]#  kubectl get rolebinding    
NAME             ROLE                  AGE
read-pods        Role/pod-reader       3d

[root@k8s-m1 ~]#  kubectl delete  rolebindings.rbac.authorization.k8s.io  read-pods 
rolebinding.rbac.authorization.k8s.io "read-pods" deleted
通过`kubectl config view` 查看当前的管理用户(current-context)确保使用的是margu用户

[root@k8s-m1 ~]#  kubectl get po 
Error from server (Forbidden): pods is forbidden: User "margu" cannot list resource "pods" in API group "" in the namespace "default"
#发现删除rolebinding后,margu账号已经不能使用

clusterrole+clusterrolebinding

授权流程(Clusterrole–> Clusterrolebinding )

[root@k8s-m1 pki]# kubectl config use-context kubernetes-admin@kubernetes  #切换会kubernetes-admin用户
Switched to context "kubernetes-admin@kubernetes".

##预生成一个yaml文件
[root@k8s-m1 pki]# kubectl create clusterrole cluster-read --verb=get,list,watch --resource=pods --dry-run  -o yaml > test-clusterrole.yml

[root@k8s-m1 pki]# cat clusterrole-demo.yaml  #查看定义clusterrole和权限,也可以修改
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  creationTimestamp: null
  name: cluster-read
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch


[root@k8s-m1 tmp]# kubectl apply -f  test-clusterrole.yml 
clusterrole.rbac.authorization.k8s.io/cluster-read configured

[root@k8s-m1 pki]# kubectl get clusterrole
NAME                                                                   CREATED AT
cluster-admin                                                          2022-05-13T07:17:19Z
cluster-read                                                           2023-02-24T03:09:53Z
cluster-readonly                                                       2022-06-28T03:12:42Z
......

clusterrolebinding定义

[root@k8s-m1 pki]#  kubectl create clusterrolebinding margu-read-all-pods --clusterrole=cluster-read --user=margu --dry-run=client -o yaml > test-clusterrolebinding.yaml

[root@k8s-m1 pki]# vim test-clusterrolebinding.yaml   #创建角色绑定,将k8s-user-test绑定到clusterrole:ye-read-all-pods上
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  creationTimestamp: null
  name: margu-read-all-pods
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-read
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: margu
[root@k8s-m1 pki]# kubectl apply -f  test-clusterrolebinding.yaml 
clusterrolebinding.rbac.authorization.k8s.io/margu-read-all-pods created

[root@k8s-m1 pki]# kubectl get clusterrolebinding
NAME                                                   ROLE                                                                               AGE
admin-user                                             ClusterRole/cluster-admin                                                          375d
blackbox-exporter                                      ClusterRole/blackbox-exporter                                                      250d
calico-kube-controllers                                ClusterRole/calico-kube-controllers                                                273d
.........
margu-read-all-pods                                    ClusterRole/cluster-read                                                           34s


[root@k8s-m1 pki]# kubectl describe clusterrolebindings.rbac.authorization.k8s.io  margu-read-all-pods
Name:         margu-read-all-pods
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  cluster-read
Subjects:
  Kind  Name   Namespace
  ----  ----   ---------
  User  margu  


[margu@k8s-m1 ~]$ kubectl get pod -A     #角色绑定后在test终端上进行获取pods信息,已经不会出现forbidden了
NAME                     READY   STATUS    RESTARTS   AGE
NAMESPACE                       NAME                                        READY   STATUS             RESTARTS   AGE
com-prod                        busybox                                     1/1     Running            279        11d
default                         cm-env-pod-all                              0/1     Completed          0          3d19h
default                         configmap-subpath                           1/1     Running            285        11d
default                         configmap-volume-pod                        1/1     Running            92         3d20h
default                         init-demo                                   1/1     Running            0          6d19h
default                         init-pod1                                   1/1     Running            163        6d19h
default                         liveness-exec-pod-1                         1/1     Running            133        5d13h
default                         liveness-http-pod                           1/1     Running            0          6d
default                         my-nginx-7ff446c4f4-2d9gz                   1/1     Running            1          10d
default                         my-nginx-7ff446c4f4-tbtpc                   1/1     Running            1          10d

或者直接使用`kubectl config use-context margu@kubernetes`切换后,测试效果和上面是一样的。主要看集群当前的管理用户


[margu@k8s-m1 ~]$ kubectl delete po cm-env-pod-all 
Error from server (Forbidden): pods "cm-env-pod-all" is forbidden: User "margu" cannot delete resource "pods" in API group "" in the namespace "default"
#但是进行删除pod就无法进行,因为在授权时是没有delete权限的

从上面的实验,我们可以知道对用户margu进行集群角色绑定,用户margu将会获取对集群内所有资源的对应权限。

clusterrole+rolebinding

授权流程Clusterrole–> Rolebinding
将margu通过rolebinding到集群角色cluster-read当中,此时,marug仅作用于当前名称空间的所有pods资源的权限。

#先删除原有的clusterrolebinding
[root@k8s-m1 pki]# kubectl delete clusterrolebinding margu-read-all-pods 
clusterrolebinding.rbac.authorization.k8s.io "margu-read-all-pods" deleted

#预生成yaml文件
[root@k8s-m1 pki]# kubectl create rolebinding margu-read-pods --clusterrole=cluster-read --user=margu --dry-run=client -o yaml > default-rolebinding-clusterrole.yaml

[root@k8s-m1 pki]# vim default-rolebinding-clusterrole.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: null
  name: margu-read-pods
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-read
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: margu

[root@k8s-m1 pki]# kubectl apply  -f default-rolebinding-clusterrole.yaml 
rolebinding.rbac.authorization.k8s.io/margu-read-pods created

#切换用户,不管用哪个用户都需要先切换上下文`kubectl config use-context margu@kubernetes`
[root@k8s-m1 pki]# kubectl config use-context margu@kubernetes
Switched to context "margu@kubernetes".

[root@k8s-m1 pki]# kubectl get pod
NAME                        READY   STATUS      RESTARTS   AGE
configmap-subpath           1/1     Running     306        12d
configmap-volume-pod        1/1     Running     113        4d17h
init-demo                   1/1     Running     0          7d17h
init-pod1                   1/1     Running     184        7d17h

[root@k8s-m1 pki]# kubectl get cm
Error from server (Forbidden): configmaps is forbidden: User "margu" cannot list resource "configmaps" in API group "" in the namespace "default"

[root@k8s-m1 pki]# kubectl get po -n kube-system
Error from server (Forbidden): pods is forbidden: User "margu" cannot list resource "pods" in API group "" in the namespace "kube-system"
#只能查看default命名空间下的pod,其他命名空间和当前命名空间的其他资源都不能查看。

#删除用户
[root@k8s-m1 pki]# kubectl config delete-context margu@kubernetes
deleted context margu@kubernetes from /root/.kube/config

[root@k8s-m1 pki]# kubectl config unset users.margu
Property "users.margu" unset.

示例:创建组访问Kubernetes集群(和user account 类似)

关于绑定group的资料比较少,大家可以参考下面的自行测试。

[root@k8s-m1 pki]#  openssl genrsa -out testgroupuser.key 2048
 
# 用此私钥创建一个csr(证书签名请求)文件
[root@k8s-m1 pki]# openssl req -new -key testgroupuser.key -subj "/O=testgroup/CN=testgroupuser" -out testgroupuser.csr
 
# 拿着私钥和请求文件生成证书
[root@k8s-m1 pki]# openssl x509 -req -in testgroupuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out testgroupuser.crt -days 3650

# 生成账号,相当于一个组(testgroupuser)
[root@k8s-m1 pki]# kubectl config set-credentials testgroupuser --client-certificate=./testgroupuser.crt --client-key=./testgroupuser.key --embed-certs=true

# 设置上下文参数,对比下面的两种不同之处
[root@k8s-m1 pki]# kubectl config set-context testgroupuser@kubernetes --cluster=kubernetes --user=testgroupuser 

[root@k8s-m1 pki]# kubectl config get-contexts 
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin   
          margu@kubernetes              kubernetes   margu              
          testgroup@kubernetes          kubernetes   testgroupuser      
          testgroupuser@kubernetes      kubernetes   testgroupuser 

[root@k8s-m1 pki]# cat testgroup-role-bind.yaml 
kind: Role  # 角色
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: dev
  name: testgroup-role
rules:
- apiGroups: [""] # ""代表核心api组
  resources: ["services","pods"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: RoleBinding # 角色绑定
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: testgroup-rolebinding
  namespace: dev
subjects:
- kind: Group
  name: testgroup   # 目标用户组
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: testgroup-role  # 角色信息
  apiGroup: rbac.authorization.k8s.io
  
[root@k8s-m1 pki]# kubectl apply  -f testgroup-role-bind.yaml 

[root@k8s-m1 pki]# kubectl config use-context testgroupuser@kubernetes
Switched to context "testgroupuser@kubernetes".
[root@k8s-m1 pki]# kubectl get po -n dev
No resources found in dev namespace.
[root@k8s-m1 pki]# kubectl config use-context testgroup@kubernetes
Switched to context "testgroup@kubernetes".
[root@k8s-m1 pki]# kubectl get po -n dev
No resources found in dev namespace.
##对比区别

示例: 对Service Account的授权管理

默认的RBAC策略为控制平台组件、节点和控制器授予有限范围的权限,但是在"kube-system"之外的Service Account是没有任何权限的。除了所有认证用户都具有的discovery权限。

在使用中,要求用户为Service Account赋予所需的权限。细粒度的角色分配能够提高安全性,但也会提高管理成本。粗放的授权方式可能会给Service Account多余的权限,但会更易于管理。

授予serviceaccount权限的示例:
1)在命名空间my-namespace内对"my-sa"Service Account 授予只读权限
kubectl create rolebinding my-sa-view --clusterrole=view --serviceaccount=my-namespace:my-sa --namespace=my-namespace

2)在全集群范围内为名为myapp的Service Account授予view ClusterRole
kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=my-namespace:myapp

更多关于kubernetes的知识分享,请前往博客主页。编写过程中,难免出现差错,敬请指出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/741644.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【UE4 C++】03-新建UE C++工程,新建C++类

UE版本&#xff1a;4.26 步骤 新建一个空白模板工程&#xff0c;选择C项目&#xff0c;选择项目名和项目存储位置&#xff0c;然后点击创建项目。 新建C类 选择父类为Character 命名&#xff0c;选择公有&#xff0c;然后点击创建类 等待编译完成 此时在Visual Studio中可以看…

源启:云原生计算架构的行业实现

7月5日&#xff0c;由工业和信息化部网络安全产业发展中心、中国软件行业协会等单位指导&#xff0c;中国电子主办的“麒麟傲天聚创未来2023操作系统产业大会”在京举行。中电金信研究院副院长陈书华在大会上发表主旨演讲。 陈书华认为数字经济已成为社会发展的重要引擎&#…

【论文解读】基于分层判断的 x264 快速模式选择算法

简介 题目&#xff1a; 基于分层判断的 x264 快速模式选择算法 原文&#xff1a; https://www.nstl.gov.cn/paper_detail.html?id77880ade9a55b3cc527192010242d90e 级别&#xff1a; EI 年份&#xff1a; 2010 年 机构&#xff1a; 上海交通大学 结论&#xff1a; 相比较 HE…

汽车+ChatGPT 车内生活体验再升级

这两年&#xff0c;人工智能工具ChatGPT爆火&#xff0c;在全球掀起了大模型之战。如今&#xff0c;最前沿的自然语言处理大模型应用到了人类的出行工具上&#xff0c;梅赛德斯-奔驰和微软官宣正在合作测试车载ChatGPT人工智能&#xff0c;并将面向约90万车主开启测试&#xff…

对象存储、数据库、NAS、标注数据集,均支持元信息配置|ModelWhale 版本更新

七月中旬&#xff0c;暑气渐浓&#xff0c;ModelWhale 新一轮的版本更新&#xff0c;期待为每个领域的你带来更好的使用体验。 本次更新中&#xff0c;ModelWhale 主要进行了以下功能迭代&#xff1a; • 新增 对象存储、数据库、NAS、标注数据的元信息展示&#xff08;专业版…

flutter开发实战-Theme主题切换

flutter开发实战-Theme主题切换 之前做的应用中有用到Theme主题切换&#xff0c;一直没有整理&#xff0c;这里整理一下。 使用的是Android studio 一、效果图 二、创建ThemeModel // 提供五套可选主题色 const _themes <MaterialColor>[Colors.blue,Colors.cyan,Co…

缓存 - Caffeine 不完全指北

文章目录 官网概述设计CodePOMPopulationEviction PolicyRefreshStatistics 官网 https://github.com/ben-manes/caffeine wiki: https://github.com/ben-manes/caffeine/wiki 概述 Caffeine是一个用于Java应用程序的高性能缓存框架。它提供了一个强大且易于使用的缓存库&a…

如何判定是否一份适合工作呢

核心指标&#xff1a;喜欢 春节仿佛还在昨天&#xff0c;转眼间2023年已经过半。分享和总结一下自己过去的这6个月吧&#xff01;你可以从以下几个方面展开谈谈。 23年上半年已经过去啦。结合工作多年经历简单写一写。 主要写自己&#xff1a; 工作非常努力&#xff0c;但是…

Java 一文掌握全部阻塞队列的使用

1、简介 本文主要对Java常用阻塞队列进行介绍和提供相关使用案例 2、 阻塞队列作用 阻塞队列提供了一种线程安全、高效的数据传递和同步机制 &#xff0c; 主要用于缓冲数据、限流、削峰填谷&#xff0c;生产者-消费者模型&#xff0c;线程间的协作等等。 3、 各阻塞队列区…

人工智能学术顶会——NeurIPS 2022 议题(网络安全方向)清单、摘要与总结

按语&#xff1a;随着大模型的崛起&#xff0c;将AI再次推向一个高峰&#xff0c;受到的关注也越来越大。在网络安全领域&#xff0c;除4大安全顶会外&#xff0c;一些涉及AI的安全话题&#xff0c;包括对AI的攻防研究&#xff0c;以及应用AI做安全的研究方向&#xff0c;也会发…

在vite创建的vue3项目中使用Cesium加载纽约建筑模型、设置样式,划分城市区域并着色

在vite创建的vue3项目中使用Cesium加载纽约建筑模型、设置样式&#xff0c;划分城市区域并着色 使用vite创建vue3项目 npm create vitelatestcd到创建的项目文件夹中 npm install安装Cesium npm i cesium vite-plugin-cesium vite -D配置 vite.config.js文件&#xff1a;添加Ce…

系统架构设计师 8:系统质量属性与架构评估

软件系统属性包括功能属性和质量属性&#xff0c;软件架构重点关注的是质量属性。为了精确、定量地表达系统的质量属性&#xff0c;通常会采用质量属性场景的方式进行描述。 在确定软件系统架构&#xff0c;精确描述质量属性场景后&#xff0c;就需要对系统架构进行评估。软件…

前端|CSS(二)

参考视频&#xff1a;黑马程序员前端CSS3基础教程&#xff0c;前端必备基础 目录 &#x1f4da;CSS 布局的三种机制 &#x1f407;普通流 &#x1f407;浮动 ⭐️浮动介绍 ⭐️浮动(float)的应用 ⭐️浮动(float)的扩展 ⭐️清除浮动 &#x1f407;定位 ⭐️定位 ⭐️…

shell? 变量!

目录 ​编辑 &#x1f428;什么是shell &#x1f428;编译型语言和解释型语言 &#x1f428;解释型语言 &#x1f428;变量 &#x1f428;1.局部变量&#xff1a; &#x1f428;2.环境变量通常又称“全局变量” &#x1f428;3.设置环境变量&#xff1a; &#x1f4…

NZ系列工具:NZ11:VBA光标跟随策略

【分享成果&#xff0c;随喜正能量】生活就像是一杯苦茶&#xff0c;而情感是茉莉花&#xff0c;调兑在一起&#xff0c;才会馥郁芬芳。人活在世上&#xff0c;有诸多苦楚萦心&#xff0c;若不懂得自我调解&#xff0c;终究会被纷呈的世相掩埋。所以&#xff0c;更多的时候&…

Ubuntu18.04修改file descriptors(文件描述符限制),解决elasticsearch启动报错问题

最近在学习elasticsearch&#xff0c;使用的平台是Ubuntu18.04&#xff0c;在部署过程中的坑记录一下。 下载安装的过程就不说了&#xff0c;在启动es的时候报错 1 max file descriptors [4096] for elasticsearch process is too low, increase to at least [65535] 看了下…

TIOBE 7月编程语言榜出炉,这个语言强势突围,前三发生重大变化

TIOBE 公布了 2023 年 7 月的编程指数信息&#xff0c;在这个月&#xff0c;语言榜有什么新变化&#xff0c;让我们一起去看看吧&#xff01; JavaScript 创历史新高 几个月前&#xff0c;编程语言 C 占据了 TIOBE 指数的第 3 位&#xff08;超过了 Java&#xff09;。 但C的…

Golang 中的流程控制

1、Golang 中的流程控制 Go 语言中最常用的流程控制有 if 和 for &#xff0c;而 switch 和 goto 主要是为了简化代码、降低重复 代码而生的结构&#xff0c;属于扩展类的流程控制。 2、if else(分支结构) if 语句 if 语句 由一个布尔表达式后紧跟一个或多个语句组成。…

JDBC技术【SQL注入、JDBC批量添加数据、JDBC事务处理、其他查询方式】(三)-全面详解(学习总结---从入门到深化)

目录 SQL注入 JDBC批量添加数据 JDBC事务处理 Blob类型的使用 插入Blob类型数据 其他查询方式 动态条件查询 SQL注入 什么是SQL注入 所谓 SQL 注入&#xff0c;就是通过把含有 SQL 语句片段的参数插入到需要 执行的 SQL 语句中&#xff0c; 最终达到欺骗数据库服务器执行…

如何将各个阶段的数据进行对比?Sugar BI 教你快速搞定

折线图可以将当前和某个时间段的数据进行对比&#xff0c;比如前一天、上周、去年。 数据对比开启条件 当折线图 X 轴有且只有一个日期或时间字段&#xff0c;并且聚合方式为年-xx&#xff0c;Y 轴有且只有一个度量字段时&#xff0c;可以开启并配置折线图数据对比。 支持数据…