apiserver的核心功能:
对组件的贡献
对下封装了对etcd数据库的操作、对上提供了list-watch机制
对客户端的贡献
对客户端提供了api接口(总体来是基于RESTFul风格设计api)
对安全的贡献
认证:检查凭证,验证用户是否是一个合法账号
授权:验证账号对请求中指定的api有没有操作权限
准入控制:提供了两种webhook:mutate和validate
API组织形式
为了方便扩展与演进,API接口支持分组与多版本,这些组织形式直接体现在访问资源的RESTful API上:
顶级路径/
:所有资源的起始路径
顶级大类:顶级路径下面有若干顶级大类,主要包括:
核心资源 /api
:包含kubernetes的基础资源和功能,下面没有分组
扩展资源 /apis
:包含核心资源之外的资源,下面细分为apps
,batch
等资源组,比如各种控制器等,使用/apis/{group}/
路径。
健康检查类 /healthz
:用于检查 Kubernetes API Server 的健康状态
性能指标类 /metrics
:用于获取 Kubernetes API Server 的性能指标数据
细分组:顶级大类下面又细分为apps
,batch
等资源组,也就是使用kubectl explain 资源
看到的Group字段的值。资源组主要存在于扩展资源大类下面,核心资源直接使用/api/v1
路径
版本号:某种资源的版本号,为了支持独立的演进,kubernetes API 支持不同的版本,代表不同的成熟度
alpha1
级别:比如v1alpha1
,测试功能,默认情况下是禁用的
Beta
级别:比如v2beta1
,表示功能已经它通过了很好的测试,但是在随后的版本中仍有可能发生更改,默认情况下是启用的。
稳定级别,比如v1
,当前以及后续的很多版本会持续稳定的版本。
资源类型:具体的资源类型,比如Pods
,namespaces
等,不多介绍。
查看当前版本 kubernetes 中的 api 层级
1 | kubectl get --raw / |
识别(Identification)
1 | APIServer首先需要识别用户实体(Subject),识别的关键是用户实体具有一个访问APIServer的identity身份,但是准确来说,识别这一步并不在APIServer的验证流程里面,因为用户实体只是一个代号,真正用于认证的东西是用户实体关联的凭证,比如token,secret等。 |
认证(Authentication)
1 | APIServer需要对用户实体所关联的凭证进行认证,包括但不限于token,secret,证书,http+ssl/tls等方式,用于确认用户身份。 |
授权(Authorization)
1 | 用户认证成功之后,APIServer还需要确认该用户是否具有执行相关请求操作的权限。在这一步中,kubernetes提供了几种授权模式,比如基于角色访问控制(RBAC)或基于属性的访问控制(ABAC) |
准入控制(Admission Controllers)
1 | 请求达到APIServer之后,通过了认证和授权,但是在将数据持久化到etcd之前,还需要进行准入控制,这一阶段发生的事情是拦截请求进行mutate或者validate操作,也就是之前介绍的APIServer提供的两种webhook。 |
RBAC(Role Base Access Control),基于角色的访问控制。
简单来说,kubernetes 并不会直接把权限赋给某个用户或者某个用户组,而是把权限赋给某个角色(Role
或者Cluster Role
),用户如果需要相关权限,可以通过RoleBinding
或者ClusterRoleBinding
来绑定到具体的某个角色。
RBAC的核心概念
1 | 绑定 关联 |
角色和绑定
角色分为两大类:Role和ClusterRole
Role
私有的角色,此类角色只能够在单个名称空间内被看到并加以引用,代表该角色是该命名空间私有的,但是私有角色Role并不一定只拥有单个命名空间的权限,它是否拥有所有命名空间的权限,取决于它的绑定方式。
Cluster Role
公共的角色,此类角色能够被所有的名称空间看到并加以引用,代表此类角色是公共的。
绑定是将用户实体与某个角色进行关联的操作。绑定方式也分为两种:rolebinding和clusterrolebinding。
rolebinding
用户实体通过rolebinding的方式绑定某个Role角色,可以将用户锁定在某个命名空间内,此时该用户只具有单个命名空间的相关操作。
clusterrolebinding
用户实体通过clusterrolebinding的方式绑定某个Cluster Role角色,那么该用户的权限范围在整个集群。
扩展:
另外还有一种特殊的绑定方式:用户实体以rolebinding的方式绑定某个Cluster Role角色,这时用户是否具有所有命名空间的权限?
其实并没有,用户权限仍然被锁定在单个命名空间内,因为是否拥有所有命名空间的权限,并不是角色决定的,而是由绑定方式决定的。这种操作看似没什么用,但是又一个场景,是集群内许多个用户,需要具有各自的单个命名空间下相同的权限,如果不采取这种方式,只能给每个用户创建一个Role,然后一对一绑定,管理和控制很麻烦。如果采用这种多个用户通过rolebinding的绑定方式来绑定同一个Cluster Role,可以方便地实现需求,也不会造成权限溢出。
rules
rules是规则集,定义在Role和Cluster Role的yaml文件中,代表某个角色对那些API资源组具有哪些操作权限。
以下面的一个Role角色的资源清单为例
1 | apiversion: rbac.authorization.k8s.io/v1 |
基于RBAC机制,我们可以创建一个用户和Role类型的角色,然后进行绑定,该用户就具有了某个命名空间下的一些权限,大致操作如下:
1 | # 先创建一个私钥文件 |
清理与删除
1 | # 删除某个用户的上下文 |
拓展:
kubectl命令执行的时候,会按照优先级来查找上下文
kubectl --context=/path/to/your-kubeconfig.yaml get pods
,具有最高的优先级。export KUBECONFIG=/path/to/your-kubeconfig.yaml
.kube/config
文件context上下文是给人使用的,kubernetes中还有一种账号是给Pod使用的,ServiceAccount
,简称sa
sa的授权方式跟上文类似,但是它不需要手动签发证书,所以它比创建账户要方便的多
1 | # 注意,创建sa这里一定要指定命名空间,因为Pod是命名空间下的资源,该sa账号一定要在该命名空间存在 |
ServiceAccount的同样采用RBAC的授权机制,但是不生成上下文,它的使用方式是在Pod的template清单中指定.spec.serviceAccountName
ServiceAcount
权限测试:
在Pod外通过kubectl命令检测sa权限,根据返回值是yes或者no判断
1 | kubectl auth can-i get pods --as=system:serviceaccount:<namespace>:<serviceaccount-name> |
在Pod内通过curl命令带token访问apiserver
1 | # token值通过令牌卷投影机制挂载到Pod的/var/run/secrets/kubernetes.io/serviceaccount目录中,可以先把token值声明成一个bian'l |