From 885733814229e2db302cffb56bb86a3d98a21c7d Mon Sep 17 00:00:00 2001 From: wxin <15253413025@163.com> Date: Sun, 11 Aug 2024 21:05:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20kubernetes-MD/kubernetes-R?= =?UTF-8?q?BAC.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kubernetes-MD/kubernetes-RBAC.md | 1487 +++++++++++++++--------------- 1 file changed, 743 insertions(+), 744 deletions(-) diff --git a/kubernetes-MD/kubernetes-RBAC.md b/kubernetes-MD/kubernetes-RBAC.md index 336da5f..056139a 100644 --- a/kubernetes-MD/kubernetes-RBAC.md +++ b/kubernetes-MD/kubernetes-RBAC.md @@ -1,744 +1,743 @@ -

kubernetes-RBAC

- -著作:行癫 <盗版必究> - ------- - -## 一:RBAC详解 - -#### 1.RBAC基于角色的访问控制 - -​ Service Account为服务提供了一种方便的认证机制,但它不关心授权的问题。可以配合RBAC来为Service Account鉴权,在Kubernetes中,授权有ABAC(基于属性的访问控制)、RBAC(基于角色的访问控制)、Webhook、Node、AlwaysDeny(一直拒绝)和AlwaysAllow(一直允许)这6种模式 - -​ 从1.6版起,Kubernetes 默认启用RBAC访问控制策略 - -​ 从1.8开始,RBAC已作为稳定的功能 - -#### 2.授权步骤 - -​ 定义角色:在定义角色时会指定此角色对于资源的访问控制的规则 - -​ 绑定角色:将主体与角色进行绑定,对用户进行访问授权 - -​ 基于角色的访问控制使用"rbac.authorization.k8s.io" API Group实现授权决策允许管理员通过Kubernetes API动态配置策略 - -​ 定义Role、ClusterRole、RoleBinding或ClusterRoleBinding - -#### 3.启用RBAC - -​ 要启用RBAC,使用--authorization-mode=RBAC启动API Server - -```shell -[root@master ~]# cat /etc/kubernetes/manifests/kube-apiserver.yaml -apiVersion: v1 -kind: Pod -metadata: - annotations: - kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 192.168.18.160:6443 - creationTimestamp: null - labels: - component: kube-apiserver - tier: control-plane - name: kube-apiserver - namespace: kube-system -spec: - containers: - - command: - - kube-apiserver - - --advertise-address=192.168.18.160 - - --allow-privileged=true - - --authorization-mode=Node,RBAC -``` - -#### 4.Role与ClusterRole - -​ 一个角色包含了一套表示一组权限的规则。 权限以纯粹的累加形式累积(没有"否定"的规则) - -###### Role: - -​ 角色可以由命名空间内的Role对象定义 - -​ 一个Role对象只能用于授予对某一单一命名空间中资源的访问权限 - -###### ClusterRole: - -​ 整个Kubernetes集群范围内有效的角色则通过ClusterRole对象实现 - -###### Role示例: - -​ 描述"default"命名空间中的一个Role对象的定义,用于授予对pod的读访问权限 - -```shell -kind: Role -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - namespace: default - name: pod-reader -rules: -- apiGroups: [""]       # 空字符串""表明使用core API group - resources: ["pods"] - verbs: ["get", "watch", "list"] -``` - -注意: - -​ watch操作语义的含义如下:读取状态并从任意版本开始 - -​ 在任何资源版本开始 watch;首选可用的最新资源版本,但不是必需的。允许任何起始资源版本。由于分区或过时的缓存,watch 可能从客户端之前观察到的更旧的资源版本开始,特别是在高可用性配置中。不能容忍这种明显倒带的客户不应该用这种语义启动 watch。 为了建立初始状态,watch从起始资源版本中存在的所有资源实例的合成 “添加” 事件开始。 以下所有监视事件都针对在watch开始的资源版本之后发生的所有更改 - -**读取状态并从最新版本开始** - -​ 从最近的资源版本开始 **watch**, 它必须是一致的(详细说明:通过仲裁读取从 etcd 提供服务)。 为了建立初始状态,**watch** 从起始资源版本中存在的所有资源实例的合成 “添加” 事件开始。 以下所有监视事件都针对在 **watch** 开始的资源版本之后发生的所有更改 - -**从指定版本开始** - -​ 以确切的资源版本开始 **watch**。监视事件适用于提供的资源版本之后的所有更改。 与 “Get State and Start at Most Recent” 和 “Get State and Start at Any” 不同, **watch** 不会以所提供资源版本的合成 “添加” 事件启动。 由于客户端提供了资源版本,因此假定客户端已经具有起始资源版本的初始状态 - -###### ClusterRole示例: - -​ ClusterRole定义可用于授予用户对某一特定命名空间,或者所有命名空间中的secret(取决于其绑定方式)的读访问权限 - -```shell -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - # ClusterRole是集群范围对象,所以这里不需要定义"namespace"字段 - name: secret-reader -rules: -- apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "watch", "list"] -``` - -#### 5.RoleBinding与ClusterRoleBinding - -​ 角色绑定将一个角色中定义的各种权限授予一个或者一组用户 - -###### 角色绑定包含: - -​ 一组相关主体, 即:subject - -​ 包括: - -​ 用户--User - -​ 用户组--Group - -​ 服务账户--Service Account - -​ 对被授予角色的引用 - -###### RoleBinding: - -​ 在命名空间中可以通过RoleBinding对象授予权限 - -​ RoleBinding可以引用在同一命名空间内定义的Role对象 - -###### ClusterRoleBinding: - -​ 集群范围的权限授予则通过ClusterRoleBinding对象完成 - -###### RoleBinding示例: - -​ 定义的RoleBinding对象在"default"命名空间中将"pod-reader"角色授予用户"jane"。 这一授权将允许用户"jane"从"default"命名空间中读取pod;以下角色绑定定义将允许用户"jane"从"default"命名空间中读取pod: - -```shell -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: read-pods - namespace: default -subjects: -- kind: User          #赋予用户jane pod-reader角色权限 - name: jane - apiGroup: rbac.authorization.k8s.io -roleRef: - kind: Role - name: pod-reader      #引用上面定义的role - apiGroup: rbac.authorization.k8s.io -``` - -​ RoleBinding对象也可以引用一个ClusterRole对象 - -​ 用于在RoleBinding所在的命名空间内授予用户对所引用的ClusterRole中定义的命名空间资源的访问权限 - -​ 这一点允许管理员在整个集群范围内首先定义一组通用的角色,然后再在不同的命名空间中复用这些角色 - -​ 例如,尽管下面示例中的RoleBinding引用的是一个ClusterRole对象,但是用户"dave"(即角色绑定主体)还是只能读取"development" 命名空间中的secret(即RoleBinding所在的命名空间) - -​ 以下角色绑定允许用户 "dave" 读取 "development" 命名空间中的secret: - -```shell -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: read-secrets - namespace: development       # 这里表明仅授权读取"development"命名空间中的资源。 -subjects: -- kind: User - name: dave - apiGroup: rbac.authorization.k8s.io -roleRef: - kind: ClusterRole - name: secret-reader      #引用上面定义的clusterRole 名称(clusterRole没有指定命名空间,默认可以应用所有,但是在rolebinding时,指定了命名空间,所以只能读取本命名空间的文件) - apiGroup: rbac.authorization.k8s.io -``` - -​ ClusterRoleBinding在集群级别和所有命名空间中授予权限 - -​ 以下 'ClusterRoleBinding' 对象允许在用户组 "manager" 中的任何用户都可以读取集群中任何命名空间中的secret - -```shell -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: read-secrets-global -subjects: -- kind: Group - name: manager - apiGroup: rbac.authorization.k8s.io -roleRef: - kind: ClusterRole - name: secret-reader - apiGroup: rbac.authorization.k8s.io -``` - -#### 6.role对资源的引用 - -​ 大多数资源由代表其名字的字符串表示,如 "pods",就像它们出现在相关API endpoint的URL中一样。然而,有一些Kubernetes API还包含了 "子资源" - -​ 比如pod的logs: - -​ pod logs endpoint的URL格式为: - -​ GET /api/v1/namespaces/{namespace}/pods/{name}/log - -​ 这种情况下,"pods" 是命名空间资源,而 "log" 是pods的子资源 - -​ 为了在RBAC角色中表示出这一点,需使用斜线来划分 资源 与 子资源 - -例子: - -​ 如果需要角色绑定主体读取pods以及pod log,需要定义以下角色 - -```shell -kind: Role -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - namespace: default - name: pod-and-pod-logs-reader -rules: -- apiGroups: [""] - resources: ["pods", "pods/log"]    #表示授予读取pods下log的权限 - verbs: ["get", "list"] -``` - -###### resourceNames: - -​ 通过 resourceNames 列表,角色可以针对不同种类的请求根据资源名引用资源实例。当指定了resourceNames 列表时,不同动作种类的请求的权限,如使用 "get"、"delete"、"update" 以及 "patch" 等动词的请求,将被限定到资源列表中所包含的资源实例上 - -例子: - -​ 如果需要限定一个角色绑定主体只能 "get" 或者 "update" 一个configmap时,可以定义以下角色 - -```shell -kind: Role -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - namespace: default - name: configmap-updater -rules: -- apiGroups: [""] - resources: ["configmap"] - resourceNames: ["my-configmap"] - verbs: ["update", "get"] -``` - -注意: - -​ 如果设置了resourceNames,则请求所使用的动词不能是list、watch、create或者deletecollection,由于资源名不会出现在create、list、watch和deletecollection等API请求的URL中,所以这些请求动词不会被设置了resourceNames 的规则所允许,因为规则中的resourceNames部分不会匹配这些请求 - -###### 角色定义的例子: - -​ 在以下示例中,仅截取展示了rules部分的定义: - -允许读取core API Group中定义的资源 "pods" - -```shell -rules: -- apiGroups: [""] - resources: ["pods"] - verbs: ["get", "list", "watch"] -``` - -允许读写在 "extensions" 和 "apps" API Group中定义的 "deployments" - -```shell -rules: -- apiGroups: [""] - resources: ["deployments"] - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] -``` - -允许读取 "pods" 以及读写 "jobs" - -```shell -rules: -- apiGroups: [""] - resources: ["pods"] - verbs: ["get", "list", "watch"] -- apiGroups: ["batch", "extensions"] - resources: ["jobs"] - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] -``` - -允许读取一个名为 "my-config" 的 ConfigMap 实例 - -```shell -rules: -- apiGroups: [""] - resources: ["configmaps"] - resourceNames: ["my-config"] - verbs: ["get"] -``` - -允许读取core API Group中的"nodes"资源,Node是集群级别资源,所以此ClusterRole定义需要与一个ClusterRoleBinding绑定才能有效 - -```shell -rules: -- apiGroups: [""] - resources: ["nodes"] - verbs: ["get", "list", "watch"] -``` - -允许对非资源endpoint "/healthz" 及其所有子路径的 "GET" 和 "POST" 请求 - -```shell -rules: -- nonResourceURLs: ["/healthz", "/healthz/*"]   # 在非资源URL中,'*'代表后缀通配符 - verbs: ["get", "post"] - -注意: - 此ClusterRole定义需要与一个ClusterRoleBinding绑定才能有效 -``` - -#### 7.对角色绑定主体(Subject)的引用 - -​ RoleBinding或者ClusterRoleBinding将角色绑定到角色绑定主体(Subject)。 角色绑定主体(kind指定)可以是用户组(Group)、用户(User)或者服务账户(Service Accounts) - -###### 用户: - -​ 由字符串表示 - -​ 纯粹的用户名,例如 "alice" - -​ 电子邮件风格的名字,如 "bob@example.com" - -​ 用字符串表示的数字id - -用户的产生: - -​ 由Kubernetes管理员配置认证模块以产生所需格式的用户名。对于用户名,RBAC授权系统不要求任何特定的格式 - -注意: - -​ 前缀system:是 为Kubernetes系统使用而保留的,所以管理员应该确保用户名不会意外地包含这个前缀 - -用户组的产生: - -​ Kubernetes中的用户组信息由授权模块提供。用户组与用户一样由字符串表示。Kubernetes对用户组 字符串没有格式要求,但前缀system:同样是被系统保留的 - -服务账户: - -​ 服务账户(serviceAccount)拥有包含 system:serviceaccount:前缀的用户名,并属于拥有system:serviceaccounts:前缀的用户组 - -###### 角色绑定例子: - -​ 以下示例中,仅截取展示了RoleBinding的subjects字段 - -一个名为"alice@example.com"的用户 - -```shell -subjects: -- kind: User - name: "alice@example.com" - apiGroup: rbac.authorization.k8s.io -``` - -一个名为"frontend-admins"的用户组 - -```shell -subjects: -- kind: Group - name: "frontend-admins" - apiGroup: rbac.authorization.k8s.io -``` - -kube-system命名空间中的默认服务账户 - -```shell -subjects: -- kind: ServiceAccount - name: default - namespace: kube-system -``` - -名为"qa"命名空间中的所有服务账户 - -```shell -subjects: -- kind: Group - name: system:serviceaccounts:qa - apiGroup: rbac.authorization.k8s.io -``` - -在集群中的所有服务账户 - -```shell -subjects: -- kind: Group - name: system:serviceaccounts - apiGroup: rbac.authorization.k8s.io -``` - -所有认证过的用户(version 1.5+) - -```shell -subjects: -- kind: Group - name: system:authenticated - apiGroup: rbac.authorization.k8s.io -``` - -所有未认证的用户(version 1.5+) - -```shell -subjects: -- kind: Group - name: system:unauthenticated - apiGroup: rbac.authorization.k8s.io -``` - -所有用户(version 1.5+) - -```shell -subjects: -- kind: Group - name: system:authenticated - apiGroup: rbac.authorization.k8s.io -- kind: Group - name: system:unauthenticated - apiGroup: rbac.authorization.k8s.io -``` - -#### 8.默认角色与默认角色绑定 - -​ API Server会创建一组默认的ClusterRole和ClusterRoleBinding对象。 这些默认对象中有许多包含system:前缀,表明这些资源由Kubernetes基础组件"拥有"。 对这些资源的修改可能导致非功能性集群(non-functional cluster) - -​ 比如:system:node ClusterRole对象。 这个角色定义了kubelets的权限。如果这个角色被修改,可能会导致kubelets无法正常工作 - -​ 所有默认的ClusterRole和ClusterRoleBinding对象都会被标记为kubernetes.io/bootstrapping=rbac-defaults - -​ 每次启动时,API Server都会更新默认ClusterRole所缺乏的各种权限,并更新默认ClusterRoleBinding所缺乏的各个角色绑定主体。 这种自动更新机制允许集群修复一些意外的修改。由于权限和角色绑定主体在新的Kubernetes释出版本中可能变化,这也能够保证角色和角色绑定始终保持是最新的 - -​ 如果需要禁用自动更新,请将默认ClusterRole以及ClusterRoleBinding的rbac.authorization.kubernetes.io/autoupdate 设置成为false。 请注意,缺乏默认权限和角色绑定主体可能会导致非功能性集群问题 - -​ 自Kubernetes 1.6+起,当集群RBAC授权器(RBAC Authorizer)处于开启状态时,可以启用自动更新功能 - -###### 命令行工具: - -​ 有两个kubectl命令可以用于在命名空间内或者整个集群内授予角色 - -```shell -[root@master ~]# kubectl create rolebinding -``` - -​ 在某一特定命名空间内授予Role或者ClusterRole - -示例如下: - -​ 在名为"acme"的命名空间中将admin ClusterRole授予用户"bob" - -```shell -[root@master ~]# kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme -``` - -​ 在名为"acme"的命名空间中将view ClusterRole授予服务账户"myapp" - -```shell -[root@master ~]# kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme -``` - -在整个集群中授予ClusterRole,包括所有命名空间,示例如下: - -​ 在整个集群范围内将cluster-admin ClusterRole授予用户"root" - -```shell - [root@master ~]# kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root -``` - -​ 在整个集群范围内将system:node ClusterRole授予用户"kubelet" - -```shell -[root@master ~]# kubectl create clusterrolebinding kubelet-node-binding --clusterrole=system:node --user=kubelet -``` - -​ 在整个集群范围内将view ClusterRole授予命名空间"acme"内的服务账户"myapp" - -```shell -[root@master ~]# kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp -``` - -#### 9.服务账户(Service Account)权限 - -​ 默认的RBAC策略将授予控制平面组件(control-plane component)、节点(node)和控制器(controller)一组范围受限的权限, 但对于"kube-system"命名空间以外的服务账户,则不授予任何权限(超出授予所有认证用户的发现权限) - -从最安全到最不安全可以排序以下方法: - -​ 对某一特定应用程序的服务账户授予角色(最佳实践) - -​ 要求应用程序在其pod规范(pod spec)中指定serviceAccountName字段,并且要创建相应服务账户(例如通过API、应用程序清单或者命令kubectl create serviceaccount等) - -###### 案例: - -​ 在"my-namespace"命名空间中授予服务账户"my-sa"只读权限 - -```shell -[root@master ~]# kubectl create rolebinding my-sa-view \ - --clusterrole=view \ - --serviceaccount=my-namespace:my-sa \ - --namespace=my-namespace -``` - -​ 换成yaml文件大概如下 - -```shell -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1beta1 -metadata: - name: my-sa-view - namespace: my-namespace -subjects: -- kind: ServiceAccount - name: my-sa - apiGroup: rbac.authorization.k8s.io -roleRef: - kind: ClusterRole - name: view #这里view为clusterrole名称,其中berbs需要给view - apiGroup: rbac.authorization.k8s.io -``` - -在某一命名空间中授予"default"服务账号角色 - -​ 如果一个应用程序没有在其pod规范中指定serviceAccountName,它将默认使用"default"服务账号 - -​ 注意:授予"default"服务账号的权限将可用于命名空间内任何没有指定serviceAccountName的pod - -例子: - -​ 下面的例子将在"my-namespace"命名空间内授予"default"服务账号只读权限 - -```shell -[root@master ~]# kubectl create rolebinding default-view \ - --clusterrole=view \ - --serviceaccount=my-namespace:default \ - --namespace=my-namespace -``` - -​ 目前,许多加载项(addon)作为"kube-system"命名空的"default"服务帐户运行。 要允许这些加载项使用超级用户访问权限,请将cluster-admin权限授予"kube-system"命名空间中的"default"服务帐户。 注意:启用上述操作意味着"kube-system"命名空间将包含允许超级用户访问API的秘钥 - -```shell -[root@master ~]# kubectl create clusterrolebinding add-on-cluster-admin \ ---clusterrole=cluster-admin \ ---serviceaccount=kube-system:default -``` - -为命名空间中所有的服务账号授予角色 - -​ 如果希望命名空间内的所有应用程序都拥有同一个角色,无论它们使用什么服务账户,可以为该命名空间的服务账户用户组授予角色 - -例子: - -​ 下面的例子将授予"my-namespace"命名空间中的所有服务账户只读权限 - -```shell -[root@master ~]# kubectl create rolebinding serviceaccounts-view \ ---clusterrole=view \ ---group=system:serviceaccounts:my-namespace \ ---namespace=my-namespace -``` - -## 二:RBAC应用 - -​ 创建k8s账号与RBAC授权使用 - -#### 创建账号 - -​ 创建私钥 - -```shell -[root@master ~]# (umask 077; openssl genrsa -out xingdian.key 2048) -``` - -​ 用此私钥创建一个csr(证书签名请求)文件 - -```shell -[root@master ~]# openssl req -new -key xingdian.key -out xingdian.csr -subj "/CN=xingdian" -[root@master ~]# openssl x509 -req -in xingdian.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out xingdian.crt -days 365 -``` - -​ 看证书内容 - -```shell -[root@master ~]# openssl x509 -in xingdian.crt -text -noout -[root@master ~]# kubectl config set-credentials xingdian --client-certificate=./xingdian.crt --client-key=./xingdian.key --embed-certs=true -``` - -​ 设置上下文(设置为k8s集群的用户) - -```shell -[root@master ~]# kubectl config set-context xingdian@kubernetes --cluster=kubernetes --user=xingdian -``` - -​ 查看当前的工作上下文 - -```shell -[root@master ~]# kubectl config view -``` - -​ 切换用户(切换上下文) - -```shell -[root@master ~]# kubectl config use-context xingdian@kubernetes -``` - -​ 验证是否已经切换到了新的上下文 - -```shell -[root@master ~]# kubectl config current-context -``` - -​ 测试(还未赋予权限) - -```shell -[root@master ~]# kubectl get pod -No resources found. -Error from server (Forbidden): pods is forbidden: User "wing" cannot list pods in the namespace "default" -``` - -#### 授权 - -​ K8S授权请求是http的请求 - -​ 对象URL格式: - -​ /apis/[GROUP]/[VERSION]/namespace/[NAMESPACE_NAME]/[KIND]/[OBJECT_ID] - -​ k8s授权方式分为: - -​ serviceaccount和自己签证ca证书的账号,及签证ca的用户组(group)上(授权给这个组的权限) - -​ role: - -​ 允许的操作,如get,list等 - -​ 允许操作的对象,如pod,svc等 - -​ rolebinding: - -​ 将哪个用户绑定到哪个role或clusterrole上 - -​ clusterrole:(集群角色) - -​ clusterrolebinding:(绑定到集群) - -​ 如果使用rolebinding绑定到role上,表示绑定的用户只能用于当前namespace的权限 - -###### 创建一个角色: - -​ 切回管理帐号先 - -```shell -[root@master ~]# kubectl config use-context kubernetes-admin@kubernetes -[root@master ~]# kubectl create role myrole --verb=get,list,watch --resource=pod,svc -``` - -​ 绑定用户xingdian,绑定role为myrole - -```shell -[root@master ~]# kubectl create rolebinding myrole-binding --role=myrole --user=xingdian -``` - -​ 切换用户 - -```shell -[root@master ~]# kubectl config use-context xingdian@kubernetes -Switched to context "xingdian@kubernetes". -``` - -​ 查看权限 - -​ 只授权了default名称空间pod和svc的get,list,watch权限 - -```shell -[root@master ~]# kubectl get pod -NAME READY STATUS RESTARTS AGE -nginx-pod 0/1 ImagePullBackOff 0 1h - -[root@master ~]# kubectl get pod -n kube-system #无权访问kube-system -No resources found. -Error from server (Forbidden): pods is forbidden: User "wing" cannot list pods in the namespace "kube-system" - -[root@master ~]# kubectl delete pod nginx-pod #无删除权限 -Error from server (Forbidden): pods "nginx-pod" is forbidden: User "wing" cannot delete pods in the namespace "default" -``` - -###### 创建clusterrole: - -​ 可以访问全部的namespace - -```shell -[root@master ~]# kubectl create clusterrole mycluster-role --verb=get,list,watch --resource=pod,svc -``` - -​ 删除xingdian账号之前绑定的rolebinding - -```shell -[root@master ~]# kubectl delete rolebinding myrole-binding -``` - -​ 使用clusterrolebinding绑定clusterrole - -```shell -[root@master ~]# kubectl create clusterrolebinding my-cluster-rolebinding --clusterrole=mycluster-role --user=xingdian -``` - -​ 切换账号 - -```shell -[root@master ~]# kubectl config use-context xingdian@kubernetes -``` - -​ 查看权限 查看kube-system空间的pod - -```shell -# kubectl get pod -n kube-system -NAME READY STATUS RESTARTS AGE -coredns-78fcdf6894-67h9h 1/1 Running 1 11h -coredns-78fcdf6894-lzxmz 1/1 Running 1 11h -etcd-k8s-m 1/1 Running 2 11h -...... -``` - - - - - - - - - - - - - +

kubernetes-RBAC

+ + +------ + +## 一:RBAC详解 + +#### 1.RBAC基于角色的访问控制 + +​ Service Account为服务提供了一种方便的认证机制,但它不关心授权的问题。可以配合RBAC来为Service Account鉴权,在Kubernetes中,授权有ABAC(基于属性的访问控制)、RBAC(基于角色的访问控制)、Webhook、Node、AlwaysDeny(一直拒绝)和AlwaysAllow(一直允许)这6种模式 + +​ 从1.6版起,Kubernetes 默认启用RBAC访问控制策略 + +​ 从1.8开始,RBAC已作为稳定的功能 + +#### 2.授权步骤 + +​ 定义角色:在定义角色时会指定此角色对于资源的访问控制的规则 + +​ 绑定角色:将主体与角色进行绑定,对用户进行访问授权 + +​ 基于角色的访问控制使用"rbac.authorization.k8s.io" API Group实现授权决策允许管理员通过Kubernetes API动态配置策略 + +​ 定义Role、ClusterRole、RoleBinding或ClusterRoleBinding + +#### 3.启用RBAC + +​ 要启用RBAC,使用--authorization-mode=RBAC启动API Server + +```shell +[root@master ~]# cat /etc/kubernetes/manifests/kube-apiserver.yaml +apiVersion: v1 +kind: Pod +metadata: + annotations: + kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 192.168.18.160:6443 + creationTimestamp: null + labels: + component: kube-apiserver + tier: control-plane + name: kube-apiserver + namespace: kube-system +spec: + containers: + - command: + - kube-apiserver + - --advertise-address=192.168.18.160 + - --allow-privileged=true + - --authorization-mode=Node,RBAC +``` + +#### 4.Role与ClusterRole + +​ 一个角色包含了一套表示一组权限的规则。 权限以纯粹的累加形式累积(没有"否定"的规则) + +###### Role: + +​ 角色可以由命名空间内的Role对象定义 + +​ 一个Role对象只能用于授予对某一单一命名空间中资源的访问权限 + +###### ClusterRole: + +​ 整个Kubernetes集群范围内有效的角色则通过ClusterRole对象实现 + +###### Role示例: + +​ 描述"default"命名空间中的一个Role对象的定义,用于授予对pod的读访问权限 + +```shell +kind: Role +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + namespace: default + name: pod-reader +rules: +- apiGroups: [""]       # 空字符串""表明使用core API group + resources: ["pods"] + verbs: ["get", "watch", "list"] +``` + +注意: + +​ watch操作语义的含义如下:读取状态并从任意版本开始 + +​ 在任何资源版本开始 watch;首选可用的最新资源版本,但不是必需的。允许任何起始资源版本。由于分区或过时的缓存,watch 可能从客户端之前观察到的更旧的资源版本开始,特别是在高可用性配置中。不能容忍这种明显倒带的客户不应该用这种语义启动 watch。 为了建立初始状态,watch从起始资源版本中存在的所有资源实例的合成 “添加” 事件开始。 以下所有监视事件都针对在watch开始的资源版本之后发生的所有更改 + +**读取状态并从最新版本开始** + +​ 从最近的资源版本开始 **watch**, 它必须是一致的(详细说明:通过仲裁读取从 etcd 提供服务)。 为了建立初始状态,**watch** 从起始资源版本中存在的所有资源实例的合成 “添加” 事件开始。 以下所有监视事件都针对在 **watch** 开始的资源版本之后发生的所有更改 + +**从指定版本开始** + +​ 以确切的资源版本开始 **watch**。监视事件适用于提供的资源版本之后的所有更改。 与 “Get State and Start at Most Recent” 和 “Get State and Start at Any” 不同, **watch** 不会以所提供资源版本的合成 “添加” 事件启动。 由于客户端提供了资源版本,因此假定客户端已经具有起始资源版本的初始状态 + +###### ClusterRole示例: + +​ ClusterRole定义可用于授予用户对某一特定命名空间,或者所有命名空间中的secret(取决于其绑定方式)的读访问权限 + +```shell +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + # ClusterRole是集群范围对象,所以这里不需要定义"namespace"字段 + name: secret-reader +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "watch", "list"] +``` + +#### 5.RoleBinding与ClusterRoleBinding + +​ 角色绑定将一个角色中定义的各种权限授予一个或者一组用户 + +###### 角色绑定包含: + +​ 一组相关主体, 即:subject + +​ 包括: + +​ 用户--User + +​ 用户组--Group + +​ 服务账户--Service Account + +​ 对被授予角色的引用 + +###### RoleBinding: + +​ 在命名空间中可以通过RoleBinding对象授予权限 + +​ RoleBinding可以引用在同一命名空间内定义的Role对象 + +###### ClusterRoleBinding: + +​ 集群范围的权限授予则通过ClusterRoleBinding对象完成 + +###### RoleBinding示例: + +​ 定义的RoleBinding对象在"default"命名空间中将"pod-reader"角色授予用户"jane"。 这一授权将允许用户"jane"从"default"命名空间中读取pod;以下角色绑定定义将允许用户"jane"从"default"命名空间中读取pod: + +```shell +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: read-pods + namespace: default +subjects: +- kind: User          #赋予用户jane pod-reader角色权限 + name: jane + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: pod-reader      #引用上面定义的role + apiGroup: rbac.authorization.k8s.io +``` + +​ RoleBinding对象也可以引用一个ClusterRole对象 + +​ 用于在RoleBinding所在的命名空间内授予用户对所引用的ClusterRole中定义的命名空间资源的访问权限 + +​ 这一点允许管理员在整个集群范围内首先定义一组通用的角色,然后再在不同的命名空间中复用这些角色 + +​ 例如,尽管下面示例中的RoleBinding引用的是一个ClusterRole对象,但是用户"dave"(即角色绑定主体)还是只能读取"development" 命名空间中的secret(即RoleBinding所在的命名空间) + +​ 以下角色绑定允许用户 "dave" 读取 "development" 命名空间中的secret: + +```shell +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: read-secrets + namespace: development       # 这里表明仅授权读取"development"命名空间中的资源。 +subjects: +- kind: User + name: dave + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: secret-reader      #引用上面定义的clusterRole 名称(clusterRole没有指定命名空间,默认可以应用所有,但是在rolebinding时,指定了命名空间,所以只能读取本命名空间的文件) + apiGroup: rbac.authorization.k8s.io +``` + +​ ClusterRoleBinding在集群级别和所有命名空间中授予权限 + +​ 以下 'ClusterRoleBinding' 对象允许在用户组 "manager" 中的任何用户都可以读取集群中任何命名空间中的secret + +```shell +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: read-secrets-global +subjects: +- kind: Group + name: manager + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: secret-reader + apiGroup: rbac.authorization.k8s.io +``` + +#### 6.role对资源的引用 + +​ 大多数资源由代表其名字的字符串表示,如 "pods",就像它们出现在相关API endpoint的URL中一样。然而,有一些Kubernetes API还包含了 "子资源" + +​ 比如pod的logs: + +​ pod logs endpoint的URL格式为: + +​ GET /api/v1/namespaces/{namespace}/pods/{name}/log + +​ 这种情况下,"pods" 是命名空间资源,而 "log" 是pods的子资源 + +​ 为了在RBAC角色中表示出这一点,需使用斜线来划分 资源 与 子资源 + +例子: + +​ 如果需要角色绑定主体读取pods以及pod log,需要定义以下角色 + +```shell +kind: Role +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + namespace: default + name: pod-and-pod-logs-reader +rules: +- apiGroups: [""] + resources: ["pods", "pods/log"]    #表示授予读取pods下log的权限 + verbs: ["get", "list"] +``` + +###### resourceNames: + +​ 通过 resourceNames 列表,角色可以针对不同种类的请求根据资源名引用资源实例。当指定了resourceNames 列表时,不同动作种类的请求的权限,如使用 "get"、"delete"、"update" 以及 "patch" 等动词的请求,将被限定到资源列表中所包含的资源实例上 + +例子: + +​ 如果需要限定一个角色绑定主体只能 "get" 或者 "update" 一个configmap时,可以定义以下角色 + +```shell +kind: Role +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + namespace: default + name: configmap-updater +rules: +- apiGroups: [""] + resources: ["configmap"] + resourceNames: ["my-configmap"] + verbs: ["update", "get"] +``` + +注意: + +​ 如果设置了resourceNames,则请求所使用的动词不能是list、watch、create或者deletecollection,由于资源名不会出现在create、list、watch和deletecollection等API请求的URL中,所以这些请求动词不会被设置了resourceNames 的规则所允许,因为规则中的resourceNames部分不会匹配这些请求 + +###### 角色定义的例子: + +​ 在以下示例中,仅截取展示了rules部分的定义: + +允许读取core API Group中定义的资源 "pods" + +```shell +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] +``` + +允许读写在 "extensions" 和 "apps" API Group中定义的 "deployments" + +```shell +rules: +- apiGroups: [""] + resources: ["deployments"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +``` + +允许读取 "pods" 以及读写 "jobs" + +```shell +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] +- apiGroups: ["batch", "extensions"] + resources: ["jobs"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +``` + +允许读取一个名为 "my-config" 的 ConfigMap 实例 + +```shell +rules: +- apiGroups: [""] + resources: ["configmaps"] + resourceNames: ["my-config"] + verbs: ["get"] +``` + +允许读取core API Group中的"nodes"资源,Node是集群级别资源,所以此ClusterRole定义需要与一个ClusterRoleBinding绑定才能有效 + +```shell +rules: +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] +``` + +允许对非资源endpoint "/healthz" 及其所有子路径的 "GET" 和 "POST" 请求 + +```shell +rules: +- nonResourceURLs: ["/healthz", "/healthz/*"]   # 在非资源URL中,'*'代表后缀通配符 + verbs: ["get", "post"] + +注意: + 此ClusterRole定义需要与一个ClusterRoleBinding绑定才能有效 +``` + +#### 7.对角色绑定主体(Subject)的引用 + +​ RoleBinding或者ClusterRoleBinding将角色绑定到角色绑定主体(Subject)。 角色绑定主体(kind指定)可以是用户组(Group)、用户(User)或者服务账户(Service Accounts) + +###### 用户: + +​ 由字符串表示 + +​ 纯粹的用户名,例如 "alice" + +​ 电子邮件风格的名字,如 "bob@example.com" + +​ 用字符串表示的数字id + +用户的产生: + +​ 由Kubernetes管理员配置认证模块以产生所需格式的用户名。对于用户名,RBAC授权系统不要求任何特定的格式 + +注意: + +​ 前缀system:是 为Kubernetes系统使用而保留的,所以管理员应该确保用户名不会意外地包含这个前缀 + +用户组的产生: + +​ Kubernetes中的用户组信息由授权模块提供。用户组与用户一样由字符串表示。Kubernetes对用户组 字符串没有格式要求,但前缀system:同样是被系统保留的 + +服务账户: + +​ 服务账户(serviceAccount)拥有包含 system:serviceaccount:前缀的用户名,并属于拥有system:serviceaccounts:前缀的用户组 + +###### 角色绑定例子: + +​ 以下示例中,仅截取展示了RoleBinding的subjects字段 + +一个名为"alice@example.com"的用户 + +```shell +subjects: +- kind: User + name: "alice@example.com" + apiGroup: rbac.authorization.k8s.io +``` + +一个名为"frontend-admins"的用户组 + +```shell +subjects: +- kind: Group + name: "frontend-admins" + apiGroup: rbac.authorization.k8s.io +``` + +kube-system命名空间中的默认服务账户 + +```shell +subjects: +- kind: ServiceAccount + name: default + namespace: kube-system +``` + +名为"qa"命名空间中的所有服务账户 + +```shell +subjects: +- kind: Group + name: system:serviceaccounts:qa + apiGroup: rbac.authorization.k8s.io +``` + +在集群中的所有服务账户 + +```shell +subjects: +- kind: Group + name: system:serviceaccounts + apiGroup: rbac.authorization.k8s.io +``` + +所有认证过的用户(version 1.5+) + +```shell +subjects: +- kind: Group + name: system:authenticated + apiGroup: rbac.authorization.k8s.io +``` + +所有未认证的用户(version 1.5+) + +```shell +subjects: +- kind: Group + name: system:unauthenticated + apiGroup: rbac.authorization.k8s.io +``` + +所有用户(version 1.5+) + +```shell +subjects: +- kind: Group + name: system:authenticated + apiGroup: rbac.authorization.k8s.io +- kind: Group + name: system:unauthenticated + apiGroup: rbac.authorization.k8s.io +``` + +#### 8.默认角色与默认角色绑定 + +​ API Server会创建一组默认的ClusterRole和ClusterRoleBinding对象。 这些默认对象中有许多包含system:前缀,表明这些资源由Kubernetes基础组件"拥有"。 对这些资源的修改可能导致非功能性集群(non-functional cluster) + +​ 比如:system:node ClusterRole对象。 这个角色定义了kubelets的权限。如果这个角色被修改,可能会导致kubelets无法正常工作 + +​ 所有默认的ClusterRole和ClusterRoleBinding对象都会被标记为kubernetes.io/bootstrapping=rbac-defaults + +​ 每次启动时,API Server都会更新默认ClusterRole所缺乏的各种权限,并更新默认ClusterRoleBinding所缺乏的各个角色绑定主体。 这种自动更新机制允许集群修复一些意外的修改。由于权限和角色绑定主体在新的Kubernetes释出版本中可能变化,这也能够保证角色和角色绑定始终保持是最新的 + +​ 如果需要禁用自动更新,请将默认ClusterRole以及ClusterRoleBinding的rbac.authorization.kubernetes.io/autoupdate 设置成为false。 请注意,缺乏默认权限和角色绑定主体可能会导致非功能性集群问题 + +​ 自Kubernetes 1.6+起,当集群RBAC授权器(RBAC Authorizer)处于开启状态时,可以启用自动更新功能 + +###### 命令行工具: + +​ 有两个kubectl命令可以用于在命名空间内或者整个集群内授予角色 + +```shell +[root@master ~]# kubectl create rolebinding +``` + +​ 在某一特定命名空间内授予Role或者ClusterRole + +示例如下: + +​ 在名为"acme"的命名空间中将admin ClusterRole授予用户"bob" + +```shell +[root@master ~]# kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme +``` + +​ 在名为"acme"的命名空间中将view ClusterRole授予服务账户"myapp" + +```shell +[root@master ~]# kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme +``` + +在整个集群中授予ClusterRole,包括所有命名空间,示例如下: + +​ 在整个集群范围内将cluster-admin ClusterRole授予用户"root" + +```shell + [root@master ~]# kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root +``` + +​ 在整个集群范围内将system:node ClusterRole授予用户"kubelet" + +```shell +[root@master ~]# kubectl create clusterrolebinding kubelet-node-binding --clusterrole=system:node --user=kubelet +``` + +​ 在整个集群范围内将view ClusterRole授予命名空间"acme"内的服务账户"myapp" + +```shell +[root@master ~]# kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp +``` + +#### 9.服务账户(Service Account)权限 + +​ 默认的RBAC策略将授予控制平面组件(control-plane component)、节点(node)和控制器(controller)一组范围受限的权限, 但对于"kube-system"命名空间以外的服务账户,则不授予任何权限(超出授予所有认证用户的发现权限) + +从最安全到最不安全可以排序以下方法: + +​ 对某一特定应用程序的服务账户授予角色(最佳实践) + +​ 要求应用程序在其pod规范(pod spec)中指定serviceAccountName字段,并且要创建相应服务账户(例如通过API、应用程序清单或者命令kubectl create serviceaccount等) + +###### 案例: + +​ 在"my-namespace"命名空间中授予服务账户"my-sa"只读权限 + +```shell +[root@master ~]# kubectl create rolebinding my-sa-view \ + --clusterrole=view \ + --serviceaccount=my-namespace:my-sa \ + --namespace=my-namespace +``` + +​ 换成yaml文件大概如下 + +```shell +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: my-sa-view + namespace: my-namespace +subjects: +- kind: ServiceAccount + name: my-sa + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: view #这里view为clusterrole名称,其中berbs需要给view + apiGroup: rbac.authorization.k8s.io +``` + +在某一命名空间中授予"default"服务账号角色 + +​ 如果一个应用程序没有在其pod规范中指定serviceAccountName,它将默认使用"default"服务账号 + +​ 注意:授予"default"服务账号的权限将可用于命名空间内任何没有指定serviceAccountName的pod + +例子: + +​ 下面的例子将在"my-namespace"命名空间内授予"default"服务账号只读权限 + +```shell +[root@master ~]# kubectl create rolebinding default-view \ + --clusterrole=view \ + --serviceaccount=my-namespace:default \ + --namespace=my-namespace +``` + +​ 目前,许多加载项(addon)作为"kube-system"命名空的"default"服务帐户运行。 要允许这些加载项使用超级用户访问权限,请将cluster-admin权限授予"kube-system"命名空间中的"default"服务帐户。 注意:启用上述操作意味着"kube-system"命名空间将包含允许超级用户访问API的秘钥 + +```shell +[root@master ~]# kubectl create clusterrolebinding add-on-cluster-admin \ +--clusterrole=cluster-admin \ +--serviceaccount=kube-system:default +``` + +为命名空间中所有的服务账号授予角色 + +​ 如果希望命名空间内的所有应用程序都拥有同一个角色,无论它们使用什么服务账户,可以为该命名空间的服务账户用户组授予角色 + +例子: + +​ 下面的例子将授予"my-namespace"命名空间中的所有服务账户只读权限 + +```shell +[root@master ~]# kubectl create rolebinding serviceaccounts-view \ +--clusterrole=view \ +--group=system:serviceaccounts:my-namespace \ +--namespace=my-namespace +``` + +## 二:RBAC应用 + +​ 创建k8s账号与RBAC授权使用 + +#### 创建账号 + +​ 创建私钥 + +```shell +[root@master ~]# (umask 077; openssl genrsa -out xingdian.key 2048) +``` + +​ 用此私钥创建一个csr(证书签名请求)文件 + +```shell +[root@master ~]# openssl req -new -key xingdian.key -out xingdian.csr -subj "/CN=xingdian" +[root@master ~]# openssl x509 -req -in xingdian.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out xingdian.crt -days 365 +``` + +​ 看证书内容 + +```shell +[root@master ~]# openssl x509 -in xingdian.crt -text -noout +[root@master ~]# kubectl config set-credentials xingdian --client-certificate=./xingdian.crt --client-key=./xingdian.key --embed-certs=true +``` + +​ 设置上下文(设置为k8s集群的用户) + +```shell +[root@master ~]# kubectl config set-context xingdian@kubernetes --cluster=kubernetes --user=xingdian +``` + +​ 查看当前的工作上下文 + +```shell +[root@master ~]# kubectl config view +``` + +​ 切换用户(切换上下文) + +```shell +[root@master ~]# kubectl config use-context xingdian@kubernetes +``` + +​ 验证是否已经切换到了新的上下文 + +```shell +[root@master ~]# kubectl config current-context +``` + +​ 测试(还未赋予权限) + +```shell +[root@master ~]# kubectl get pod +No resources found. +Error from server (Forbidden): pods is forbidden: User "wing" cannot list pods in the namespace "default" +``` + +#### 授权 + +​ K8S授权请求是http的请求 + +​ 对象URL格式: + +​ /apis/[GROUP]/[VERSION]/namespace/[NAMESPACE_NAME]/[KIND]/[OBJECT_ID] + +​ k8s授权方式分为: + +​ serviceaccount和自己签证ca证书的账号,及签证ca的用户组(group)上(授权给这个组的权限) + +​ role: + +​ 允许的操作,如get,list等 + +​ 允许操作的对象,如pod,svc等 + +​ rolebinding: + +​ 将哪个用户绑定到哪个role或clusterrole上 + +​ clusterrole:(集群角色) + +​ clusterrolebinding:(绑定到集群) + +​ 如果使用rolebinding绑定到role上,表示绑定的用户只能用于当前namespace的权限 + +###### 创建一个角色: + +​ 切回管理帐号先 + +```shell +[root@master ~]# kubectl config use-context kubernetes-admin@kubernetes +[root@master ~]# kubectl create role myrole --verb=get,list,watch --resource=pod,svc +``` + +​ 绑定用户xingdian,绑定role为myrole + +```shell +[root@master ~]# kubectl create rolebinding myrole-binding --role=myrole --user=xingdian +``` + +​ 切换用户 + +```shell +[root@master ~]# kubectl config use-context xingdian@kubernetes +Switched to context "xingdian@kubernetes". +``` + +​ 查看权限 + +​ 只授权了default名称空间pod和svc的get,list,watch权限 + +```shell +[root@master ~]# kubectl get pod +NAME READY STATUS RESTARTS AGE +nginx-pod 0/1 ImagePullBackOff 0 1h + +[root@master ~]# kubectl get pod -n kube-system #无权访问kube-system +No resources found. +Error from server (Forbidden): pods is forbidden: User "wing" cannot list pods in the namespace "kube-system" + +[root@master ~]# kubectl delete pod nginx-pod #无删除权限 +Error from server (Forbidden): pods "nginx-pod" is forbidden: User "wing" cannot delete pods in the namespace "default" +``` + +###### 创建clusterrole: + +​ 可以访问全部的namespace + +```shell +[root@master ~]# kubectl create clusterrole mycluster-role --verb=get,list,watch --resource=pod,svc +``` + +​ 删除xingdian账号之前绑定的rolebinding + +```shell +[root@master ~]# kubectl delete rolebinding myrole-binding +``` + +​ 使用clusterrolebinding绑定clusterrole + +```shell +[root@master ~]# kubectl create clusterrolebinding my-cluster-rolebinding --clusterrole=mycluster-role --user=xingdian +``` + +​ 切换账号 + +```shell +[root@master ~]# kubectl config use-context xingdian@kubernetes +``` + +​ 查看权限 查看kube-system空间的pod + +```shell +# kubectl get pod -n kube-system +NAME READY STATUS RESTARTS AGE +coredns-78fcdf6894-67h9h 1/1 Running 1 11h +coredns-78fcdf6894-lzxmz 1/1 Running 1 11h +etcd-k8s-m 1/1 Running 2 11h +...... +``` + + + + + + + + + + + + +