Skip to content

RBAC(基于角色的访问控制)

role/roleBingding

ClusterRole/ClusterRoleBingding

ServiceAccount

1. Kubernetes认证、授权与准入控制

1.1 认证基本概念

1.1.1 为什么需要验证

对于Kubernetes系统来说,,APIServer肯定不是任何人都能轻易访问的,如果任何人都能轻易的访问,意味着可以通过kubectl命令访问APIServer,进而操作Kubernetes。也就意味着它能够在我们的系统上随便部署应用程序,甚至还会删除我们正在运行的应用程序,这是非常危险的。所以我们需要对用户进行身份认证,确保身份是合法.

1.1.2 认证流程

任何客户端用户试图通过 APIServer操作资源对象时,它们必须经历多个阶段的访问控制,才会被接受处理,其中包含认证、授权以及准入控制

image-20240616184222954

1.认证:任何客户端访问,经过API操作之前,需要先完成认证操作,也就是进行身份认证;

2.授权:认证通过后仅代表它是一个合法的系统用户,但它是否拥有删除对应资源权限,需要进行授权检查

3.准入控制:虽然我们有了权限,也可以创建Pod等各种资源,但创建Pod是否能成功呢,假设ops名称空间限制最多创建2个Pod,目前已经有2个Pod了,那么这次的创建就会失败。

1.1.3 认证方式

UserAccount

使用kubectl创建资源,首先要进行客户端身份认证,所以客户端每次在请求APIServer时都会携带上数字证书,用于认证API-Server,当认证通过后,证书中的Subject将被识别为用户标识,其中的CN字段的值为用户名,字段O的值就是用户所属的组,例如:Subject:0=ops,CN=k8用户名为k8,用户的组为ops。

image-20240616185036588

ServiceAccount

有些情况下,我们希望在pod内部能够访问API-Server,获取集群的信息,甚至对集群进行改动。针对这种情况,kubernetes提供了一种特殊的认证方式:ServiceAccount。

默认情况下,创建的Pod如果没有指定ServiceAccount则系统会默认提供一个ServiceAccount,而后通过mount方式挂载到Pod的文件系统中(/var/run/secretes/kubernetes.io/serviceaccount/token),该ServiceAccount能通过DownWardAPI获取该Pod相关的一些元数据信息。当然也可以自行创建ServiceAccount来完成API-Server的身份认证,至于能否对集群进行改变,则需要看该ServiceAccount是否拥有权限。

image-20240616185404426

❌ 注意

  • 同一个命名空间下的多个pod可以使用同一个ServiceAccount
  • pod只能使用同一个命名空间下的ServiceAccount
  • 如果在pod的manifest文件中没有显示的指定ServiceAccount名称.则默认使用default ServiceAccount

1.2 RBAC授权

官当

1.2.0 如何开启RBAC

bash
grep -C3 'authorization-mode' /etc/kubernetes/manifests/kube-apiserver.yaml

 #- --feature-gates=RemoveSelfLink=false
    - --advertise-address=10.103.236.201
    - --allow-privileged=true
    - --authorization-mode=Node,RBAC
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --enable-admission-plugins=NodeRestriction
    - --enable-bootstrap-token-auth=true
grep -C3 'authorization-mode' /etc/kubernetes/manifests/kube-apiserver.yaml

 #- --feature-gates=RemoveSelfLink=false
    - --advertise-address=10.103.236.201
    - --allow-privileged=true
    - --authorization-mode=Node,RBAC
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --enable-admission-plugins=NodeRestriction
    - --enable-bootstrap-token-auth=true

API Server目前支持以下几种授权策略:

  • AlwaysDeny:表示拒绝所有请求,一般用于测试。
  • AlwaysAllow:允许接收所有请求。 如果集群不需要授权流程,则可以采用该策略,这也是Kubernetes的默认配置。
  • ABAC(Attribute-Based Access Control):基于属性的访问控制。 表示使用用户配置的授权规则对用户请求进行匹配和控制。
  • Webhook:通过调用外部REST服务对用户进行授权。
  • RBAC:Role-Based Access Control,基于角色的访问控制
  • Node:是一种专用模式,用于对kubelet发出的请求进行访问控制。

1.2.1 什么是RBAC

RBAC(RoleBasedAccessControl)基于角色的访问控制;其实就是将资源的操作权限授予给指定的角色,而后将用户加入该角色,那么该用户则拥有了对应角色的权限;

授权过程:

  1. 定义角色(Role and ClusterRole):在定义角色时会指定此角色对于资源访问控制的一系列规则;
  1. 定义主体("User", "Group" or "ServiceAccount"): 客户端标识;
  2. 绑定角色RoleBinding and ClusterRoleBinding:将主体与角色进行绑定,对用户进行访问授权。

image-20240712154756886

简单来说:

  • RBAC(Role-Based Access Control,基于角色的访问控制),允许通过Kubernetes API动态配置策略。
  • 角色
    • Role:授权特定命名空间的访问权限
    • ClusterRole:授权所有命名空间的访问权限
  • 角色绑定
    • RoleBinding:将角色绑定到主体(即subject)
    • ClusterRoleBinding:将集群角色绑定到主体
  • 主体(subject)
    • User:用户
    • Group:用户组
    • ServiceAccount:服务账号

1.2.2 RBAC角色与集群角色

Kubernetes系统的RBAC授权插件将角色分为了RoLe和CLusterRoLe两类:

  • RoLe:仅作用于名称空间级别,用于承载名称空间级别内的资源权限集合。
  • ClusterRole:作用于集群范围,能够同时承载名称空间和集群级别的资源权限集合。

Kubernetes利用RoleCLusterRoLe两类角色来赋予对应的权限,同时也需要用到另外两类资源RoLebindingCLusterRoLebinding来完成用户与角色之间的绑定关系;

1.2.3 Role

Role是一系列的权限的集合,在命名空间内定义的权限集合。它只能在指定的命名空间内生效。

例如一个Role可以包含读取 Pod 的权限和列出 Pod 的权限,Role只能授予单个 namespace 中资源的访问权限,比如:

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

参数解释:

# 首先,Role对象指定了它能产生作用的Namespace(mynamespace)。# Namespace是kubernetes项目中的一个逻辑管理单位。不同Namespace的API对象,
# 在通过kubectl命令进行操作的时候,是互相隔离的
# namespace并不会提供任何实际的隔离或者多租户能力,如果没有设置namespace默认则是default

# apiGroups: 支持的API组列表,例如"“apiVersion: batch/v1”“apiVersion: extensions:v1”“apiVersion: apps/v1”等”

# resources: 支持的资源对象列表,例如Pods,deployments,jobs等

# verbs: 对资源对象的操作方法列表,例如get,watch,list,delete,replace,patch等

# rules字段定义它的是权限规则,这条规则的含义就是允许"被作用者" ,对namespace下面Pod(resources中定义)有哪些权限;

# 用户的权限对应的API资源对象已经创建了,但是还没有绑定,也就是只有一个规则没有规定哪些用户有这个权限
# 首先,Role对象指定了它能产生作用的Namespace(mynamespace)。# Namespace是kubernetes项目中的一个逻辑管理单位。不同Namespace的API对象,
# 在通过kubectl命令进行操作的时候,是互相隔离的
# namespace并不会提供任何实际的隔离或者多租户能力,如果没有设置namespace默认则是default

# apiGroups: 支持的API组列表,例如"“apiVersion: batch/v1”“apiVersion: extensions:v1”“apiVersion: apps/v1”等”

# resources: 支持的资源对象列表,例如Pods,deployments,jobs等

# verbs: 对资源对象的操作方法列表,例如get,watch,list,delete,replace,patch等

# rules字段定义它的是权限规则,这条规则的含义就是允许"被作用者" ,对namespace下面Pod(resources中定义)有哪些权限;

# 用户的权限对应的API资源对象已经创建了,但是还没有绑定,也就是只有一个规则没有规定哪些用户有这个权限

1.2.4 ClusterRole

ClusterRole授权 >= Role授予(与Role类似),但ClusterRole属于集群级别对象,可以在整个集群范围内生效。

yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]
bash
#默认 获取 ClusterRole
kubectl get clusterroles --namespace=kube-system
#默认 获取 ClusterRole
kubectl get clusterroles --namespace=kube-system
bash
[root@kube-master manifests]#  kubectl describe clusterrole cluster-admin -n kube-system
Name:         cluster-admin
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  *.*        []                 []              [*]
             [*]                []              [*]
[root@kube-master manifests]#  kubectl describe clusterrole cluster-admin -n kube-system
Name:         cluster-admin
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  *.*        []                 []              [*]
             [*]                []              [*]

1.2.5 RoleBinding

将 Role 与一个或多个用户、组或服务账户绑定,赋予在特定命名空间内的权限。

比如以下 RoleBinding 是将 default 命名空间的 pod-reader Role 授予 bmw 用户,此后 bmw 用户在 default 命名空间中将具有 pod-reader 的权限

yaml
# This role binding allows "bmw" to read pods in the "default" namespace.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User  # May be "User", "Group" or "ServiceAccount"
  name: bmw
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
# This role binding allows "bmw" to read pods in the "default" namespace.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User  # May be "User", "Group" or "ServiceAccount"
  name: bmw
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
  • kubectl
bash
$ kubectl create rolebinding read-pods --role=pod-reader --user=bmw --namespace=default
$ kubectl  get rolebindings.rbac.authorization.k8s.io  -o wide
其它类似 subjects:
$ kubectl create rolebinding read-pods-svc --role=pod-reader --serviceaccount=default:bmw-svc --namespace=default
$ kubectl create rolebinding read-pods-group --role=pod-reader --group=bmw-group --namespace=default
$ kubectl create rolebinding read-pods --role=pod-reader --user=bmw --namespace=default
$ kubectl  get rolebindings.rbac.authorization.k8s.io  -o wide
其它类似 subjects:
$ kubectl create rolebinding read-pods-svc --role=pod-reader --serviceaccount=default:bmw-svc --namespace=default
$ kubectl create rolebinding read-pods-group --role=pod-reader --group=bmw-group --namespace=default

1.2.6 ClusterRoleBinding

ClusterRoleBinding 适用于集群范围内的授权,也就是说可以跨namespace

比如以下 ClusterRoleBinding 是将 bmw 用户在任意namespace中都具有 pod-reader 的权限:

yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods-global
subjects:
- kind: User
  name: bmw
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-pod-reader
  apiGroup: rbac.authorization.k8s.io
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods-global
subjects:
- kind: User
  name: bmw
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-pod-reader
  apiGroup: rbac.authorization.k8s.io
  • kubectl
bash
$ kubectl create clusterrolebinding read-pods-global --clusterrole=cluster-pod-reader --user=bmw
$ kubectl  get clusterrolebindings.rbac.authorization.k8s.io  -o wide
$ kubectl create clusterrolebinding read-pods-global --clusterrole=cluster-pod-reader --user=bmw
$ kubectl  get clusterrolebindings.rbac.authorization.k8s.io  -o wide

1.2.7 ServiceAccount

一种特殊的 Kubernetes 账户,通常用于容器或应用程序访问 Kubernetes API。

1.3 RBAC权限定义

bash
1. apiGroups: 指定哪个 API 组下的权限,比如:apps,可以使用该命令获取apiGroups,如果为空字符串,代表就是core下的api: kubectl api-resources -o wide

2. resources: 该apiGroups组下具体资源,比如 pod,service,secret 

3. verbs: 指对该资源具体执行哪些动作,如 get, delete,list 
1. apiGroups: 指定哪个 API 组下的权限,比如:apps,可以使用该命令获取apiGroups,如果为空字符串,代表就是core下的api: kubectl api-resources -o wide

2. resources: 该apiGroups组下具体资源,比如 pod,service,secret 

3. verbs: 指对该资源具体执行哪些动作,如 get, delete,list 

1.3.1 系统预定义角色

Kubernetes有一个很基本的特性就是它的所有资源都是模型化的API对象,允许执行CRUD(Create、Read、Update、Delete)操作。资源如下

# Pods
# ConfigMaps
# Deployments
# Nodes
# Secrets
# Namespaces

# 资源对象可能存在的操作有如下
# create
# get
# delete
# list
# update
# edit
# watch
# exec
# Pods
# ConfigMaps
# Deployments
# Nodes
# Secrets
# Namespaces

# 资源对象可能存在的操作有如下
# create
# get
# delete
# list
# update
# edit
# watch
# exec
  • 通过命令查看
bash
kubectl get role -n kube-system
kubectl get clusterrole
kubectl get rolebinding -n kube-system
kubectl get clusterrolebinding

 kubectl get clusterrole view -o yaml
kubectl get role -n kube-system
kubectl get clusterrole
kubectl get rolebinding -n kube-system
kubectl get clusterrolebinding

 kubectl get clusterrole view -o yaml

1.4 涉及命令

bash
#查看上下文
[root@kube-master manifests]# kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin

#切换
kubectl  config use-context  name

#返回生成 kubeconfig 条目所针对的所有集群的列表
kubectl config view


#1.创建role
kubectl create role pod-reader --verb=get,list --resource=pods --namespace=development

#2.创建ClusterRole:创建集群范围内的角色
kubectl create clusterrole pod-admin --verb=get,list,create,delete --resource=pods

#3.创建RoleBinding:将Role绑定给特定用户或服务账户
kubectl create rolebinding read-pods --role=pod-reader --user=johndoe --namespace=development

#4.创建ClusterRoleBinding:将ClusterRole绑定到用户,授予其集群范围的权限
kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=admin-user

#查看
#查看Role:列出命名空间中的所有角色
kubectl get roles --namespace=development

#查看RoleBinding:查看所有角色绑定
kubectl get rolebindings --namespace=development

#查看ClusterRole和ClusterRoleBinding:查看集群范围的角色和角色绑定
kubectl get clusterroles
kubectl get clusterrolebindings

#生成yaml文件
kubectl create role han --namespace monitor --verb=get,list,watch --resource=pods -o yaml
#查看上下文
[root@kube-master manifests]# kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin

#切换
kubectl  config use-context  name

#返回生成 kubeconfig 条目所针对的所有集群的列表
kubectl config view


#1.创建role
kubectl create role pod-reader --verb=get,list --resource=pods --namespace=development

#2.创建ClusterRole:创建集群范围内的角色
kubectl create clusterrole pod-admin --verb=get,list,create,delete --resource=pods

#3.创建RoleBinding:将Role绑定给特定用户或服务账户
kubectl create rolebinding read-pods --role=pod-reader --user=johndoe --namespace=development

#4.创建ClusterRoleBinding:将ClusterRole绑定到用户,授予其集群范围的权限
kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=admin-user

#查看
#查看Role:列出命名空间中的所有角色
kubectl get roles --namespace=development

#查看RoleBinding:查看所有角色绑定
kubectl get rolebindings --namespace=development

#查看ClusterRole和ClusterRoleBinding:查看集群范围的角色和角色绑定
kubectl get clusterroles
kubectl get clusterrolebindings

#生成yaml文件
kubectl create role han --namespace monitor --verb=get,list,watch --resource=pods -o yaml

1.5 实践

假如我们想给用户 bmw 开通一个只可以查看集群中default namespace中的 pods,services 权限,该如何实现呢?一般分如下几个步骤

bash
1. 定义个角色(Role/ClusterRole),角色包含资源(resources)和动作(verbs)
2. 分别以 User,Group, ServiceAccount 模式定义一个主体
3. 定义一个 (RoleBinding/ClusterRoleBinding), 把 subjects 与 Role/ClusterRole 进行关联
4. 配置 kubeconfig,使用 kubectl 验证
1. 定义个角色(Role/ClusterRole),角色包含资源(resources)和动作(verbs)
2. 分别以 User,Group, ServiceAccount 模式定义一个主体
3. 定义一个 (RoleBinding/ClusterRoleBinding), 把 subjects 与 Role/ClusterRole 进行关联
4. 配置 kubeconfig,使用 kubectl 验证

1.创建role

yaml
# bmw-svc-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - pods/status
  - pods/log
  - services
  - services/status
  - endpoints
  - endpoints/status
  verbs:
  - get
  - list
  - watch
# bmw-svc-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - pods/status
  - pods/log
  - services
  - services/status
  - endpoints
  - endpoints/status
  verbs:
  - get
  - list
  - watch

2.serviceAccount

$ kubectl create serviceaccount bmw-svc
$ kubectl  get sa bmw-svc -o yaml
$ kubectl  get secrets bmw-svc-token-8f9js -o yaml
$ kubectl create serviceaccount bmw-svc
$ kubectl  get sa bmw-svc -o yaml
$ kubectl  get secrets bmw-svc-token-8f9js -o yaml

3.创建角色绑定

yaml
# bmw-svc-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: bmw-svc-role
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: bmw-svc-role
subjects:
- kind: ServiceAccount
  name: bmw-svc
  namespace: default
# bmw-svc-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: bmw-svc-role
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: bmw-svc-role
subjects:
- kind: ServiceAccount
  name: bmw-svc
  namespace: default

4.修改config view

bash
#kubectl config view

...
- context:
    cluster: kubernetes
    user: bmw-svc
  name: bmw-svc
- context:
    cluster: kubernetes
    user: admin
  name: kubernetes
...
users:
- name: admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: bmw-svc
  user:
    token: xxxx
#kubectl config view

...
- context:
    cluster: kubernetes
    user: bmw-svc
  name: bmw-svc
- context:
    cluster: kubernetes
    user: admin
  name: kubernetes
...
users:
- name: admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: bmw-svc
  user:
    token: xxxx
  1. 查看上下文
bash
[root@kube-master manifests]# kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin

[root@kube-master manifests]# kubectl config get-users
NAME
kubernetes-admin

[root@kube-master manifests]# kubectl config get-clusters
NAME
kubernetes

#切换context:
$ kubectl  config use-context bmw-svc
[root@kube-master manifests]# kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin

[root@kube-master manifests]# kubectl config get-users
NAME
kubernetes-admin

[root@kube-master manifests]# kubectl config get-clusters
NAME
kubernetes

#切换context:
$ kubectl  config use-context bmw-svc

role实践2

  1. 创建命名空间
kubectl create namespace test-namespace
kubectl create namespace test-namespace
  1. 创建 Role

创建一个 Role,允许在 test-namespace 命名空间中查看 Pods 和 Services

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: test-namespace
  name: viewer-role
rules:
  - apiGroups: [""]
    resources: ["pods", "services"]
    verbs: ["get", "list"]
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: test-namespace
  name: viewer-role
rules:
  - apiGroups: [""]
    resources: ["pods", "services"]
    verbs: ["get", "list"]
kubectl apply -f viewer-role.yaml
kubectl apply -f viewer-role.yaml
  1. 创建 ServiceAccount

创建一个 ServiceAccount,命名为 viewer-sa,用于测试授权效果

kubectl -n test-namespace create serviceaccount viewer-sa
kubectl -n test-namespace create serviceaccount viewer-sa
  1. 创建 RoleBinding

将 Role viewer-role 绑定到 ServiceAccount viewer-sa

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: viewer-rolebinding
  namespace: test-namespace
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: viewer-role
subjects:
  - kind: ServiceAccount
    name: viewer-sa
    namespace: test-namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: viewer-rolebinding
  namespace: test-namespace
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: viewer-role
subjects:
  - kind: ServiceAccount
    name: viewer-sa
    namespace: test-namespace
kubectl apply -f viewer-rolebinding.yaml
kubectl apply -f viewer-rolebinding.yaml
  1. 验证权限

使用 kubectl auth can-i 命令验证 viewer-sa 是否可以查看 Pods 和 Services

bash
kubectl -n test-namespace auth can-i get pods --as=system:serviceaccount:test-namespace:viewer-sa

kubectl -n test-namespace auth can-i list services --as=system:serviceaccount:test-namespace:viewer-sa
kubectl -n test-namespace auth can-i get pods --as=system:serviceaccount:test-namespace:viewer-sa

kubectl -n test-namespace auth can-i list services --as=system:serviceaccount:test-namespace:viewer-sa

cluster实践3

  1. 创建 ClusterRole
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: viewer-clusterrole
rules:
  - apiGroups: [""]
    resources: ["pods", "services"]
    verbs: ["get", "list"]
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: viewer-clusterrole
rules:
  - apiGroups: [""]
    resources: ["pods", "services"]
    verbs: ["get", "list"]
kubectl apply -f viewer-clusterrole.yaml
kubectl apply -f viewer-clusterrole.yaml
  1. 创建 ClusterRoleBinding

将 ClusterRole viewer-clusterrole 绑定到 viewer-sa

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: viewer-clusterrolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: viewer-clusterrole
subjects:
  - kind: ServiceAccount
    name: viewer-sa
    namespace: test-namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: viewer-clusterrolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: viewer-clusterrole
subjects:
  - kind: ServiceAccount
    name: viewer-sa
    namespace: test-namespace
kubectl apply -f viewer-clusterrolebinding.yaml
kubectl apply -f viewer-clusterrolebinding.yaml

2. 推荐配置

访问资源角色类型绑定类型
集群级别的资源(Nodes,PersistentVolumes,……)ClusterRoleClusterRoleBinding
非资源URL(/api,/healthz……)ClusterRoleClusterRoleBinding
在任何名称空间中的资源(跨所有名称空间的资源)ClusterRoleClusterRoleBinding
具体名称空间中的资源(在多个名称空间中重用这个相同的ClusterRoleClusterRoleRoleBinding
在具体名称空间中的资源(Role必须在每个名称空间中定义)RoleRoleBinding

2.1 总结

bash
#创建ServiceAccount
kubectl create serviceaccount 服务账号名 

#将ServiceAccount分配给pod
在pod的manifest配置文件中指定ServiceAccount名:
serviceAccountName: 服务账号名

#RBAC4种角色资源
Role: 常规角色.定义了对某个资源具有某种访问权限
RoleBinding: 常规角色绑定.定义了该角色绑定到哪个主体
ClusterRole: 集群角色.同上
ClusterRoleBinding: 集群角色绑定.同上

区别在于:
常规角色和集群角色绑定作用于某个名称空间下.
集群角色和集群角色绑定作用于整个集群,不受限于任何名称空间
#创建ServiceAccount
kubectl create serviceaccount 服务账号名 

#将ServiceAccount分配给pod
在pod的manifest配置文件中指定ServiceAccount名:
serviceAccountName: 服务账号名

#RBAC4种角色资源
Role: 常规角色.定义了对某个资源具有某种访问权限
RoleBinding: 常规角色绑定.定义了该角色绑定到哪个主体
ClusterRole: 集群角色.同上
ClusterRoleBinding: 集群角色绑定.同上

区别在于:
常规角色和集群角色绑定作用于某个名称空间下.
集群角色和集群角色绑定作用于整个集群,不受限于任何名称空间

3.RBAC案例

角色(权限的集合)

  • Role:授权特定命名空间的访问权限
  • ClusterRole:授权所有命名空间的访问权限(集群角色)

角色绑定

  • RoleBinding:将角色(Role)绑定到主体(即subject)
  • ClusterRoleBinding:将集群角色(ClusterRole)绑定到主体

主体(subject)

  • User:用户
  • Group:用户组
  • ServiceAccount:服务账号
bash
Role ---> RoleBinding ---> User/Group/ServiceAccount
ClusterRole ---> ClusterRoleBinding ---> User/Group/ServiceAccount

#将准备要设置赋予的权限,放到角色(Role/ClusterRole)里,
#通过角色绑定(RoleBinding/ClusterRoleBinding)
#将权限放在绑定到主体(User/Group/ServiceAccount)上
Role ---> RoleBinding ---> User/Group/ServiceAccount
ClusterRole ---> ClusterRoleBinding ---> User/Group/ServiceAccount

#将准备要设置赋予的权限,放到角色(Role/ClusterRole)里,
#通过角色绑定(RoleBinding/ClusterRoleBinding)
#将权限放在绑定到主体(User/Group/ServiceAccount)上

3.1 部署cfssl

为 Han用户授权 nginx 命名空间的 Pod 读取权限

1.创建CA证书签名请求文件

bash
cat > han-ca-csr.json << EOF
{
  "CN": "han",
  "hosts": [],
  "key": { 
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",    
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF
# "CN: feiyi": Common Name,feiyi作为之后要授权的用户
# C: 国家 ST: 州/省 L: 地区/城市 
# O: Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group),也就是feiyi用户所属的组,之后也可给该组授权
# OU: 组织单位名称,公司部门
cat > han-ca-csr.json << EOF
{
  "CN": "han",
  "hosts": [],
  "key": { 
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",    
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF
# "CN: feiyi": Common Name,feiyi作为之后要授权的用户
# C: 国家 ST: 州/省 L: 地区/城市 
# O: Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group),也就是feiyi用户所属的组,之后也可给该组授权
# OU: 组织单位名称,公司部门

2. 部署k8s使用当时生成CA 签发证书

bash
cfssl gencert \
-ca=/etc/kubernetes/pki/ca.crt \
-ca-key=/etc/kubernetes/pki/ca.key \
-config=ca-config.json \
-profile=kubernetes han-ca-csr.json | cfssljson -bare han

# -ca: 指定k8s的ca文件所在位置
# -ca-key: 指定k8s的ca密钥文件所在位置
# -config: 指定刚刚创建好的CA-config.json文件
# -profile: 指定ca-config.json中的profile---kubernetes
# cfssljson -bare han:将以上信息解析,生成以han为前缀的证书文件
cfssl gencert \
-ca=/etc/kubernetes/pki/ca.crt \
-ca-key=/etc/kubernetes/pki/ca.key \
-config=ca-config.json \
-profile=kubernetes han-ca-csr.json | cfssljson -bare han

# -ca: 指定k8s的ca文件所在位置
# -ca-key: 指定k8s的ca密钥文件所在位置
# -config: 指定刚刚创建好的CA-config.json文件
# -profile: 指定ca-config.json中的profile---kubernetes
# cfssljson -bare han:将以上信息解析,生成以han为前缀的证书文件

新增三个文件

bash
han-key.pem  # ca的私钥
han.pem      # ca证书
han.csr      # 签署请求
han-key.pem  # ca的私钥
han.pem      # ca证书
han.csr      # 签署请求

3.2 创建kubeconfig 授权文件

在创建完集群后,会让你执行如下命令

bash
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
  • 把集群信息写入kubeconfig文件
bash
# 因为创建的kubeconfig也将作用于K8S集群,所以需要指定K8S的API信息
kubectl config set-cluster kubernetes \
  --certificate-authority=/etc/kubernetes/pki/ca.crt \
  --embed-certs=true \
  --server=https://192.168.1.11:6443 \
  --kubeconfig=han.kubeconfig
  
# --certificate-authority:ca证书
# --server:apiserver地址
# --kubeconfig:根据给定的信息生成的kubeconfig名字
# --embed-certs:为true时,将证书信息写入kubeconfig文件;为false时,在kubeconfig文件中引用证书所在路径  

################################################################
# 这一步主要生成了以下信息
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0t
...
ejhKYld1OHY3WmI4TVR2MG9GVQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://192.168.1.11:6443
  name: kubernetes
# 因为创建的kubeconfig也将作用于K8S集群,所以需要指定K8S的API信息
kubectl config set-cluster kubernetes \
  --certificate-authority=/etc/kubernetes/pki/ca.crt \
  --embed-certs=true \
  --server=https://192.168.1.11:6443 \
  --kubeconfig=han.kubeconfig
  
# --certificate-authority:ca证书
# --server:apiserver地址
# --kubeconfig:根据给定的信息生成的kubeconfig名字
# --embed-certs:为true时,将证书信息写入kubeconfig文件;为false时,在kubeconfig文件中引用证书所在路径  

################################################################
# 这一步主要生成了以下信息
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0t
...
ejhKYld1OHY3WmI4TVR2MG9GVQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://192.168.1.11:6443
  name: kubernetes
  • 客户端信息写入 kubeconfig

bash
kubectl config set-credentials han \
  --client-key=han-key.pem \
  --client-certificate=han.pem \
  --embed-certs=true \
  --kubeconfig=han.kubeconfig
  
# set-credentials: 在 kubeconfig 中设置用户条目
# --client-key: 指定刚才生成私钥
# --client-certificate=han.pem: 指定生成的数字证书
# --kubeconfig: 将客户端信息加入刚才生成的kubeconfig文件中

################################################################
# 这一步主要生成了以下信息
users:
- name: han
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0
...
Si8rbHRhdXM4UWFRVmhCOHlndz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    client-key-data: LS0tLS1CRUdJTi BSU0EgUFJJVkFURSBLRVktLS0tLQp
... 
ck9xK0pFdDJDNGpidmh0Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
kubectl config set-credentials han \
  --client-key=han-key.pem \
  --client-certificate=han.pem \
  --embed-certs=true \
  --kubeconfig=han.kubeconfig
  
# set-credentials: 在 kubeconfig 中设置用户条目
# --client-key: 指定刚才生成私钥
# --client-certificate=han.pem: 指定生成的数字证书
# --kubeconfig: 将客户端信息加入刚才生成的kubeconfig文件中

################################################################
# 这一步主要生成了以下信息
users:
- name: han
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0
...
Si8rbHRhdXM4UWFRVmhCOHlndz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    client-key-data: LS0tLS1CRUdJTi BSU0EgUFJJVkFURSBLRVktLS0tLQp
... 
ck9xK0pFdDJDNGpidmh0Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
  • 上下文信息写入 kubeconfig

设置默认上下文加入 kubeconfig:如果存在多套集群,通过设置上下文可以在多套集群间切换

kubectl config set-context kubernetes \
  --cluster=kubernetes \
  --user=han \
  --kubeconfig=han.kubeconfig 
  
# set-context: 设置上下文,默认在名为kubernetes的集群
# --user=han: 使用客户端用户为han
# --cluster=kubernetes: 用户作用到名为kubernetes的集群
# --kubeconfig:将上下文信息加入刚才生成的kubeconfig文件中

################################################################
# 这一步主要生成了以下信息,表示使用feiyi用户访问集群kubernetes
contexts:
- context:
    cluster: kubernetes
    user: han
  name: kubernetes
kubectl config set-context kubernetes \
  --cluster=kubernetes \
  --user=han \
  --kubeconfig=han.kubeconfig 
  
# set-context: 设置上下文,默认在名为kubernetes的集群
# --user=han: 使用客户端用户为han
# --cluster=kubernetes: 用户作用到名为kubernetes的集群
# --kubeconfig:将上下文信息加入刚才生成的kubeconfig文件中

################################################################
# 这一步主要生成了以下信息,表示使用feiyi用户访问集群kubernetes
contexts:
- context:
    cluster: kubernetes
    user: han
  name: kubernetes

3.3 验证

bash
kubectl get node -n nginx --kubeconfig=han.kubeconfig

Error from server (Forbidden): pods is forbidden: User "han" cannot list resource "pods" in API group "" in the namespace "nginx"
#这是因为现在生成的 kubeconfig 还没有任何权限,所以任何资源还无法访问
kubectl get node -n nginx --kubeconfig=han.kubeconfig

Error from server (Forbidden): pods is forbidden: User "han" cannot list resource "pods" in API group "" in the namespace "nginx"
#这是因为现在生成的 kubeconfig 还没有任何权限,所以任何资源还无法访问

3.4 创建 RBAC 权限策略

仅给予查看 default命名空间的 pod 资源

bash
$ vim han-rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default  # 将权限给到nginx命名空间
  name: rbac-test
rules:
- apiGroups: [""] # 如果为空,则代表核心组(一般不指定),可以指定多个
  resources: ["pods"] # 仅允许该role对pod操作,可以指定多个
  verbs: ["get", "watch", "list"] # 对pod 所作的操作
---
# 将role绑定到user
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: default
  name: rbac-test-binding
subjects:
- kind: User
  name: han  # 该名为生成证书时的CN名字
  apiGroup: rbac.authorization.k8s.io
roleRef:  # 指定上面创建的Role与han绑定
  kind: Role
  name: rbac-test
  apiGroup: rbac.authorization.k8s.io
$ vim han-rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default  # 将权限给到nginx命名空间
  name: rbac-test
rules:
- apiGroups: [""] # 如果为空,则代表核心组(一般不指定),可以指定多个
  resources: ["pods"] # 仅允许该role对pod操作,可以指定多个
  verbs: ["get", "watch", "list"] # 对pod 所作的操作
---
# 将role绑定到user
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: default
  name: rbac-test-binding
subjects:
- kind: User
  name: han  # 该名为生成证书时的CN名字
  apiGroup: rbac.authorization.k8s.io
roleRef:  # 指定上面创建的Role与han绑定
  kind: Role
  name: rbac-test
  apiGroup: rbac.authorization.k8s.io
  • 执行
bash
kubectl apply -f han-rbac.yaml
kubectl apply -f han-rbac.yaml

文档参考

https://learnk8s.io/rbac-kubernetes#rbac-in-kubernetes

http://docs.kubernetes.org.cn/148.html