背景
在k8s中,可以通过聚合层扩展 Kubernetes API。
本文参考sample-apiserver项目的readme和安装一个扩展的 API server,通过部署sample-apiserver来体验"聚合层"的效果。
实验目的:
- 验证"聚合层"的功能:看一看"sample-apiserver"是否能够扩展api
- 学习怎么部署"扩展的api server"
实验过程
0x01 配置聚合层
安装一个扩展的 API server 中提到,需要先配置聚合层。
其中很重要的一步是提交APIService对象,apiservice.yaml中定义了APIService对象,执行kubectl apply -f artifacts/example
后,能看到APIService对象被创建。
root@ip-172-31-14-33:~/test_cr# kubectl get APIService v1alpha1.wardle.example.com -o yaml
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apiregistration.k8s.io/v1","kind":"APIService","metadata":{"annotations":{},"name":"v1alpha1.wardle.example.com"},"spec":{"group":"wardle.example.com","groupPriorityMinimum":1000,"insecureSkipTLSVerify":true,"service":{"name":"api","namespace":"wardle"},"version":"v1alpha1","versionPriority":15}}
creationTimestamp: "2022-05-19T07:48:23Z"
name: v1alpha1.wardle.example.com
resourceVersion: "4191734"
uid: 2f101ecd-15b9-4e06-8cbe-5c58c099f7e6
spec:
group: wardle.example.com
groupPriorityMinimum: 1000
insecureSkipTLSVerify: true
service:
name: api
namespace: wardle
port: 443
version: v1alpha1
versionPriority: 15
status:
conditions:
- lastTransitionTime: "2022-05-19T09:10:39Z"
message: all checks passed
reason: Passed
status: "True"
type: Available
不过可能你执行的时候,status字段会显示不正常,比如可能像下面这样
status:
conditions:
- lastTransitionTime: "2022-05-19T07:48:23Z"
message: 'failing or missing response from https://10.233.43.56:443/apis/wardle.example.com/v1alpha1:
bad status from https://10.233.43.56:443/apis/wardle.example.com/v1alpha1: 404'
reason: FailedDiscoveryCheck
status: "False"
type: Available
原因是因为deployment.yaml的镜像有些问题。
0x02 遇到问题:镜像无法获取
如上图,deployment.yaml两个镜像无法获取:
gcr.io/etcd-development/etcd:v3.5.3:这个镜像名字,导致无法用阿里云的docker代理
kube-sample-apiserver:latest:确实没有这个镜像
解决思路:去docker hub中找对应镜像,然后docker tag
或者修改deployment.yaml。
使用lukelau/kube-sample-apiserver:latest
代替kube-sample-apiserver:latest
、zhaowenlei/etcd-development
代替gcr.io/etcd-development/etcd:v3.4.9
docker pull zhaowenlei/etcd-development
docker tag zhaowenlei/etcd-development gcr.io/etcd-development/etcd:v3.4.9
0x03 验证是否新增api?
从下面可以看到,确实有新的路由 "wardle.example.com"
root@ip-172-31-14-33:~# kubectl proxy --port=8080 &
[1] 40768
root@ip-172-31-14-33:~# Starting to serve on 127.0.0.1:8080
root@ip-172-31-14-33:~# curl http://127.0.0.1:8080/apis/wardle.example.com/v1alpha1/namespaces/default/flunders
{
"kind": "FlunderList",
"apiVersion": "wardle.example.com/v1alpha1",
"metadata": {
"selfLink": "/apis/wardle.example.com/v1alpha1/namespaces/default/flunders",
"resourceVersion": "3"
},
"items": []
}
使用kubectl也可以验证
root@ip-172-31-14-33:~# kubectl get flunder
No resources found in default namespace.
删除apiservice后,api无法访问
root@ip-172-31-14-33:~# kubectl delete apiservice v1alpha1.wardle.example.com
apiservice.apiregistration.k8s.io "v1alpha1.wardle.example.com" deleted
root@ip-172-31-14-33:~# curl http://127.0.0.1:8080/apis/wardle.example.com/v1alpha1/namespaces/default/flunders
404 page not found
小结:说明"v1alpha1.wardle.example.com APIService"会给"k8s master api server"新增路由
0x04 能否创建和删除flunder对象?
创建flunder对象
root@ip-172-31-14-33:~# cat test.yaml
apiVersion: wardle.example.com/v1alpha1
kind: Flunder
metadata:
name: sample
root@ip-172-31-14-33:~# kubectl create -f test.yaml
flunder.wardle.example.com/sample created
root@ip-172-31-14-33:~# kubectl get flunder sample -o yaml
apiVersion: wardle.example.com/v1alpha1
kind: Flunder
metadata:
creationTimestamp: "2022-05-19T09:38:22Z"
name: sample
namespace: default
resourceVersion: "7"
selfLink: /apis/wardle.example.com/v1alpha1/namespaces/default/flunders/sample
uid: 504b1583-54fc-4f0d-974f-9ae54b66a01b
spec: {}
status: {}
删除flunder对象
root@ip-172-31-14-33:~# kubectl delete -f test.yaml
flunder.wardle.example.com "sample" deleted
root@ip-172-31-14-33:~#
root@ip-172-31-14-33:~# kubectl get flunder
No resources found in default namespace.
小结:像操作其他api对象一样操作flunder对象,比如创建、删除
总结
部署"扩展的api server",很重要的两步:
- 创建APIService对象
- 部署"扩展api server"
可以类比web框架来理解"扩展的api server":APIService对象的"group、version"字段组合成"路由","service"字段会指向"控制器"(java中的servlet、gin中的handler)。