Openshift API部分源碼學習筆記(一)


Openshift API簡介

Openshift API包含了兩部分,一部分是Kubernetes v1 REST API,另一部分是OpenShift v1 REST API,這些RESTful API都是通過HTTP(s)來訪問OpenShift Container Platform的master服務器來調用的。這些API可用於管理終端用戶的應用程序,集群和集群用戶。

Openshift里面Kubernetes api的前綴是 /api,而OpenShift 自己開發了一些api,它們的前綴是 /oapi,kubernetes原生api已有的功能Openshift並沒有重新寫接口而是直接用的kubernetes的原生apii,只不過開發了一些kubernetes原先沒有的功能和api接口。

源碼分析

github地址:https://github.com/openshift/origin(此文中代碼對應1.3版本)

sourcegraph網站地址:https://sourcegraph.com/github.com/openshift/origin@release-1.3/-/blob/cmd/openshift/openshift.go

代碼入口

--》openshift/origin/cmd/openshift/openshift.go

openshift.go里面的main方法有啟動服務邏輯,通過調用CommandFor獲取哪些啟動命令需要執行。

CommandFor方法里面根據傳入的basename參數來決定獲取哪些命令,默認是調用NewCommandOpenShift方法獲取所有命令

 

NewCommandOpenShift方法先創建一個Command結構root,然后往root里面添加命令。邏輯里會首先調用NewCommandStartAllInOne方法獲取一些主要命令集。

--》openshift/origin/pkg/cmd/server/start/start_allinone.go

NewCommandStartAllInOne方法里面添加命令的主要邏輯如下:

此處會拿到master,node等等的啟動命令,還有kubernetes相關服務組件的啟動。

1).這里我先從獲取kubernetes相關命令的方法開始看

--》openshift/origin/pkg/cmd/server/start/kubernetes/kubernetes.go 

NewCommand方法里面主要邏輯如下:

 

這里包含了好幾部分kubernetes組件的啟動命令,我們主要關注api部分,因此是NewAPIServerCommand方法

--》openshift/origin/pkg/cmd/server/start/kubernetes/apiserver.go

這后面的邏輯跟kubernetes源碼里面api這部分的邏輯大致相同,先根據默認參數新建一個APIServer

然后通過server.go里面的run方法啟動指定的APIServer

--》openshift/origin/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/server.go 

run方法里面啟動api server的主要邏輯如下,先根據配置新建一個server然后啟動

--》openshift/origin/vendor/k8s.io/kubernetes/pkg/master/master.go

master里面的new方法先根據配置信息返回一個api server的實例,然后調用InstallAPIs方法初始化所有的api

InstallAPIs方法里面會根據條件來創建好幾個apiGroupsInfo結構並將它們添加到一個apiGroupsInfo組中間去,這些不同的apiGroupsInfo對應不同的版本信息,例如v1,v1beta1等等。添加到數組中去好了之后會調用InstallAPIGroups方法來安裝所有的apiGroupsInfo中的api。這里我們拿v1這個group來看,邏輯里面會先調用initV1ResourcesStorage方法來初始化v1這個group的所有storage,例如podStorage,nodeStorage

新建好這些storage之后會將它們配置到一個map中去,此map即相當於一個配置文件去管理要用到哪些storage以及對應的路徑path,這些即決定了后面會提供哪些api

m.v1ResourcesStorage = map[string]rest.Storage{
        "pods":             podStorage.Pod,
        "pods/attach":      podStorage.Attach,
        "pods/status":      podStorage.Status,
        "pods/log":         podStorage.Log,
        "pods/exec":        podStorage.Exec,
        "pods/portforward": podStorage.PortForward,
        "pods/proxy":       podStorage.Proxy,
        "pods/binding":     podStorage.Binding,
        "bindings":         podStorage.Binding,

        "podTemplates": podTemplateStorage,

        "replicationControllers":        controllerStorage.Controller,
        "replicationControllers/status": controllerStorage.Status,

        "services":        serviceRest.Service,
        "services/proxy":  serviceRest.Proxy,
        "services/status": serviceStatusStorage,

        "endpoints": endpointsStorage,

        "nodes":        nodeStorage.Node,
        "nodes/status": nodeStorage.Status,
        "nodes/proxy":  nodeStorage.Proxy,

        "events": eventStorage,

        "limitRanges":                   limitRangeStorage,
        "resourceQuotas":                resourceQuotaStorage,
        "resourceQuotas/status":         resourceQuotaStatusStorage,
        "namespaces":                    namespaceStorage,
        "namespaces/status":             namespaceStatusStorage,
        "namespaces/finalize":           namespaceFinalizeStorage,
        "secrets":                       secretStorage,
        "serviceAccounts":               serviceAccountStorage,
        "securityContextConstraints":    securityContextConstraintsStorage,
        "persistentVolumes":             persistentVolumeStorage,
        "persistentVolumes/status":      persistentVolumeStatusStorage,
        "persistentVolumeClaims":        persistentVolumeClaimStorage,
        "persistentVolumeClaims/status": persistentVolumeClaimStatusStorage,
        "configMaps":                    configMapStorage,

        "componentStatuses": componentstatus.NewStorage(func() map[string]apiserver.Server { return m.getServersToValidate(c) }),
    }

然后新建一個APIGroupInfo,將前面的這個map放到這個新建的APIGroupInfo中去。等所有APIGroupInfo放好之后調用InstallAPIGroups方法

--》openshift/origin/vendor/k8s.io/kubernetes/pkg/genericapiserver/genericapiserver.go

InstallAPIGroups方法里面會循環調用InstallAPIGroup方法去安裝每個APIGroup

InstallAPIGroup方法先取得api路徑前綴,這里我們還是拿v1這個group舉例,所以這里拿到的前綴apiPrefix會是 /api,然后根據APIGroupInfo結構的信息來獲取一個apiGroupVersion結構對象,再調用apiGroupVersion的InstallREST方法來注冊REST api。

--》openshift/origin/vendor/k8s.io/kubernetes/pkg/apiserver/apiserver.go

 

InstallREST方法會新建一個webService,此webService會處理指定的path下面的所有請求,vi這個group的webService所對應的path就是/api/v1,然后調用Install方法去安裝初始化所有route

--》openshift/origin/vendor/k8s.io/kubernetes/pkg/apiserver/api_installer.go

Install方法里面主要邏輯如下,循環遍歷所有前面那個記錄path和storage的map里的路徑path,然后注冊每個path對應的handler

registerResourceHandlers方法里面先根據當前的storage獲取各種action方法,例如create,get方法

然后根據當前storage對應的resource是否是有namespace的來分別創建action並放到actions這個數組中

這里的不同action方法用到的api路徑不盡相同,像LIST,POST方法都是path里面不需要item name的,而GET,PUT都是需要item name的

然后循環actions數組將每種action對應的方法轉化成route並添加到webService中去,這里截取GET的處理代碼

所有這些都處理好之后將此webService添加到container中去,至此kubernetes的API Server注冊啟動命令就創建好了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM