API聚合机制是Kubernetes 1.7版本引入的特性,能够将用户扩展的API注册到kube-apiserver上,仍然通过API Server的HTTP URL对新的API进行访问和操作。为了实现这个机制,Kubernetes在kube-apiserver服务中引入了一个API聚合层(API Aggregation Layer),用于将扩展API的访问请求转发到用户服务的功能。
设计API聚合机制的主要目标如下。
◎ 增加API的扩展性:使得开发人员可以编写自己的API Server来发布他们的API,而无须对Kubernetes核心代码进行任何修改。
◎ 无须等待Kubernetes核心团队的繁杂审查:允许开发人员将其API作为单独的API Server发布,使集群管理员不用对Kubernetes核心代码进行修改就能使用新的API,也就无须等待社区繁杂的审查了。
◎ 支持实验性新特性API开发:可以在独立的API聚合服务中开发新的API,不影响系统现有的功能。
◎ 确保新的API遵循Kubernetes的规范:如果没有API聚合机制,开发人员就可能会被迫推出自己的设计,可能不遵循Kubernetes规范。
总的来说,API聚合机制的目标是提供集中的API发现机制和安全的代理功能,将开发人员的新API动态地、无缝地注册到Kubernetes API Server中进行测试和使用。
下面对API聚合机制的使用方式进行详细说明。
1.在Master的API Server中启用API聚合功能
为了能够将用户自定义的API注册到Master的API Server中,首先需要配置kube-apiserver服务的以下启动参数来启用API聚合功能。
◎ --requestheader-client-ca-file=/etc/kubernetes/ssl_keys/ca.crt:客户端CA证书。
◎ --requestheader-allowed-names=:允许访问的客户端common names列表,通过header中--requestheader-username-headers参数指定的字段获取。客户端common names的名称需要在client-ca-file中进行设置,将其设置为空值时,表示任意客户端都可访问。
◎ --requestheader-extra-headers-prefix=X-Remote-Extra-::请求头中需要检查的前缀名。
◎ --requestheader-group-headers=X-Remote-Group:请求头中需要检查的组名。
◎ --requestheader-username-headers=X-Remote-User:请求头中需要检查的用户名。
◎ --proxy-client-cert-file=/etc/kubernetes/ssl_keys/kubelet_client.crt:在请求期间验证Aggregator的客户端CA证书。
◎ --proxy-client-key-file=/etc/kubernetes/ssl_keys/kubelet_client.key:在请求期间验证Aggregator的客户端私钥。
如果kube-apiserver所在的主机上没有运行kube-proxy,即无法通过服务的ClusterIP进行访问,那么还需要设置以下启动参数:
--enable-aggregator-routing=true
在设置完成重启kube-apiserver服务,就启用API聚合功能了。
2. 注册自定义APIService资源
在启用了API Server的API聚合功能之后,用户就能将自定义API资源注册到Kubernetes Master的API Server中了。用户只需配置一个APIService资源对象,就能进行注册了。APIService示例的YAML配置文件如下:
apiVersion: apiregistration.k8s.io/v1beta1
kind: APIService
metadata:
name: v1beta1.custom.metrics.k8s.io
spec:
service:
name: custom-metrics-server
namespace: custom-metrics
group: custom.metrics.k8s.io
version: v1beta1
insecureSkipTLSVerify: true
groupPriorityMinimum: 100
versionPriority: 100
在这个APIService中设置的API组名为custom.metrics.k8s.io,版本号为v1beta1,这两个字段将作API路径的子目录注册到API路径“/apis/”下。注册成功后,就能通过Master API路径“/apis/custom.metrics.k8s.io/v1beta1”访问自定义的API Server了。
在service段中通过name和namespace设置了后端的自定义API Server,本例中的服务名为custom-metrics-server,命名空间为custom-metrics。
通过kubectl create命令将这个APIService定义发送给Master,就完成了注册操作。
之后,通过Master API Server对“/apis/custom.metrics.k8s.io/v1beta1”路径的访问都会被API聚合层代理转发到后端服务custom-metrics-server.custom-metrics.svc上了。
3.实现和部署自定义API Server
仅仅注册APIService资源还是不够的,用户对“/apis/custom.metrics.k8s.io/v1beta1”路径的访问实际上都被转发给了custom-metrics-server.custom-metrics.svc服务。这个服务通常能以普通Pod的形式在Kubernetes集群中运行。当然,这个服务需要由自定义API的开发者提供,并且需要遵循Kubernetes的开发规范,详细的开发示例可以参考官方给出的示例(https://github.com/kubernetes/sample-apiserver)。
下面是部署自定义APIServer的常规操作步骤
(1)确保APIService API已启用,这需要通过kube-apiserver的启动参数--runtime-config进行设置,默认是启用的。
(2)建议创建一个RBAC规则,允许添加APIService资源对象,因为API扩展对整个Kubernetes集群都生效,所以不推荐在生产环境中对API扩展进行开发或测试。
(3)创建一个新的Namespace用于运行扩展的API Server。
(4)创建一个CA证书用于对自定义API Server的HTTPS安全访问进行签名。
(5)创建服务端证书和秘钥用于自定义API Server的HTTPS安全访问。服务端证书应该由上面提及的CA证书进行签名,也应该包含含有DNS域名格式的CN名称。
(6)在新的Namespace中使用服务端证书和秘钥创建Kubernetes Secret对象。
(7)部署自定义API Server实例,通常可以以Deployment形式进行部署,并且将之前创建的Secret挂载到容器内部。该Deployment也应被部署在新的Namespace中。
(8)确保自定义的API Server通过Volume加载了Secret中的证书,这将用于后续的HTTPS握手校验。
(9)在新的Namespace中创建一个Service Account对象。
(10)创建一个ClusterRole用于对自定义API资源进行操作。
(11)使用之前创建的ServiceAccount为刚刚创建的ClusterRole创建一个ClusterRolebinding。
(12)使用之前创建的ServiceAccount为系统ClusterRole“system:auth-delegator”创建一个ClusterRolebinding,以使其可以将认证决策代理转发给Kubernetes核心API Server。
(13)使用之前创建的ServiceAccount为系统Role“extension-apiserver-authenticationreader”创建一个Rolebinding,以允许自定义API Server访问名为“extension-apiserverauthentication”的系统ConfigMap。
(14)创建APIService资源对象。
(15)访问APIService提供的API URL路径,验证对资源的访问能否成功。
下面以部署Metrics Server为例,说明一个聚合API的实现方式。
随着API聚合机制的出现,Heapster也进入弃用阶段,逐渐被Metrics Server替代。Metrics Server通过聚合API提供Pod和Node的资源使用数据,供HPA控制器、VPA控制器及kubectl top命令使用。Metrics Server的源码可以在GitHub代码库(https://github.com/kubernetes-incubator/metrics-server)找到,在部署完成后,Metrics Server将通过Kubernetes核心API Server的“/apis/metrics.k8s.io/v1beta1”路径提供Pod和Node的监控数据。
首先,部署Metrics Server实例,在下面的YAML配置中包含一个ServiceAccount、一个Deployment和一个Service的定义:
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: metrics-server
namespace: kube-system
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: metrics-server
namespace: kube-system
labels:
k8s-app: metrics-server
spec:
selector:
matchLabels:
k8s-app: metrics-server
template:
metadata:
name: metrics-server
labels:
k8s-app: metrics-server
spec:
serviceAccountName: metrics-server
containers:
- name: metrics-server
image: k8s.gcr.io/metrics-server-amd64:v0.3.1
imagePullPolicy: IfNotPresent
volumeMounts:
- name: tmp-dir
mountPath: /tmp
volumes:
- name: tmp-dir
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: metrics-server
namespace: kube-system
labels:
kubernetes.io/name: "Metrics-server"
spec:
selector:
k8s-app: metrics-server
ports:
- port: 443
protocol: TCP
targetPort: 443
然后,创建Metrics Server所需的RBAC权限配置:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: system:aggregated-metrics-reader
labels:
rbac.authorization.k8s.io/aggregate-to-view: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rules:
- apiGroups: ["metrics.k8s.io"]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:metrics-server
rules:
- apiGroups:
- ""
resources:
- pods
- nodes
- nodes/stats
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:metrics-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:metrics-server
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: metrics-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: metrics-server-auth-reader
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
最后,定义APIService资源,主要设置自定义API的组(group)、版本号(version)及对应的服务(metrics-server.kube-system):
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
在所有资源都成功创建之后,在命名空间kube-system中会看到新建的metrics-server Pod。
通过Kubernetes Master API Server的URL“/apis/metrics.k8s.io/v1beta1”就能查询到Metrics Server提供的Pod和Node的性能数据了
# curl http://192.168.18.3:8080/apis/metrics.k8s.io/v1beta1/nodes
# curl http://192.168.18.3:8080/apis/metrics.k8s.io/v1beta1/pods
小结:
本节内容到此结束,大家可以尝试这来玩一下。