Kubernetes RBAC认证 ServiceAccount、Dashboard

Kubernetes Rbac Serviceaccount

Posted by BlueFat on Wednesday, October 28, 2020

简介

简介摘自Kubernetes权威指南

RBAC(Role-Based Access Control,基于角色的访问控制)在Kubernetes的1.5版本中引入,在1.6版本时升级为Beta版本,在1.8版本时升级为GA。作为kubeadm安装方式的默认选项,足见其重要程度。相对于其他访问控制方式,新的RBAC具有如下优势。

  • 对集群中的资源和非资源权限均有完整的覆盖。
  • 整个RBAC完全由几个API对象完成,同其他API对象一样,可以用kubectl或API进行操作
  • 可以在运行时调整,无须重新启动API Server

要想使用RBAC授权模式,需要在API Server的启动参数加上–authorization-mode=RBAC.

Kubernetes RBAC

RBAC概念

RBAC引入了4个新的顶级资源对象: Role, ClusterRole,RoleBinding和ClusterRoleBinding. 同其他API资源对象一样,用户可以使用kubectl 或者API调用等方式操作这些资源对象.

我们首先要明确下面三个概念

  • Role: 角色,它定义了一组规则,定义了一组对Kubernetes API对象的操作权限
  • Subject: 被作用者,既可以是User,Group或ServiceAccount(默认)
  • RoleBinding: 定义了”被作用者”和”角色”的绑定关系

RBAC API对象

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

资源对象(resources)

  • Pods, ConfigMaps, Deployments, Nodes, Secrets, Namespaces

资源对象操作(verbs)

  • create, get, delete, list, update, edit, watch, exec

这些资源和API Group进行关联,比如Pods属于Core API Group,而Deployment属于apps API Group, 要在kubernetes中进行RBAC授权

默认ClusterRole:

view:对全部或所选命名空间下大多数资源的只读权限。 edit:对全部或所选命名空间下多数资源的读写权限。当配置在全部命名空间时能力与运维权限一致。 admin:对全部命名空间下大多数资源的读写权限,对节点、存储卷,命名空间和配额管理的只读权限。 cluster-admin:对全部命名空间下所有资源的读写权限。

Role

Role 作用于指定的namespace,不能跨namespace. 若跨namespace需用ClusterRole.

Role只能对namespace内的资源进行授权,下面的例子中定义的角色具备读取Pod的权限

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: test
  name: test-role
rules:
- apiGroups: [""]  # ""空字符串,表示核心API群
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

参数说明:

# 如果没有设置namespace默认则是default
# apiGroups: 支持的API组列表,例如APIVersion: batch/v1、APIVersion: extensions:v1、apiVersion:apps/v1等
# resources: 支持的资源对象列表,例如pods,deployments,jobs等
# verbs: 对资源对象的操作方法列表,例如get,watch,list,delete,replace,patch等

# 这只是规则,需要绑定才生效

ClusterRole

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

  • 集群范围的资源,例如Node
  • 非资源型的路径,例如/healthz
  • 包含全部命名空间的资源,例如pods(用于kubectl get pods –all-namespaces)

下面的集群角色可以让用户有权访问任意一个或所有命名空间的secrets

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  # ClusterRole 不受限于命名空间,所以无需设置namespace的名称
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"] 

此外,kubernetes还提供了预先定义好的ClusterRole来提供用户直接使用

  • 如: cluster-admin, admin, edit, view
[root@k8s-master01 ~]# kubectl get clusterrole view -o yaml

[root@k8s-master01 ~]# 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
  ---------  -----------------  --------------  -----
  *.*        []                 []              [*]
             [*]                []              [*]

Rolebinding和ClusterRoleBinding

Rolebinding或ClusterRoleBinding绑定用来把一个角色绑定到一个目标上,绑定目标可以是User、Group或者Service Account。 使用RoleBinding引用Role为某个命名空间授权。 使用ClusterRoleBinding为集群范围内授权。

下面的例子中的RoleBinding将在default命名空间中把pod-reader角色授予用户jane,这一操作可以让jane读取default命名空间中的Pod:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: example-rolebinding
  namespace: default
subjects:
- kind: User
  name: youmen
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: example-role
  apiGroup: rbac.authorization.k8s.io

RoleBinding也可以引用ClusterRole,对属于同一命名空间内ClusterRole定义的资源主体进行授权。一种常见的做法是集群管理员为集群范围预先定义好一组角色(ClusterRole),然后在多个命名空间中重复使用这些ClusterRole。

使用RoleBinding绑定集群角色secret-reader,使dave只能读取development命名空间中的secret:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-secrets
  namespace: development
  # 集群角色中,dave用户只有development命名空间的权限
subjects:
- kind: User
  name: dave
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

对Resources的引用方式

Kubernetes API包含下级资源,例如Pod的日志(logs), Pod日志的Endpoint是GET/ api/v1/namespaces/{namespace}/pods/{name}/log。
若想获取下级资源,则使用斜线/ 如 “pods/log”

下面是授权让某个主体同时能够读取Pod和Pod log

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: test
  name: test-role
rules:
- apiGroups: [""]  # ""空字符串,表示核心API群
  resources: ["pods","pods/log"]
  verbs: ["get", "watch", "list"]

Resources还可以通过ResourceName进行引用。在指定ResourceName后,使用get、delete、update、patch操作请求,就会被限制在这个资源实例范围内。

例如下面的声明让一个主体只能对一个叫my-configmap的configmap进行get和update操作:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: configmap-updater
rules:
- apiGroups: [""]
  resources: ["configmap"]
  resourceNames: ["my-configmap"]
  verbs: ["update", "get"]

resourceName这种用法对list,watch,create或deletecollection的操作是无效的,这是因为必须要通过URL进行授权, 而resourceName在list,watch,create,delete,collection请求中只是请求Body数据的一部分.

常见Role实例

授权sunday用户对test命名空间pods和pogs/log权限

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: test
  name: pods-reader
rules:
- apiGroups: [""]
  resources: ["pods","pods/log"]
  verbs: ["get","list","watch"]

---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pods-read-test
  namespace: test
subjects:
- kind: User
  name: sunday
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pods-reader
  apiGroup: rbac.authorization.k8s.io

允许读取核心API组中的Pod资源

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

允许读写extensions和apps两个API组中的deployment资源

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

允许读取Pods及读写Jobs

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

允许读取一个名为my-config的ConfigMap(必须绑定到一个RoleBinding来限制到一个Namespace下的ConfigMap)

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

常用RoleBinding示例

用户名alice@example.com

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

组名frontend-admins

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

kube-system命名空间中的默认Service Account

subjects:
- kind: ServiceAccount
  name: default
  namespace: kube-system

test命名空间中的所有Service Account

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

所有Service Account

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

所有认证用户

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

所有未认证用户

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

ServiceAccount

ServiceAccount主要负责kubernetes内置用户,下面简单定义一个ServiceAccount

apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: mynamespace
  name: example-sa

创建Serviceaccount

---
apiVersion: v1
kind: Namespace
metadata:
  name: test
  labels:
    name: test

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: test
  name: role-test
rules:
- apiGroups: [""]
  resources: ["pods","pods/log"]

---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: rolebinding-test
  namespace: test
subjects:
- kind: ServiceAccount
  name: sa-test
  namespace: test
roleRef:
  kind: Role
  name: role-test
  apiGroup: rbac.authorization.k8s.io

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: sa-test
kubectl create serviceaccount sa-test -o yaml --dry-run > serviceaccount.yaml

Kubectl命令权限

# master
cd /etc/kubernetes/pki/      
(umask 077;openssl genrsa -out sunday.key 2048)
openssl  req -new -key sunday.key -out sunday.csr -subj "/CN=sunday"   
openssl x509 -req -in sunday.csr -CA ./ca.pem -CAkey ./ca-key.pem -CAcreateserial -out sunday.crt -days 365
# openssl x509 -in youmen.crt -text -noout 
# sunday用户下操作
useradd sunday
su - sunday
kubectl config set-cluster kubernetes --server="https://192.168.1.111:8443" --certificate-authority=/etc/kubernetes/pki/ca.pem --embed-certs=true
kubectl config set-credentials sunday --client-certificate=./sunday.crt --client-key=./sunday.key --embed-certs=true
kubectl config set-context sunday@kubernetes --cluster=kubernetes --user=sunday
kubectl config use-context sunday@kubernetes

# kubectl get pod
Error from server (Forbidden): pods is forbidden: User "youmen" cannot list resource "pods" in API group "" in the namespace "default"   
# master
kubectl create role pods-reader --verb=get,list,watch --resource=pods
kubectl create rolebinding sunday-pods-read --role=pods-reader --user=sunday

如查看其他namespace则无权限,因为role无法跨namespace,需使用clusterrole

[sunday@@k8s-master01 ~] kubectl get pods -n kube-system   
Error from server (Forbidden): pods is forbidden: User "sunday" cannot list resource "pods" in API group "" in the namespace "kube-system"   

创建clusterrole,可以访问全部的namespace

kubectl create clusterrole cluster-reader --verb=get,list,watch --resource=pods
kubectl create clusterrolebinding read-all-pods-sunday --clusterrole=cluster-reader --user=sunday  
kubectl create secret tls admin-certs --key admin-key.pem --cert admin.pem -n kubernetes-dashboard
kubectl get pod -n kubernetes-dashboard -l k8s-app=kubernetes-dashboard

dashboard_pod=`kubectl get pod -n kubernetes-dashboard -l k8s-app=kubernetes-dashboard --output=jsonpath={.items..metadata.name}`
kubectl get pod -n kubernetes-dashboard $dashboard_pod -o yaml > 1.yaml

Helm

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add stable  https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts/

kubectl port-forward –namespace kubeapps service/kubeapps 8080:80

参考

https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/rbac/. https://cloud.tencent.com/developer/article/1706581. https://jimmysong.io/kubernetes-handbook/concepts/rbac.html. https://www.cnblogs.com/RRecal/p/15747097.html. https://support.huaweicloud.com/usermanual-cce/cce_01_0189.html.