1、概述
在kubernetes上擴展資源類型的方式有三種,第一種是CRD,CRD是kubernetes內建的資源類型,該類型資源主要用來創建用戶自定義資源類型的資源;即通過CRD資源,可以將用戶自定義資源類型轉換為kubernetes上資源類型;第二種是自定義apiserver;這種方式要比第一種方式要復雜一點,需要用戶手動開發程序實現對應功能的apiserver,讓其用戶創建自定義類型資源能夠通過自定義apiserver實現;第三種方式就是修改現有kubernetes apiserver服務,讓其支持對應用戶自定義資源類型。
本文主要是講解kubernetes的第二種擴展機制自定義apiserver,以及APIService資源。
2、Kubernetes原生apiserver
在開始聊自定義apiserver前,我們先來了解下kubernetes原生的apiserver。
2.1 apiserver資源組織邏輯
其實apiserver就是一個https服務器,我們可以使用kubectl工具通過https協議請求apiserver創建資源,刪除資源,查看資源等等操作;每個請求都對應着restful api中的請求方法,對應資源就是http協議中的url路徑;比如我們要創建一個pod,其kubectl請求apiserver 使用post方法將資源定義提交給apiserver;pod資源就是對應群組中的某個版本下某個名稱空間下的某個pod資源。

客戶端訪問apiserver,對應資源類似上圖中的組織方式;比如訪問default名稱空間下某個pod,其路徑就為/apis/core/v1/namespace/default/pod/mypod;對應resource包含命名空間以及對應資源類型;
2.2 k8s原生apiserver組成
kubernetes原生apiserver主要有兩個組件組成,第一個組件aggregator,其功能類似web代理服務器,第二個組件就是真正的apiserver;其工作邏輯是,用戶請求首先送達給aggregator,由aggregator根據用戶請求的資源,將對應請求路由至apiserver;簡單講aggregator這個組件主要作用就是用來路由用戶請求;默認情況aggregator會把所有請求都路由至原生的apiserver上進行響應;如果我們需要自定義apiserver,就需要在默認的aggregator上使用APIService資源將自定義apiserver注冊到原生的apiserver上,讓其用戶請求能夠被路由至自定義apiserver進行響應;如下圖

apiserver是kubernetes的唯一訪問入口,默認客戶端的所有操作都是發送給apiserver進行響應,我們自定義的apiserver要想能夠被客戶端訪問,就必須通過內建apiserver中的aggregator組件中的路由信息,把對應路徑的訪問路由至對應apiserver進行訪問;對應aggregator中的路由信息,由k8s內建APIService資源定義;簡單講APIService資源就是用來定義原生apiserver中aggregator組件上的路由信息;該路由就是將某某端點的訪問路由至對應apiserver;
查看原生apiserver中的群組/版本信息:
[root@master1 ~]# kubectl api-versions admissionregistration.k8s.io/v1 admissionregistration.k8s.io/v1beta1 apiextensions.k8s.io/v1 apiextensions.k8s.io/v1beta1 apiregistration.k8s.io/v1 ........
只有上面列出的群組版本才能夠被客戶端訪問,即客戶端只能訪問上述列表中群組版本中的資源,沒有出現群組版本是一定不會被客戶端訪問到。在原生kubernetes集群根據業務需求創建的CRD資源的group/version信息也能通過上述命令查詢到,假設我在原生kubernetes集群中創建了一個自定義CRD,其group是iam.zmc.io,version是v1alpha2,那么在kubernetes集群中查詢對應APIService資源會查詢到。
[root@master1 ~]# kubectl get apiservices.apiregistration.k8s.io v1alpha2.iam.zmc.io NAME SERVICE AVAILABLE AGE v1alpha2.iam.zmc.io Local True 14s
3、APIService資源的使用
3.1 APIService資源介紹
APIService 是用來表示一個特定的 GroupVersion 的中的 server,它的結構定義位於代碼 staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/types.go 中。
下面是一個 APIService 的示例配置:
[root@master1 ~]# cat apiservice-demo.yaml
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v2beta1.auth.ilinux.io
spec:
insecureSkipTLSVerify: true
group: auth.ilinux.io
groupPriorityMinimum: 1000
versionPriority: 15
service:
name: auth-api
namespace: default
port: 443
version: v2beta1
3.2 APIService資源詳解
使用 apiregistration.k8s.io/v1beta1 版本的 APIService,在 metadata.name 中定義該 API 的名字。
使用上面的 yaml 的創建 v2beta1.auth.ilinux.io APIService。
insecureSkipTLSVerify:當與該服務通信時,禁用 TLS 證書認證。強加建議不要設置這個參數,默認為 false。應該使用 CABundle 代替。service:與該 APIService 通信時引用的 service,其中要注明 service 的名字和所屬的 namespace,如果port參數為空的話,則所有的服務將在本地 443 端口處理所有通信。上述資源清單表示在aggregator上注冊auth.ilinux.io/v2beta1這個端點,該端點對應的后端apiserver的service是default名稱空間下的auth-api service;即客戶端訪問auth.ilinux.io/v2beta1下的資源都會被路由至default名稱空間下的auth-api service進行響應;groupPriorityMinimum:該組 API 的處理優先級,主要排序是基於groupPriorityMinimum,該數字越大表明優先級越高,客戶端就會與其通信處理請求。次要排序是基於字母表順序,例如 v1.bar 比 v1.foo 的優先級更高。versionPriority:VersionPriority 控制其組內的 API 版本的順序。必須大於零。主要排序基於 VersionPriority,從最高到最低(20 大於 10)排序。次要排序是基於對象名稱的字母比較。 (v1.foo 在 v1.bar 之前)由於它們都是在一個組內,因此數字可能很小,一般都小於 10。
3.3 查看集群支持的 APISerivce
作為 Kubernetes 中的一種資源對象,可以使用 kubectl get apiservice 來查看。
例如查看集群中所有的 APIService:
$ kubectl get apiservice NAME AGE v1. 2d v1.authentication.k8s.io 2d v1.authorization.k8s.io 2d v1.autoscaling 2d v1.batch 2d ........
另外查看當前 kubernetes 集群支持的 API 版本還可以使用kubectl api-versions:
$ kubectl api-versions apiextensions.k8s.io/v1beta1 apiregistration.k8s.io/v1beta1 apps/v1beta1 apps/v1beta2 authentication.k8s.io/v1 authentication.k8s.io/v1beta1 authorization.k8s.io/v1 authorization.k8s.io/v1beta1 autoscaling/v1 ..........
3.4 應用清單
[root@master1 ~]# kubectl apply -f apiservice-demo.yaml apiservice.apiregistration.k8s.io/v2beta1.auth.ilinux.io created [root@master1 ~]# kubectl get apiservice |grep auth.ilinux.io v2beta1.auth.ilinux.io default/auth-api False (ServiceNotFound) 16s [root@master1 ~]# kubectl api-versions |grep auth.ilinux.io auth.ilinux.io/v2beta1
可以看到應用清單以后,對應的端點信息就出現在api-versions中;上述清單只是用來說明對應APIService資源的使用;其實應用上述清單創建apiservice資源沒有實質的作用,其原因是我們對應名稱空間下並沒有對應的服務,也沒有對應自定義apiserver;所以通常自定義apiserver,我們會用到APIService資源來把自定義apiserver整合進原生apiserver中;這塊內容我們在metrics-server篇章講解(metrics-server是用來擴展k8s的第三方apiserver,其主要作用是收集pod或node上的cpu和內存的指標數據,並提供一個api接口供kubectl top命令訪問;默認情況kubectl top 命令是沒法正常使用,其原因是默認apiserver上沒有對應的接口提供收集pod或node的cpu,內存的指標數據;kubectl top命令主要用來顯示pod/node資源的cpu,內存的占用比例;該命令能夠正常使用必須依賴Metrics API)。
4、總結
APIService資源的主要作用就是在aggregator上創建對應的路由信息,該路由信息的主要作用是將對應端點訪問路由至自定義apiserver所對應的service進行響應。
本文大部分內容參考本篇博文:https://www.cnblogs.com/qiuhom-1874/archive/2021/01/15/14279850.html
作者:Linux-1874
