1 ControllingAccess访问控制简介

Controlling Access,即Kubernetes API的访问控制,它属于Kubernetes的Security安全大类。我们前面经常用到的kubectl,以及下一章要讲的Dashboard,都是在向Kubernetes API Server发送请求,由API Server进行一系列处理后将结果返回kubectl或Dashboard。为避免不可信客户端发起API Server访问请求,Kubernetes在API访问过程中引入了Controlling Access访问控制机制。

2 Kubernetes API Server和访问控制

API Server是Kubernetes集群中的核心组件之一,它负责接收客户端的请求,处理这些请求,并将结果返回给客户端。这里的客户端,可以是kubectl这种命令行工具,可以是调用API Server库的程序,也可以是调用REST请求的程序(如Dashboard或curl)。REST API访问的主体可以是用户(human users)或服务账号(Kubernetes service accounts)。

2.1 API Server主要功能

API Server的主要功能如下:

功能 说明
REST接口 提供HTTPS+JSON/YAML接口(/api/v1/…),供kubectl、Dashboard、Operator调用。
认证&授权 验证证书/BearerToken/WebHook,然后走RBAC/WebHook决定能否操作。
准入控制 Admission Controller链(Mutating/Validating)在写入etcd前做校验/修改。
总调度器 kube-scheduler是API Server的一个插件,API Server把待调度资源推给scheduler,再把结果写回。
etcd前端 与etcd后端交互的组件,其他组件通过API Server间接读写集群状态。

2.2 API Server常用访问路径

(1) 核心 API(/api/v1)

功能 子路径
Pod 列表 /api/v1/namespaces/{ns}/pods
单 Pod /api/v1/namespaces/{ns}/pods/{name}
Pod 日志 /api/v1/namespaces/{ns}/pods/{name}/log
Pod exec /api/v1/namespaces/{ns}/pods/{name}/exec
Service 列表 /api/v1/namespaces/{ns}/services
ConfigMap /api/v1/namespaces/{ns}/configmaps
Namespace 列表 /api/v1/namespaces
Node 列表 /api/v1/nodes

(2) 命名空间外(集群级)

功能 子路径
集群健康 /api/v1/healthz
metrics /metrics
版本信息 /version

(3) API 组(/apis/<group><version>)

功能 子路径
Deployment /apis/apps/v1/namespaces/{ns}/deployments
Job /apis/batch/v1/namespaces/{ns}/jobs
CustomResource /apis/<group>/<version>/namespaces/{ns}/<plural>

(4) 子资源(功能级)

功能 子路径
Pod exec /api/v1/namespaces/{ns}/pods/{name}/exec
Pod logs /api/v1/namespaces/{ns}/pods/{name}/log
Pod port-forward /api/v1/namespaces/{ns}/pods/{name}/portforward
Status /api/v1/namespaces/{ns}/pods/{name}/status

(5) 节点代理

功能 子路径
节点 Pod列表 /api/v1/proxy/nodes/{node}/pods
节点 stats /api/v1/proxy/nodes/{node}/stats
节点 exec /api/v1/proxy/nodes/{node}/exec

2.3 API Server请求的访问控制流程

当API Server收到一个请求时(以kubectl为例,其他客户端也一样),将执行如下处理流程:

kubectl -> HTTPS -> API Server -> 认证 -> 授权 -> 准入 -> etcd -> 返回结果

在这个调用链中,HTTPS属于HTTP协议本身的认证,etcd属于访问控制后的业务逻辑单元,不算是K8s的访问控制。
K8s的访问控制为认证(Authentication)、授权(Authorization)和准入(Admission Control)这三个阶段。

注意,K8s的认证、授权、准入虽然三个字母都是A开头,但和计算机网络安全3A还是不同的(3A概念:认证Authentication、授权Authentication、审计Audit),不要搞混。

2.4 认证(Authentication)

在TLS连接建立后,会进行认证处理,如果请求认证失败,会拒绝该请求并返回401错误码;如果认证成功,将进行到鉴权的部分。
Kubernetes支持的客户端认证方式有很多,例如:x509客户端证书、Bearer Token、基于用户名密码的认证、OpenID认证等。其中x509客户端证书和Bear Token我们本章会用到。

2.5 授权(Authorization)

认证通过后仅代表客户端被API Server信任,能访问到API Server,但客户端是否拥有操作资源对象的权限,还需要进行授权操作。
Kubernetes支持多种授权模式,如ABAC模式,RBAC模式和Webhook模式等。
这几种模式中最常见的是RBAC,它也是K8s默认使用的授权模式,本章后面会详细介绍。
在创建集群时,可以直接为kube-apiserver传递参数(如:–authorization-mode=RBAC)配置授权模式。

2.6 准入控制(Admission Control)

发往API Server的请求,在通过认证和授权后,将会准备创建资源对象并写入etdc进行持久化存储。
在进行资源对象创建前,Kubernetes提供了一种Webhook机制,可以让资源对象被持久化前任意修改资源对象并进行自定义的校验,这就是准入控制。
准入控制有多种控制策略,不同的策略代表着对请求的不同处理,即使前面的认证和授权都通过了,但是准入策略配置了拒绝该请求也是会被立马拒绝。以下是最常用的三种策略:

  • Always:允许所有的请求
  • AlwaysPullmages:在启动容器之前总是尝试重新下载镜像
  • AlwaysDeny:禁止所有请求

准入通过准入控制器(Admission Controller)起作用,准入控制器在API请求到达API服务器之前拦截它们,并根据一系列的策略和规则来决定是否允许这些请求通过,常用于验证配置的正确性、修改 API 对象、记录日志等。
Kubernetes提供了一些内置的Admission Controller,如:

  • NamespaceLifecycle:确保命名空间的存在性。
  • LimitRanger:确保请求不会超过设置的资源限制。
  • ResourceQuota:确保请求不会超过设置的资源配额。
  • DefaultStorageClass:为持久卷设置默认的存储类。
  • ValidatingAdmissionWebhook:允许通过Webhook的方式自定义验证资源对象是否符合规则。
  • MutatingAdmissionWebhook:允许通过Webhook的方式自定义修改资源对象并验证是否符合规则。

3 RBAC授权模式

在Kubernetes中,RBAC(Role-Based Access Control,基于角色的访问控制)是一种权限管理机制,用于控制用户、系统进程或系统组件对Kubernetes资源的访问权限。
RBAC是一种角色-绑定-权限的体系,在该体系下可以创建不同的角色,每个角色赋予一组特定的资源操作权限,将一个用户与角色绑定,该用户就具有了操作资源的权限。这个过程可以用下面的一幅图来概况。
这幅图中,Subjects是用户,Role和ClusterRole是角色,RoleBingding和ClusterRoleBinding是绑定动作,Resources是要操作的资源对象,Operations是操作类型。

                                                          Resources↓
                                                         ┌────────────┐
                                                         │ Pod        │
 Subjects↓                                              /│ Service    │
┌───────┐    ┌────────────────────┐    ┌─────────────┐ / │ Deployment │
│ User  │    │ RoleBinding        │    │ Role        │/  └────────────┘
│ Group │<-->│                    │<-->│             │    Operations↓
│ SA    │    │ ClusterRoleBinding │    │ ClusterRole │\  ┌────────────┐
└───────┘    └────────────────────┘    └─────────────┘ \ │ get        │
                                                        \│ list       │
                                                         │ watch      │
                                                         └────────────┘

RBAC有三类比较重要的概念:
Subject:主体。可以理解为用户,实际上又分为普通用户(组)和K8s系统用户。
Role、ClusterRole:角色、集群角色。主要是定义了一组资源访问控制规则。
RoleBinding、ClusterRoleBinding:角色绑定、集群角色绑定。将主体与角色绑定,赋予用户操作权限。

在主体里面,K8s系统用户有自己特定的名字,叫做Service Account,它本身存储在K8s中,是一种资源对象,kind类型为ServiceAccount。
Role、ClusterRole、RoleBinding、ClusterRoleBinding也是K8s的资源对象,kind类型分别为:Role、ClusterRole、RoleBinding、ClusterRoleBinding。

3.1 主体Subject

Subject是RBAC体系里访问Kubernetes API的实体,有普通用户(User,human users)、用户组(Group,由多个普通用户组成)和服务账号(SA, Service Accounts)三种类型。

  • User:由外部系统(如X.5089证书,静态Token、LDAP等)提供,不在K8s内存储,典型用途为管理员、开发人员、CI脚本等
  • Group:多个User可以组成一个Group,常用于批量授权
  • SA:由Kubernetes自身提供,可以使用kubectl creata/delete管理,常用于Pod内进程访问API
3.1.1 示例:创建及删除ServiceAccounts账户

下面将通过yaml配置文件及命令行两种方式创建两个SA账户

# 通过yaml配置文件方式创建ServiceAccounts,配置文件如下
[root@master 9-controlling-access]# cat test-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: test-sa
  namespace: default
# 系统只有一个Service Account, 集群部署时默认创建的default账户
[root@master 9-controlling-access]# kubectl get serviceaccounts
NAME      SECRETS   AGE
default   0         4h54m
# sa是serviceaccounts的缩写
[root@master 9-controlling-access]# kubectl get sa
NAME      SECRETS   AGE
default   0         4h54m
# 使用yaml创建一个sa账户
[root@master 9-controlling-access]# kubectl apply -f test-sa.yaml
serviceaccount/test-sa created
# 已创建成功
[root@master 9-controlling-access]# kubectl get sa
NAME      SECRETS   AGE
default   0         4h54m
test-sa   0         3s
# 使用命令行创建一个sa账户
[root@master 9-controlling-access]# kubectl create sa cli-test-sa
serviceaccount/cli-test-sa created
# cli-test-sa账户已创建
[root@master 9-controlling-access]# kubectl get sa
NAME          SECRETS   AGE
cli-test-sa   0         2s
default       0         4h55m
test-sa       0         34s
# 删除刚创建的两个账户
[root@master 9-controlling-access]# kubectl delete sa cli-test-sa
serviceaccount "cli-test-sa" deleted
[root@master 9-controlling-access]# kubectl delete sa test-sa
serviceaccount "test-sa" deleted
# 已删除
[root@master 9-controlling-access]# kubectl get sa
NAME      SECRETS   AGE
default   0         4h55m

3.2 Role和ClusterRole

Role和ClusterRole都是角色,角色是一组资源访问控制规则的集合。Role和ClusterRole的区别是,Role只在当前命名空间有效,而ClusterRole则在整个集群都有效。

3.2.1 Role和ClusterRole资源清单

一个典型的Role对象资源清单如下:

[root@master 9-controlling-access]# cat role-pod-ro.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: role-pod-ro
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","list","watch"]

该资源清单的含义是,创建一个Role对象,可以操作default命名空间下的Pod资源,只能读这些资源,无法更新、删除或打补丁。
使用kubectl apply -f role-pod-ro.yaml可以创建这个对象。
使用如下命令行也可以创建一个Role对象,该对象角色可以对default命名空间下的Service资源进行读取、删除、更新、打补丁等操作:
kubectl create role svc-full -n default --verb=get,list,watch,create,update,patch,delete --resource=services
如果想操作本命名空间下的所有资源,可以使用--resources=*通配符,如果想对本命名空间下的所有资源拥有所有操作权限,可以使用--verb=*通配符。

一个典型的ClusterRole对象资源清单如下:

[root@master 9-controlling-access]# cat clusterrole-pod-deploy-full.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: clusterrole-pod-deploy-full
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","list","watch","create","update","patch","delete"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get","list","watch","create","update","patch","delete"]

该资源清单的含义是,创建一个ClusterRole对象,可以操作所有命名空间下的pods和deployments资源,可以对这些资源读取、删除、更新、打补丁等所有操作。
使用kubectl apply -f clusterrole-pod-deploy-full.yaml可以创建这个对象。
使用如下命令行也可以创建一个ClusterRole对象:
kubectl create clusterrole clusterrole-pod-deploy-ro --verb=get,list,watch --resource=pods,deployments

3.2.2 示例:创建及删除Role、ClusterRole对象

下面使用yaml及命令行两种方式创建Role、ClusterRole对象。

# 查看集群中现有的Role
[root@master 9-controlling-access]# kubectl get role
No resources found in default namespace.
# 查看集群中现有的ClusterRole,由于默认创建的ClusterRole资源太多,这里使用grep过滤
[root@master 9-controlling-access]# kubectl get clusterrole | grep clusterrole-pod-deploy
[root@master 9-controlling-access]# ls
clusterrole-pod-deploy-full.yaml  role-pod-ro.yaml  test-sa.yaml
# Role资源清单
[root@master 9-controlling-access]# cat role-pod-ro.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: role-pod-ro
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","list","watch"]
# ClusterRole资源清单
[root@master 9-controlling-access]# cat clusterrole-pod-deploy-full.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: clusterrole-pod-deploy-full
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","list","watch","create","update","patch","delete"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get","list","watch","create","update","patch","delete"]
# 创建Role
[root@master 9-controlling-access]# kubectl apply -f role-pod-ro.yaml
role.rbac.authorization.k8s.io/role-pod-ro created
# 创建ClusterRole
[root@master 9-controlling-access]# kubectl apply -f clusterrole-pod-deploy-full.yaml
clusterrole.rbac.authorization.k8s.io/clusterrole-pod-deploy-full created
# 查看Role
[root@master 9-controlling-access]# kubectl get role
NAME          CREATED AT
role-pod-ro   2025-08-20T04:53:41Z
# 查看ClusterRole
[root@master 9-controlling-access]# kubectl get clusterrole | grep clusterrole-pod-deploy
clusterrole-pod-deploy-full                                            2025-08-20T04:53:46Z
# 命令行创建一个名称为svc-full的Role对象
[root@master 9-controlling-access]# kubectl create role role-svc-full -n default --verb=get,list,watch,create,update,patch,delete --resource=services
role.rbac.authorization.k8s.io/svc-full created
# 命令行创建一个名称为clusterrole-pod-deploy-ro的ClusterRole对象
[root@master 9-controlling-access]# kubectl create clusterrole clusterrole-pod-deploy-ro --verb=get,list,watch --resource=pods,deployments
clusterrole.rbac.authorization.k8s.io/clusterrole-pod-deploy-ro created
# 查看创建的两个Role和两个ClusterRole
[root@master 9-controlling-access]# kubectl get role
NAME            CREATED AT
role-pod-ro     2025-08-20T04:53:41Z
role-svc-full   2025-08-20T04:54:41Z
[root@master 9-controlling-access]# kubectl get clusterrole | grep clusterrole-pod-deploy
clusterrole-pod-deploy-full                                            2025-08-20T04:53:46Z
clusterrole-pod-deploy-ro                                              2025-08-20T04:54:57Z
# 查看资源详情,可以看到规则
[root@master 9-controlling-access]# kubectl describe role role-pod-ro
Name:         role-pod-ro
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  pods       []                 []              [get list watch]
[root@master 9-controlling-access]# kubectl describe role role-svc-full
Name:         role-svc-full
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  services   []                 []              [get list watch create update patch delete]
[root@master 9-controlling-access]# kubectl describe clusterrole clusterrole-pod-deploy-full
Name:         clusterrole-pod-deploy-full
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources         Non-Resource URLs  Resource Names  Verbs
  ---------         -----------------  --------------  -----
  pods              []                 []              [get list watch create update patch delete]
  deployments.apps  []                 []              [get list watch create update patch delete]
[root@master 9-controlling-access]# kubectl describe clusterrole clusterrole-pod-deploy-ro
Name:         clusterrole-pod-deploy-ro
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources         Non-Resource URLs  Resource Names  Verbs
  ---------         -----------------  --------------  -----
  pods              []                 []              [get list watch]
  deployments.apps  []                 []              [get list watch]

Role和ClusterRole的删除操作如下:
注意我们只删除命令行创建的Role和ClusterRole,通过yaml创建的对象先不删除,下一节角色和主体绑定时会用到。

[root@master 9-controlling-access]# kubectl delete role svc-full
role.rbac.authorization.k8s.io "svc-full" deleted
[root@master 9-controlling-access]# kubectl get clusterrole| grep deploy
clusterrole-pod-deploy-full                                            2025-08-20T04:53:46Z
clusterrole-pod-deploy-ro                                              2025-08-20T04:54:57Z
system:controller:deployment-controller                                2025-08-19T23:05:58Z
[root@master 9-controlling-access]# kubectl delete clusterrole clusterrole-pod-deploy-ro
clusterrole.rbac.authorization.k8s.io "clusterrole-pod-deploy-ro" deleted

3.3 RoleBinding和ClusterRoleBinding

RoleBinding和ClusterRoleBinding用于将角色和主体绑定,其中RoleBinding的作用范围为指定命名空间,ClusterRoleBinding的作用范围为整个集群。

3.3.1 RoleBinding和ClusterRoleBinding资源清单

一个典型的RoleBinding对象资源清单如下:

[root@master 9-controlling-access]# cat rolebinding-alice.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: alice-read
  namespace: default
subjects:
- kind: User
  name: Alice
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: role-pod-ro
  apiGroup: rbac.authorization.k8s.io

该资源清单含义为,创建一个绑定关系,该绑定关系名为alice-read,主体为普通用户(User) Alice,绑定的角色为role-pod-ro,绑定之后,Alice在default命名空间就拥有role-pod-ro规则描述的操作权限。如果我们想让Alice同时在default和kube-system命名空间拥有权限,就需要用到ClusterRoleBinding,可以跨命名空间绑定角色。
可以使用kube-ctl apply -f rolebinding-alice.yaml创建绑定关系。RoleBinding也可以使用命令行创建,如:
kubectl create rolebinding bob-readwrite -n default --role=role-pod-rw --user=Bob

一个典型的ClusterRoleBinding对象资源清单如下:

[root@master 9-controlling-access]# cat clusterrolebinding-test-sa.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: test-sa-cluster-full
subjects:
- kind: ServiceAccount
  name: test-sa
  namespace: default
roleRef:
  kind: ClusterRole
  name: clusterrole-pod-deploy-full
  apiGroup: rbac.authorization.k8s.io

该资源清单含义为:创建一个绑定关系,该绑定关系名为test-sa-cluster-full,主体为Service Account,test-sa,绑定的角色为clusterrole-pod-deploy-full,绑定之后,test-sa拥有角色clusterrole-pod-deploy-full描述的操作权限。
可以使用kube-ctl apply -f clusterrolebinding-ci-bot.yaml创建绑定关系。ClusterRoleBinding也可以使用命令行创建,如:
kubectl create clusterrolebinding test1-sa-cluster-read --clusterrole=clusterrole-pod-deploy-read --serviceaccount=default:test1-sa

3.3.2 示例:创建及删除RoleBinding和ClusterRoleBinding对象

下面示例为主体和角色的绑定过程。
注意:在执行绑定前,需要保证主体及角色都已经存在,如果不存在,则会报错,因为RBAC绑定是即时校验,主体或角色不存在立即404。

# 创建一个Service Account账号
[root@master 9-controlling-access]# kubectl apply -f test-sa.yaml
serviceaccount/test-sa created
[root@master 9-controlling-access]# kubectl get sa
NAME      SECRETS   AGE
default   0         6h41m
test-sa   0         3s
# role-pod-ro为上一节创建的Role
[root@master 9-controlling-access]# kubectl get role
NAME          CREATED AT
role-pod-ro   2025-08-20T04:53:41Z
# clusterrole-pod-deploy-full为上一节创建的ClusterRole
[root@master 9-controlling-access]# kubectl get clusterrole | grep clusterrole-pod-deploy
clusterrole-pod-deploy-full                                            2025-08-20T04:53:46Z
[root@master 9-controlling-access]# ls
clusterrolebinding-test-sa.yaml  clusterrole-pod-deploy-full.yaml  rolebinding-alice.yaml  role-pod-ro.yaml  test-sa.yaml
# RoleBinding资源清单文件
[root@master 9-controlling-access]# cat rolebinding-alice.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: alice-read
  namespace: default
subjects:
- kind: User
  name: Alice
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: role-pod-ro
  apiGroup: rbac.authorization.k8s.io
# ClusterRoleBinding资源清单文件
[root@master 9-controlling-access]# cat clusterrolebinding-test-sa.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: test-sa-cluster-full
subjects:
- kind: ServiceAccount
  name: test-sa
  namespace: default
roleRef:
  kind: ClusterRole
  name: clusterrole-pod-deploy-full
  apiGroup: rbac.authorization.k8s.io
# 创建普通用户Alice和Role的绑定关系
[root@master 9-controlling-access]# kubectl apply -f rolebinding-alice.yaml
rolebinding.rbac.authorization.k8s.io/alice-read created
[root@master 9-controlling-access]# kubectl get rolebinding
NAME         ROLE               AGE
alice-read   Role/role-pod-ro   9s
# 查看绑定关系
[root@master 9-controlling-access]# kubectl describe rolebinding alice-read
Name:         alice-read
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  Role
  Name:  role-pod-ro
Subjects:
  Kind  Name   Namespace
  ----  ----   ---------
  User  Alice
# 创建SA test-sa账户和ClusterRole的绑定关系
[root@master 9-controlling-access]# kubectl apply -f clusterrolebinding-test-sa.yaml
clusterrolebinding.rbac.authorization.k8s.io/test-sa-cluster-full created
[root@master 9-controlling-access]# kubectl get clusterrolebinding | grep test-sa-cluster-full
test-sa-cluster-full                                     ClusterRole/clusterrole-pod-deploy-full                              31s
# 查看绑定关系
[root@master 9-controlling-access]# kubectl describe clusterrolebinding test-sa-cluster-full
Name:         test-sa-cluster-full
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  clusterrole-pod-deploy-full
Subjects:
  Kind            Name     Namespace
  ----            ----     ---------
  ServiceAccount  test-sa  default

RoleBinding和ClusterRoleBinding对象删除:

# 删除RoleBinding资源对象
[root@master 9-controlling-access]# kubectl delete rolebinding alice-read
rolebinding.rbac.authorization.k8s.io "alice-read" deleted
# 删除ClusterRoleBinding资源对象
[root@master 9-controlling-access]# kubectl delete clusterrolebinding test-sa-cluster-full
clusterrolebinding.rbac.authorization.k8s.io "test-sa-cluster-full" deleted

3.4 RBAC角色规则之常见资源(resources)

创建一个RBAC Role/ClusterRole,需要填写如下字段:

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

这个resources就是K8s资源,常见值有下面几种:
(1) 原生资源

资源 缩写 示例
pods po --resource=pods
services svc --resource=services
configmaps cm --resource=configmaps
secrets --resource=secrets
deployments deploy --resource=deployments
statefulsets sts --resource=statefulsets
daemonsets ds --resource=daemonsets
replicasets rs --resource=replicasets
jobs --resource=jobs
cronjobs cj --resource=cronjobs
endpoints ep --resource=endpoints
namespaces ns --resource=namespaces
nodes no --resource=nodes
endpoints ep --resource=endpoints
events ev --resource=events
limitranges lr --resource=limitranges
resourcequotas quota --resource=resourcequotas
networkpolicies netpol --resource=networkpolicies
poddisruptionbudgets pdb --resource=poddisruptionbudgets

(2) 子资源

子资源 示例
pods/log --resource=pods/log
pods/status --resource=pods/status
services/proxy --resource=services/proxy
deployments/scale --resource=deployments/scale
pods/exec --resource=pods/exec

(3) 全资源(以通配符*表示)
--resource=*

3.5 RBAC角色规则之动词(verbs)

创建一个RBAC Role/ClusterRole,需要填写如下字段:

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

这个verbs就是对资源的操作方式,常见值有下面几种:
(1) 常见动词

动词 作用
get 读取单个资源
list 读取集合(多数资源)
watch 监听变化(长连接)
create 新建资源
update 整体替换资源
patch 局部修改资源
delete 删除单个资源
deletecollection 删除集合(多数资源)

(2) 特殊动词

动词 作用
proxy 代理到 Pod/Service/Node
use 使用子资源(如 pods/execpods/portforward

(3) 所有动词

动词 作用
*(通配符) 所有动词(慎用)

4 综合示例:普通用户账户认证和授权

我们知道,Kubernetes API可以通过多种方式访问,前面我们介绍的都是kubectl方式,这里我们介绍使用curl工具直接发送REST请求的方式。
查看集群REST服务地址:
得到地址为https://127.0.0.1:6443

[root@master 9-controlling-access]# kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://127.0.0.1:6443
  name: default
contexts:
- context:
    cluster: default
    user: default
  name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED

4.1 普通用户账户认证

(1) 直接访问K8s API Server
使用curl直接访问API Server该地址,报以下错误

[root@master 9-controlling-access]# curl https://127.0.0.1:6443/api/v1/namespaces
curl: (60) SSL certificate problem: self signed certificate in certificate chain
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

这是因为HTTPS环节出了问题,访问HTTPS地址,需要传入一个证书,这个证书在k3s的证书目录
/var/lib/rancher/k3s/server/tls/server-ca.crt

(2) 传入证书访问API Server
我们传入这个证书,访问API Server:

[root@master 9-controlling-access]# curl --cacert /var/lib/rancher/k3s/server/tls/server-ca.crt https://127.0.0.1:6443/api/v1/namespaces
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "Unauthorized",
  "reason": "Unauthorized",
  "code": 401
}

HTTPS通过,服务端有返回值,这里返回401表示API Server还不认识这个客户端用户。下一步就需要认证。

(3) 创建用户证书

1. 生成私钥
生成 2048 位 RSA 私钥,后续用于签名 CSR。
[root@master 9-controlling-access]# mkdir testuser && cd testuser
[root@master testuser]# openssl genrsa -out testuser.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
..........................+++++
..........................................+++++
e is 65537 (0x010001)
[root@master testuser]# ls
testuser.key

2. 生成 CSR(证书签名请求)
用私钥生成 CSR,CN=testuser 即用户名(RBAC 绑定用)。
[root@master testuser]# openssl req -new -key testuser.key -out testuser.csr -subj "/CN=testuser"
[root@master testuser]# ls
testuser.csr  testuser.key

3. 清理旧 CSR
若之前存在同名 CSR,先删除,避免冲突。
[root@master testuser]# kubectl delete csr testuser 2>/dev/null

4. 提交 CSR 到 K8s
把 CSR 以 CertificateSigningRequest 资源提交,Base64 纯文本
若想把这段yaml保存成文件,需要先替换`$(base64 -w0 testuser.csr)`为csr文件的base64编码值
[root@master testuser]# cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: testuser
spec:
  request: $(base64 -w0 testuser.csr)
  signerName: kubernetes.io/kube-apiserver-client
  usages: ["client auth"]
EOF
certificatesigningrequest.certificates.k8s.io/testuser created

5. 手动批准证书
让 kube-controller-manager 用 client-ca 签发证书,证书写入 CSR.status.certificate。
[root@master testuser]# kubectl certificate approve testuser
certificatesigningrequest.certificates.k8s.io/testuser approved

6. 提取证书
把 Base64 证书 解码为 PEM 文件,即可用于 kubectl/curl 访问 API。
[root@master testuser]# kubectl get csr testuser -o jsonpath='{.status.certificate}' | base64 -d > testuser.crt
[root@master testuser]# ls
testuser.crt  testuser.csr  testuser.key

(4) 使用用户证书访问API Server
这里可以看到,认证已经通过,不再返回401错误,而是返回403错误,没有权限,需要授权

[root@master testuser]# curl --cacert /var/lib/rancher/k3s/server/tls/server-ca.crt --cert testuser.crt --key testuser.key https://127.0.0.1:6443/api/v1/namespaces
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "namespaces is forbidden: User \"testuser\" cannot list resource \"namespaces\" in API group \"\" at the cluster scope",
  "reason": "Forbidden",
  "details": {
    "kind": "namespaces"
  },
  "code": 403
}

4.2 普通用户账户授权

下面将创建一个ClusterRole角色,赋予该角色访问namespaces资源的权限,并将该角色与普通账户testuser绑定。

(1) 创建一个ClusterRole角色
kubectl create clusterrole testuserclusterrole --resource=namespaces --verb=get,list,watch
该命令行效果与如下yaml文件等价

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: testuserclusterrole
rules:
- apiGroups: [""]
  resources: ["namespaces"]
  verbs: ["get","list","watch"]

(2) 创建ClusterRoleBinding绑定关系
kubectl create clusterrolebinding testuser --clusterrole=testuserclusterrole --user=testuser
该命令行效果与如下yaml文件等价

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: testuser
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: testuserclusterrole
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: testuser

(3) 查看绑定关系

[root@master testuser]# kubectl describe clusterrolebinding testuser
Name:         testuser
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  testuserclusterrole
Subjects:
  Kind  Name      Namespace
  ----  ----      ---------
  User  testuser

(4) 访问API Server

# 授权成功,可以访问namespaces资源
[root@master testuser]# curl --cacert /var/lib/rancher/k3s/server/tls/server-ca.crt --cert testuser.crt --key testuser.key https://127.0.0.1:6443/api/v1/namespaces | grep \"name\"
        "name": "default",
        "name": "kube-node-lease",
        "name": "kube-public",
        "name": "kube-system",
# 与kubectl查询到的namespaces资源相同
[root@master testuser]# kubectl get namespaces
NAME              STATUS   AGE
default           Active   8h
kube-node-lease   Active   8h
kube-public       Active   8h
kube-system       Active   8h
# 由于没有对pods资源授权,这里还是返回403 Forbidden
[root@master testuser]# curl --cacert /var/lib/rancher/k3s/server/tls/server-ca.crt --cert testuser.crt --key testuser.key https://127.0.0.1:6443/api/v1/pods
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "pods is forbidden: User \"testuser\" cannot list resource \"pods\" in API group \"\" at the cluster scope",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403
}

5 综合示例:ServiceAccount账户认证和授权

5.1 ServiceAccount账户认证

(1) 创建ServiceAccount账户testsauser

[root@master 9-controlling-access]# mkdir testsauser && cd testsauser
[root@master testsauser]# kubectl create sa testsauser
serviceaccount/testsauser created
[root@master testsauser]# kubectl get sa
NAME         SECRETS   AGE
default      0         8h
test-sa      0         116m
testsauser   0         3s
[root@master testsauser]#

kubectl create sa testsauser为创建SA账户的命令,该命令效果与如下yaml文件等价:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: testsauser
  namespace: default

(2) 创建ServiceAccount账户testsauser对应的token
SA访问API Server需要用到token,为了方便,写入环境变量,后续直接引用

[root@master testsauser]# TEST_SA_USER_TOKEN=$(kubectl create token testsauser -n default --duration=24h)
[root@master testsauser]# echo $TEST_SA_USER_TOKEN
eyJhbGciOiJSUzI1NiIsImtpZCI6Im41N0FLdzVqTnpsZUU5MGYyR0ZBc2tlUlV0dkYzdVhFQTBuTzJ1VWg4cFEifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJrM3MiXSwiZXhwIjoxNzU1NzYyMzM5LCJpYXQiOjE3NTU2NzU5MzksImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwic2VydmljZWFjY291bnQiOnsibmFtZSI6InRlc3RzYXVzZXIiLCJ1aWQiOiI4MTg2MzhlYy1mZTM1LTQzYjMtODRkZC0wNjE1NWMwZTAzOWUifX0sIm5iZiI6MTc1NTY3NTkzOSwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6dGVzdHNhdXNlciJ9.p366DuuOLgYhiYfgeC4Wv-x2esP0DzfdvX9Ipnlwq7BPq7tQi8wo92WT3RM4mCgXqx3dIfTYc1KebT2cLmMx1EMgF3R2G-RYlcPfsfETzo_0333hfM2WrqwszrTQwdR3owOx6jejt_StrMfHGDpjCVkXH48DdHyfRiNKtj0nZX-fQ--CQ0Ez8yb3y8BXNf7-CKPm_C_5dFa89ZMF6zlIu7DvPp1UIBNGhIwitau6e22SEb5jXw7hHX_u26hZTjkdu3_0XNafImrmffFlovFiOYIss1OxGFFM0XYFYQG92OoSH9gWof5ldoB6mGehtBDE_SGS1mNf3nW7kCkm5fN0nQ

kubectl create token testsauser -n default --duration=24h为创建testsauser这个SA账户token的命令,该命令效果与如下yaml文件相似:

apiVersion: v1
kind: Secret
metadata:
  name: testsa-token
  namespace: default
  annotations:
    kubernetes.io/service-account.name: testsauser
type: kubernetes.io/service-account-token

但是命令行创建的token立即返回,不会创建Secret对象,也不会持久化保存,–duration参数决定了其有效期。Secret对象创建的Token会持久化,可以多次使用,这个我们在后面的示例会有演示。

(3) 不使用token访问API Server
返回401,未认证通过。

[root@master testsauser]# curl --cacert /var/lib/rancher/k3s/server/tls/server-ca.crt https://127.0.0.1:6443/api/v1/pods
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "Unauthorized",
  "reason": "Unauthorized",
  "code": 401
}

(4) 使用token访问API Server
返回403 Forbidden,认证通过,但没有访问资源的权限,需要授权。

[root@master testsauser]# curl --cacert /var/lib/rancher/k3s/server/tls/server-ca.crt  -H "Authorization: Bearer $TEST_SA_USER_TOKEN" https://127.0.0.1:6443/api/v1/pods
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "pods is forbidden: User \"system:serviceaccount:default:testsauser\" cannot list resource \"pods\" in API group \"\" at the cluster scope",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403
}

5.2 ServiceAccount账户授权

创建一个ClusterRole,可以访问Pod资源,再创建一个ClusterRoleBinding,将ClusterRole与ServiceAccount testsauser绑定。

(1) 创建ClusterRole对象

[root@master testsauser]# kubectl create clusterrole testsauserclusterrole --resource=pods --verb=get,list,watch
clusterrole.rbac.authorization.k8s.io/testsauserclusterrole created

该命令等价于如下yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: testsauserclusterrole
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","list","watch"]

(2) 创建ClusterRoleBinding对象
将testsauser与testsauserclusterrole绑定。

[root@master testsauser]# kubectl create clusterrolebinding testsauser --clusterrole=testsauserclusterrole --serviceaccount=default:testsauser
clusterrolebinding.rbac.authorization.k8s.io/testsauser created

该命令等价于如下yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: testsauser
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: testsauserclusterrole
subjects:
- kind: ServiceAccount
  name: testsauser
  namespace: default

(3) 查看绑定关系

[root@master testsauser]# kubectl describe clusterrolebinding testsauser
Name:         testsauser
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  testsauserclusterrole
Subjects:
  Kind            Name        Namespace
  ----            ----        ---------
  ServiceAccount  testsauser  default

(4) 访问API Server
可以查看到集群中所有命名空间下的所有Pod。由于没有为namespaces资源授权,所以这里无法查看namespaces资源,返回403错误。

[root@master testsauser]# curl --cacert /var/lib/rancher/k3s/server/tls/server-ca.crt  -H "Authorization: Bearer $TEST_SA_USER_TOKEN" https://127.0.0.1:6443/api/v1/pods | grep \"name\"
        "name": "coredns-6799fbcd5-hnz2f",
            "name": "coredns-6799fbcd5",
            "name": "config-volume",
              "name": "coredns",
            "name": "custom-config-volume",
             (。。。查询到的是集群所有的Pod,较多,部分内容略。。。)
                "name": "kube-api-access-hjdhk",
            "name": "local-path-provisioner",
[root@master testsauser]# curl --cacert /var/lib/rancher/k3s/server/tls/server-ca.crt  -H "Authorization: Bearer $TEST_SA_USER_TOKEN" https://127.0.0.1:6443/api/v1/namespaces
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "namespaces is forbidden: User \"system:serviceaccount:default:testsauser\" cannot list resource \"namespaces\" in API group \"\" at the cluster scope",
  "reason": "Forbidden",
  "details": {
    "kind": "namespaces"
  },
  "code": 403
}

6 综合示例:使用Secret对象持久化保存Token

我们知道kubectl create token testsauser -n default --duration=24h可以产生token,但并不持久化,duration时间过后就失效了,如果想持久化token,可以使用Secret对象,下面我们用一个例子演示一下。

(1) 创建testaaa SA对象和Secret对象的资源清单

[root@master 9-controlling-access]# mkdir secret-token && cd secret-token
[root@master secret-token]# cat testaaa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: testbbb
  namespace: default

---

apiVersion: v1
kind: Secret
metadata:
  name: testbbb-token
  namespace: default
  annotations:
    kubernetes.io/service-account.name: testbbb
type: kubernetes.io/service-account-token

(2) 创建这个两个对象
注:在Kubernetes v1.24版本前,SA创建后Secret将会自动创建,但这个功能自1.24及之后的版本就没有了,需要手动创建Secret。

[root@master secret-token]# kubectl apply -f testbbb.yaml
serviceaccount/testbbb created
secret/testbbb-token created

(3) 查看创建的SA

[root@master secret-token]# kubectl get sa
NAME         SECRETS   AGE
default      0         8h
test-sa      0         131m
testbbb      0         5s
testsauser   0         14m

(4) 查看创建的Secret

[root@master secret-token]# kubectl get secret
NAME            TYPE                                  DATA   AGE
testbbb-token   kubernetes.io/service-account-token   3      70s

(5) 查看Secret对象详情

[root@master secret-token]# kubectl describe secret bbb-token
Name:         testbbb-token
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: testbbb
              kubernetes.io/service-account.uid: ba8f8137-1551-4a10-a3ab-affc517bbb99

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     570 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6Im41N0FLdzVqTnpsZUU5MGYyR0ZBc2tlUlV0dkYzdVhFQTBuTzJ1VWg4cFEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImJiYi10b2tlbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJ0ZXN0YWFhIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiYmE4ZjgxMzctMTU1MS00YTEwLWEzYWItYWZmYzUxN2JiYjk5Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6dGVzdGFhYSJ9.UbjSQa6fz89y5KSN3fCH_-qqfE3XkE2UwzZ3_H9KIVbm0mWY1ccrbstELi1MPd0Ol-b7iuCNNEUyTmKvYrKr785qNszaay8PmeyR-2aNz-y9KOFmKncYQu4kn0ezoEn0ZKJ4sHnVWgBNl951UpQIEMZxvrC_BNJ6tftrZ31mjrkm4TWJo2sdvIB0HOg3kSzGUZWcitN7mdi93wTGx3nsGntxBcS7Sy2RymlTUflgd2SQRz4pNCQO4tis6Q2omdJVLimovAWGN3i3yykKD3O6Kr0A4x6D7ilI3IfnVVaOX8qAFzfc30vWwnAzUVcEIOFGuvU-I_VYc_CcGruEVqysgA

(6) 提取token

[root@master secret-token]# kubectl -n default get secret testbbb-token -o jsonpath='{.data.token}' | base64 -d
eyJhbGciOiJSUzI1NiIsImtpZCI6Im41N0FLdzVqTnpsZUU5MGYyR0ZBc2tlUlV0dkYzdVhFQTBuTzJ1VWg4cFEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImJiYi10b2tlbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJ0ZXN0YWFhIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiYmE4ZjgxMzctMTU1MS00YTEwLWEzYWItYWZmYzUxN2JiYjk5Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6dGVzdGFhYSJ9.UbjSQa6fz89y5KSN3fCH_-qqfE3XkE2UwzZ3_H9KIVbm0mWY1ccrbstELi1MPd0Ol-b7iuCNNEUyTmKvYrKr785qNszaay8PmeyR-2aNz-y9KOFmKncYQu4kn0ezoEn0ZKJ4sHnVWgBNl951UpQIEMZxvrC_BNJ6tftrZ31mjrkm4TWJo2sdvIB0HOg3kSzGUZWcitN7mdi93wTGx3nsGntxBcS7Sy2RymlTUflgd2SQRz4pNCQO4tis6Q2omdJVLimovAWGN3i3yykKD3O6Kr0A4x6D7ilI3IfnVVaOX8qAFzfc30vWwnAzUVcEIOFGuvU-I_VYc_CcGruEVqysgA
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐