文章字數一多,在線編輯不方便,本文是 k8s:kube-apiserver 啓動流程的第2部分
傳送門:k8s :kube-apiserver 啓動流程 - 1segmentfault
上回講到 Run 方法:後端
// kubernetes/cmd/kube-apiserver/app.server.go func Run(runOptions *options.ServerRunOptions, stopCh <-chan struct{}) error { ... server, err := CreateServerChain(runOptions, stopCh) if err != nil { return err } return server.PrepareRun().Run(stopCh) }
目前系統中有如下 api server:api
每一個 api server 都對應一個 Config(配置)架構
CreateServerChain 的任務就是根據 ServerRunOptions 建立 XXXConfig,而後再用 XXXConfig 建立 api server,各個 api server 經過 GenericAPIServer 的 delegationTarget 字段組成《責任鏈》
以 Master api server 建立爲例:app
func CreateServerChain( runOptions *options.ServerRunOptions, stopCh <-chan struct{}) (*genericapiserver.GenericAPIServer, error) { ... kubeAPIServerConfig, ... := CreateKubeAPIServerConfig(...) ... kubeAPIServer, err := CreateKubeAPIServer(kubeAPIServerConfig, apiExtensionsServer.GenericAPIServer, sharedInformers, versionedInformers) ... }
下面將簡要介紹 Master api server 的建立過程,主要分析 kube-apiserver 是如何將 資源對象(Node,Pod,Service 等)綁定到具體的 RESTful API,使得客戶端能夠經過 RESTful API 操做資源對象框架
在大概看了一些源代碼以後,我不由問本身:若是是你來設計代碼架構,你會怎麼作?
例如給定一個實體 Student(Java 僞代碼,下同),持久化在 etcd 裏url
public class Student { public int id; public String name; public String phone; }
如何提供 RESTful api 接口提供對 Student 的 CRUD 操做? 設計代碼框架使之適應全部的實體設計
api 接口示例:code
PUT: /user?id=xxx&name=yyy&phone=zzz DELETE: /user?id=xxx POST: /user?id=xxx&name=yyy GET: /user?id=xxx
咱們分幾步來考慮,首先考慮持久化,爲了支持不一樣的持久化框架,或者即時咱們就使用一種持久化框架也須要考慮框架版本匹配問題,這就須要將對持久化框架的基本操做進行抽象,抽取出接口 Backendorm
public interface Backend { String get(String key); void set(String key, String value); }
而後咱們有具體的實現類 EtcdBackend, ConsulBackend 以及 工廠類 BackendFactory
public class EtcdBackend implements Backend { public String get(String key) { ... } public void set(String key, String value) { ... } } public class ConsulBackend implements Backend { public String get(String key) { ... } public void set(String key, String value) { ... } } public class BackendFactory { Backend get(String name) { ... } }
Backend 搞定了,如今咱們須要一個 DAO(Data access object)來訪問它
public class UserDao { private Backend backend; // CRUD 方法 ... }
咱們注意到會有不少實體,他們都須要使用 Backend 接口訪問後端存儲,因此能夠搞個基類 AbstractDao,將 backedn 字段移到基類裏頭
pubic class AbstractDao { private Backend backend; } public class User extends AbstractDao { // CRUD 方法 ... }
進一步觀察,其實各個 DAO 的 CRUD 方法也有不少重複的(模版)代碼,好比若是咱們可以封裝如下變化點:
DAO 中的 CRUD 方法能夠進一步抽取到 AbstractDao 中,那些實在須要子類特例化的方法,能夠經過《模版方法》模式來實現
public class AbstractDao { private Backend backend; // CRUD 方法 ... } public class UserDao extends AbstractDao { // Template 方法 ... }
咱們如今離最後的完工又近了一步,還剩一個問題,就是如何將 url 和 DAO 對應起來,這是一個映射問題,可使用 map 來保持 url 對應的 DAO
map.put("/user", userDao)
以上只是一個簡單的推導,k8s 的實現遠比這個 demo 複雜的多,考慮到各類解耦和擴展性,下回將正式介紹 k8s 的實現