APIService 资源
在 Kubernetes 1.7 版本中,通过 API 服务器聚合,可以将 自定义 API 服务器 与 Kubernetes 集群中的主 API 服务器继承。

图中,自定义 API 服务器 X 使用主 API 服务器的 etcd 实例存储数据;自定义 API 服务器 Y 使用自己的 etcd 实例存储数据
当基于 API 服务器聚合,针对自定义资源对象设计了 自定义 API 服务器 时,就不必再通过创建 CRD 资源来表示我们的自定义资源对象,而是可以直接将自定义对象类型实现到自定义 API 服务器中。
🚀 自定义 API 服务器可以通过 APIService
资源进行定义,生成对象后,主服务器将为其分配 URL,所有请求该 URL 的数据会被转发至自定义 API 服务器中。假设 APIService
中的 spec.group=extensions.example.com
且 spec.version=v1alpha1
,则该自定义 API 服务器的 URL 为 /apis/extensions.example.com/v1alpha1/
。
🗣 需要注意的是,自定义 API 服务器 收到的 HTTP 请求的 URL 路径为 /apis/extensions.example.com/v1alpha1
而不是 /
🍓 光定义 APIService
对象是不够的,还需要将自定义 API 服务器运行在集群中,可以将其部署为一个 Pod 并通过 Service 暴露。
在注册完自定义 API 服务器后,可以通过 HTTP 请求或构建自定义 CLI 客户端的方式,向自定义 API 服务器提交请求,实现具体功能。
官方部署自定义 APIService步骤
官方指导的部署自定义 API Service 步骤如下:
确保 API Service 已启用,这需要通过 kube-apiserver 组件的启动参数
--runtime-config
进行设置,默认是启用的建议创建一个 RBAC 规则,允许添加 APIService 资源对象,因为 API 扩展 对整个Kubernetes 集群都生效,所以不推荐在生产环境中对API扩展进行开发或测试
创建一个新的 Namespace 用于运行 APIService
创建一个 CA 证书 用于对 自定义 API Server 的 HTTPS 安全访问进行签名
创建 服务端证书和秘钥 用于 自定义API Server 的 HTTPS 安全访问「服务端证书应该由上面提及的 CA证书 进行签名,也应该包含含有DNS域名格式的CN名称」
在新的 Namespace 中使用服务端证书和秘钥创建 Kubernetes Secret 对象
部署自定义 API Server 实例,通常可以以 Deployment 形式进行部署,并且将之前创建的 Secret 挂载到容器内部「该Deployment也应被部署在新的 Namespace 中」
确保自定义的 API Server 通过 Volume 加载了 Secret 中的证书,这将用于后续的 HTTPS 握手校验
在新的 Namespace 中创建一个 ServiceAccount 对象
创建一个 ClusterRole 用于对 自定义 API 资源 进行操作
使用之前创建的 ServiceAccount 为刚刚创建的 ClusterRole 创建一个 ClusterRolebinding
使用之前创建的 ServiceAccount 为系统 ClusterRole
"system:auth-delegator"
创建一个ClusterRolebinding,以使其可以将认证决策代理转发给 Kubernetes 核心 API Server使用之前创建的 ServiceAccount 为系统 Role
"extension-apiserver-authenticationreader"
创建一个 Rolebinding,以允许 自定义 API Server 访问名为"extension-apiserverauthentication"
的系统 ConfigMap创建 APIService 资源对象
访问 APIService 提供的 API URL 路径,验证对资源的访问能否成功
案例
在本案例中,创建一个没有实际功能的自定义 API Server。
自定义 API Server 实例中运行的代码如下,比较简单,监听了 /apis/example.k8s.io/v1/
和 /apis/example.k8s.io/v1/pods
这些路径:
package main
import (
"fmt"
"net/http"
)
var prefix = "/apis/example.k8s.io/v1"
func main() {
http.HandleFunc(prefix + "/pods/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hit '/pods/' and URL is '" + r.URL.Path + "'")
})
http.HandleFunc(prefix + "/pods", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hit '/pods' and URL is '" + r.URL.Path + "'")
})
http.HandleFunc(prefix + "/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hit '/' and URL is '" + r.URL.Path + "'")
})
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hit '/' and URL is '" + r.URL.Path + "'")
})
// 监听的是 HTTPS 协议
http.ListenAndServeTLS("", "server.crt", "server.key", nil)
}
自定义 API Server 实例由于使用的是 HTTPS 协议,因此需要生成相应的服务端证书和密钥文件,这里我们直接通过下面两句签发即可:
openssl genrsa -out server.key 2048
openssl req -new -x509 -key server.key -out server.crt -days 365
在一切准备就绪后,创建相应的 Dockerfile 文件,并生成 Docker 镜像,上传至镜像仓库中:
FROM corfr/tcpdump
RUN apk --no-cache add curl
ADD example-server /
ADD server.crt /
ADD server.key /
ENTRYPOINT [ "/example-server" ]
在准备好自定义 API Server 实例镜像后,即可以开始进行部署,部署所需的资源如下图所示:

使用的 YAML 配置文件如下,其中使用 Deployment
部署了自定义 API Server 实例:
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: example-server
namespace: example-namespace
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-server
namespace: example-namespace
labels:
k8s-app: example-server
spec:
selector:
matchLabels:
k8s-app: example-server
template:
metadata:
name: example-server
labels:
k8s-app: example-server
spec:
serviceAccountName: example-server
containers:
- name: example-server
image: ysj/example-server:https
imagePullPolicy: IfNotPresent
volumeMounts:
- name: tmp-dir
mountPath: /tmp
volumes:
- name: tmp-dir
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: example-server
namespace: example-namespace
labels:
kubernetes.io/name: "example-server"
spec:
selector:
k8s-app: example-server
ports:
- port: 443
protocol: TCP
targetPort: 443
---
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: ["example.k8s.io"]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:example-server
rules:
- apiGroups:
- ""
resources:
- pods
- services
verbs:
- get
- list
- watch
- create
- delete
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:example-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:example-server
subjects:
- kind: ServiceAccount
name: example-server
namespace: example-namespace
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: example-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: example-server
namespace: example-namespace
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: example-server-auth-reader
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
name: example-server
namespace: example-namespace
---
apiVersion: apiregistration.k8s.io/v1beta1
kind: APIService
metadata:
name: v1.example.k8s.io
spec:
service:
name: example-server
namespace: example-namespace
group: example.k8s.io
version: v1
insecureSkipTLSVerify: true
groupPriorityMinimum: 100
versionPriority: 100
🐙 根据 APIService
的配置可以看出访问自定义 API Server 的 URL 路径为:/apis/example.k8s.io/v1/
验证
通过访问自定义 API Server 的 URL 路径,并通过其返回值确认是否访问成功。
在访问之前,首先通过 kubectl proxy
将原生 API Server 的端口映射至本地,然后开始访问:

从测试结果中可以看出,部署成功。
Last updated
Was this helpful?