30.kubernetes 聚合层
说明:
下文涉及到kube-apiserver则代表的是master节点的apiserver服务
一、简述
聚合层(Aggregation Layer)可以让用户通过额外的 API 来扩展 kubernetes,这些 API 作为Kubernetes 核心API的补充,以基于具体需求来扩展功能。
聚合层在kube-apiserver进程内运行,API扩展资源注册前,聚合层不会做任何事。注册API时,需添加一个APIServer资源对象,该APIServer对象“申领”Kubernetes API中的URL路径,并绑定到扩展APIService上。此后kube-apiserver中的聚合层会将发送给被申领了URL的所有内容转发到已注册的APIService。例如后面文章介绍的metrics-server
二、Authentication流程
Aggregation API除了标准的kubernetes apiservice 外还涉及到另一个扩展服务,该扩展服务是Aggregation API的真正实现。因此我们需要维护kube-apiserver与我们扩展apiserver之间的安全通信,kube-apiserver使用X509证书向扩展apiserver认证。
鉴权大概流程如下:
三、Kubenetes Apiserver 认证
Kubenetes Apiserver 客户端认证
Kubenetes Apiserver 转聚合API请求到扩展apiserver时,是client角色,在建立TLS连接时需使用客户端证书认证。
我们为kube-apiserver添加如下参数配置证书信息
--proxy-client-key-file
指定私钥文件
--proxy-client-cert-file
签名的客户端证书文件
--requestheader-client-ca-file
签署客户端证书文件的 CA 证书
--requestheader-allowed-names
在签署的客户证书中有效的公用名(CN)
客户端证书必须由--requestheader-client-ca-file
指定的CA证书签发,该CA应该和扩展apiserver的server证书同源
客户端证书CN应该属于--requestheader-allowed-names
配置值之一,若--requestheader-allowed-names
为空则表明任何CN都是可接受的。
Kubenetes Apiserver 原始请求用户名和组
kube-apiserver将请求代理到扩展apiserver时,需告诉扩展apiserver已通过kube-apiserver验证的原始请求的用户名和组,代理请求的HTTP头部会提供这些信息。
我们可以通过如下参数告诉kube-apiserver将用户信息保存在HTTP头部的哪个标签下:
--requestheader-username-headers
标明用来保存用户名的头部
--requestheader-group-headers
标明用来保存 group 的头部
--requestheader-extra-headers-prefix
标明用来保存拓展信息前缀的头部
kubernetes处理授权配置的方式
kube-apiserver会在kube-system
命名空间中创建一个名为extension-apiserver-authentication
的ConfigMap,将上述各种配置保存进去。该ConfigMap供kube-apiserver和扩展apiserver共同检索和使用
四、扩展 Apiserver 认证过程
扩展apiserver再收到kube-apiserver代理过来的请求后,需验证原始身份确实由kube-apiserver验证通过,其过程大概如下
1. 扩展apiserver从kube-system命名空间获取名为extension-apiserver-authentication
的Configmap,并从中检索出如下信息
- Client CA 证书
- requestheader-allowed-names(允许的CN列表)
- 用户名、组和扩展信息的HTTP头部标签
2. 对kube-apiserver代理请求进行校验
- 验证扩展apiserver证书 是否与从Configmap中检索出来的CA证书的签名匹配
扩展apiserver需授予具有检索configmap的权限:
kube-system
namespace下的默认角色extension-apiserver-authentication-reader
- 判断CA证书的CN是否在允许的CN列表中(允许的CN列表为空,则允许所有CN)
- 通过检索出来的HTTP头部标签,从请求中提取出
user/group
等信息
3. 访问kube-apiserver对上步提取出来的user/group
进行鉴权
扩展apiserver向kube-apiserver发送标准SubjectAccessReview请求来实现鉴权,为此扩展apiserver需要有向kube-apiserver发送SubjectAccessReview请求的权限(ClusterRole system:auth-delegator
)。
k8s鉴权概述
SelfSubjectAccessReview 是 authorization.k8s.io API 组的一部分,它将 API 服务器鉴权公开给外部服务。
4. 若 SubjectAccessReview 通过,则扩展apiserver开始执行请求
五、Kubernetes Apiserver的启用
启用标志
上文大概提到了一些配置,这里统一列举一下:
--requestheader-client-ca-file=<path to aggregator CA cert>
--requestheader-allowed-names=front-proxy-client
--requestheader-extra-headers-prefix=X-Remote-Extra-
--requestheader-group-headers=X-Remote-Group
--requestheader-username-headers=X-Remote-User
--proxy-client-cert-file=<path to aggregator proxy cert>
--proxy-client-key-file=<path to aggregator proxy key>
除此之外,若kube-apiserver的节点上没有运行kube-proxy,那么kube-apiserver必须启用
--enable-aggregator-routing=true
CA冲突
kube-apiserver的启动参数中,有两个关于客户端CA的选项:
--client-ca-file
:该CA证书验证到达kube-apiserver的请求,要求请求由该参数配置的CA证书签名且用户名是CN值,组织是O值;
--requestheader-client-ca-file
:该CA验证到达kube-apiserver的请求,通过后进行后续检查,要求请求由该参数配置的CA证书签名,且CN是否是属于--requestheader-allowed-names
;
若--client-ca-file
和--requestheader-client-ca-file
同时配置,kube-apiserver先检查requestheader-client-ca-file CA。若这两个参数配置同一个CA,则可能发生通过client-ca-file传递的客户端请求,会先被requestheader-client-ca-file匹配到,并后续requestheader-allowed-names 的CN检查不通过,导致这些原本应该由client-ca-file验证的请求全部失败。
因此,建议--client-ca-file
和--requestheader-client-ca-file
使用不同的CA。
六、注册APIServer对象
资源定义示例
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: <注释对象名称>
spec:
group: <扩展Apiserver的API组名>
version: <扩展Apiserver的API版本>
groupPriorityMinimum: <APIService对应组的优先级>
versionPriority: <版本在组中的优先排序>
service:
namespace: <扩展Apiserver服务的名字空间>
name: <扩展Apiserver服务的名称>
caBundle: <PEM编码的CA证书,用于对Webhook服务器的证书签名>
案例
---
apiVersion: apiregistration.k8s.io/v1beta1
kind: APIService
metadata:
name: v1beta1.metrics.k8s.io
spec:
service:
name: metrics-server
namespace: kube-system
group: metrics.k8s.io
version: v1beta1
insecureSkipTLSVerify: true
groupPriorityMinimum: 100
versionPriority: 100