K8s Service那些事-kubernetes 服務發佈以及在eBay的實踐




eBay自2014年末開始kubernetes的落地工作,並在2015年擴大研發投入。目前kubernetes已經部署在eBay的生產環境,並將作爲下一代雲計算平臺。本文結合社區kubernetes的設計和實現,並結合openstack雲基礎架構,深入分析kubernetes服務部署的設計與實現。如果您在尋×××發佈的方案或者在尋找kubernetes服務相關的模塊的原理或行爲,閱讀本文會讓你有比較明確的方向。

總攬

Kubernetes架構

下圖是kubernetes的架構圖,當用戶將應用從傳統平臺轉移至kubernetes時,首當其衝的任務就是將應用容器話,並定義pod和replicaset(或者petsets,如果遷移的是有狀態應用)來運行應用,kubernetes提供針對應用的PDMR(provision, deployment, monitoring, remediation)。通常來講,kubernetes爲pod分配的是私有ip。如果需要提供應用的跨集羣訪問,則需要通過Service以及Ingress來實現。


服務的發佈

下圖展示的是kubernetes 集羣包括集羣聯邦中服務相關的組件以及組件之間的關係。


Federated-apiserver作爲集羣聯邦推薦的面向用戶的接口,接受用戶請求,並根據聯邦層面的調度器和控制器,將用戶請求分裂/轉發至kubernetes集羣。


根據用戶IaaS環境的不同,可能需要採用不同的provider來實現與外部組件的整合,目前這些定製化provider 包括:


  • DNS provider:社區實現包括 gce googledns,aws dns,eBay採用自己的GTM client

  • Load Balancer provider for service: 主流雲平臺都有自己的provider,eBay的Kubernetes部署在openstack之上,採用社區版本的openstack provider。

  • Load Balancer provider for ingress:社區目前有gclb和nginx兩個版本的ingress controller,eBay與自己的內部load balancer management system(LBMS)對接,採用自己訂製的基於LBMS client的ingress controller。




關於kubernetes的基本概念如pod, service等,網上有很多相關文章,可以參考kubernetes官網或網上的入門文章,本文不再一一贅述。本文希望針對kubernetes服務發佈,進行end to end的分析,並針對特定雲環境如eBay採用的openstack的具體實踐。

服務發佈

第一步:定義你的服務

eBay很多應用都採用微服務架構,這使得在大多數情況下,作爲服務所有者,除了實現業務邏輯以外,還需要考慮如何把服務發佈到kubernetes集羣或者集羣外部,使這些服務能夠被kubernetes應用,其他kubernetes集羣的應用以及外部應用使用。

這是一個業界的通用需求,因此kubernetes提供了靈活的服務發佈方式,用戶可以通過ServiceType來指定如何來發布服務。

  • ClusterIP: 此類型是默認的,這種類型的服務只能在集羣內部訪問。

  • NodePort: 此類型同時會分配clusterIP,並進一步在集羣所有節點的同一端口上曝露服務,用戶可以通過任意的 <NodeIP>:NodePort 訪問服務。

  • LoadBalancer: 此類型同時會分配clusterIP,分配NodePort,並且通過cloud provider來實現LB設備的配製,並且在LB設備中配置中,將<NodeIP>:NodePort作爲pool member,LB設備依據轉發規則將流量轉到節點的NodePort。

內部服務

ClusterIP


如果你的service只服務於cluster 內部,那麼service type定義爲ClusterIP就足夠了。

Kube-proxy是運行在kubernetes 集羣所有節點的組件,它的主要職責是實現服務的虛擬IP。

針對只面向集羣內部的服務,我們建議用戶使用ClusterIP作爲服務類型,該類型比nodePort少佔用節點端口,並比LoadBalancer類型減少對LB設備的訪問,我們應該儘可能的避免不必要的LB設備的訪問,因爲任何外部依賴都有失敗的可能性。

外部服務

NodePort

針對類型是”NodePort”的服務,kubernetes master會從與定義的端口範圍內請求一個端口號(默認範圍:30000-32767),每個節點會把該端口的流量轉發到對應的服務,端口號會先是在服務的spec.ports[*].nodePort

如果你希望指定端口,你可以通過nodePort來定義端口號,系統會檢查該端口是否可用,如果可用就則分配該指定端口。指定端口時需要考慮端口衝突,並且端口需要在預定義的範圍內。

這爲開發者提供了自由度,他們可以配製自己的LB設備,配製未被kubernetes完全支持的雲環境,直接開放一個或者多個節點的IP供用戶訪問服務。


eBay的kubernetes 集羣架設在openstack 環境之上,採用openstack vm作爲kubernetes node,這些node在隔離的VPC,無法直接訪問,因此對外不採用nodePort方式發佈服務。

LoadBalancer

針對支持外部LB設備的cloud provider的情況,將type字段設置爲LoadBalancer會爲服務通過異步調用生成負載均衡配製,負載均衡配製會體現在服務的status.loadBalancer 字段。


實際上,當此類型的服務進行load balancer配置時,nodeip:nodeport 作爲LB Pool的member,最終的traffic還是轉到某node的nodeport上的。


因爲eBay有openstack作爲IaaS層架構,每個openstack AZ有專屬的負載均衡設備,負載均衡設備與虛擬機(即kubernetes node)的連通性在openstack AZ創建的時候就已經設置好,並且openstack的LBaaS已經把針對LB設備的操作做了抽象,這讓kubernetes和LB設備的通信變得非常簡單。eBay直接採用社區版本的openstack provider作爲cloud provider,該provider會調用openstack LBaaS api來進行LB設備的配製,無需訂製即可實現與LB設備的集成。


Service Controller:服務是如何被髮布到集羣外部的

Kubernetes controller manager的主要作用是watch kube-apiserver的相關對象,在有新對象事件如創建,更新和刪除發生時,進行相應的配製,如servicecontroller的主要作用是爲service配製負載均衡,replicaset controller主要作用是管理replicaset中定義的pod,保證pod與replicas一致。如果你對kubernetes代碼比較熟悉,你會發現servicecontroller是其中職責相對清晰,代碼相對簡單的一個控制器。


通過解讀servicecontroller的源碼,我們可以瞭解到servicecontroller 同時監控service和node兩種對象的變化,針對任何新創建或者更新的服務,servicecontroller調用loadbalancer provider的接口來實現loadbalancer的配製。因爲loadbalancer的member是cluster中所有的ready node,所以當有任何node的變化時,我們需要重新配製所有的Loadbalancer Pool以體現這種變化,這也就是servicecontroller要同時監控node對象的原因。


下圖展示的是當servicecontroller調用openstack LB provider時所做的操作的時序圖。



所以最終的配置結果是針對每個service的port,在LB設備上會創建一個loadbalancer pool,VIP可以接受外部請求,Pool Member是節點IP加nodePort。LB設備和Node(即openstack VM)處於同一個aviailablity zone和VPC,其連通性在aviailablity zone創建時即得到保證。物理上,LB設備和虛擬機所在的物理機通過路由連接,路由規則保證LB設備對特定IP段的VM可見。


這樣的配製結果保證VIP接受到的所有traffic,能夠根據LB設備的規則,跳轉到kubernetes node的nodePort。





爲什麼用NodeIP:nodePort作爲LB member,如果一個cluster規模較大,如幾千個Node,LB pool會不會很大,爲什麼不用pod IP作爲LB?

  1. LB和VM之間的路由規則配製只包含VM IP段,在AZ部署的時候創建。pod ip在通常情況下是不同的range,與LB之間無法直接相通。採用node IP作爲Pool member使得底層架構openstack的配製和kubernetes的配製分離開來,不用考慮pod的IP範圍劃定。

  2. node的變化相對pod而言較少,這樣可以減少對LB 設備的訪問,LB可能會出錯。

  3. LB service type是基於node port type的,service 同時提供兩種訪問方式。

  4. 集羣中每個節點被輪詢到的機會均等,這使得每個節點需要解析iptables的機會一致,進而使iptables解析在每臺機器的資源需求一致,避免某些節點因爲iptable rules解析導致壓力過大的可能性。(與Tim Hockin面對面討論過此事)


kube-proxy: 接好最後一棒,從Node到Pod

我們知道,kubernetes服務只是把應用對外提供服務的方式做了抽象,真正的應用跑在Pod的成員container裏,我們通過LB設備已經把提交至VIP的請求轉到kubernetes nodes對應的nodePort上,那麼nodePort上的請求是如何進一步轉到提供後臺服務的Pod的呢?Kube-proxy is the secret sauce,我們來看看kube-proxy都做了什麼。


目前kube-proxy支持兩種模式,userspace和iptables,iptables模式因爲不需要userspace和kernel space的切換,在數據轉發上有更高的效率。所以從1.2版本開始,iptables是默認模式,只有當kernel版本不支持iptables時,userspace模式才需要被啓用。


kubernetes只操作了filter和nat表。

Filter

在該表中,一個基本原則是隻過濾數據包而不修改他們。filter table的優勢是小而快,可以hook到input,output和forward。這意味着針對任何給定的數據包,只有可能有一個地方可以過濾它。

NAT

此表的主要作用是在PREROUTING和POSTROUNTING的鉤子中,修改目標地址和原地址。與filter表稍有不同的是,該表中只有新連接的第一個包會被修改,修改的結果會自動apply到同一連接的後續包中。


下面是基於iptables chain的數據包流向圖




基於iptables的kube-proxy的實現代碼在pkg/proxy/iptables/proxier.go,其主要職責包括兩大塊,一塊是偵聽service更新事件,並更新service相關的iptables規則,一塊是偵聽endpoint更新事件,更新endpoint相關的iptables規則,將包請求轉入endpoint對應的Pod,如果某個service尚沒有Pod創建,那麼針對此service的請求將會被drop掉。


kube-proxy對iptables的鏈進行了擴充,自定義了KUBE-SERVICES,KUBE-NODEPORTS,KUBE-POSTROUTING,KUBE-MARK-MASQ和KUBE-MARK-DROP五個鏈,並主要通過爲 KUBE-SERVICES chain增加rule來配製traffic routing 規則。


我們可以通過對照源碼和iptables 規則表,來分析針對下面的service信息,kubernetes做了怎麼樣的iptables 配製。


kubectl get svc es1 -o yaml

apiVersion: v1

kind: Service

metadata:

 creationTimestamp: 2016-08-26T05:03:38Z

 labels:

   component: elasticsearch

 name: es1

 namespace: default

 resourceVersion: "7514"

 selfLink: /api/v1/namespaces/default/services/es1

 uid: 72f28428-6b4a-11e6-887a-42010af00002

spec:

 clusterIP: 10.0.147.93

 ports:

 - name: http

   nodePort: 32135

   port: 9200

   protocol: TCP

   targetPort: 9200

 selector:

   component: elasticsearch

 sessionAffinity: None

 type: LoadBalancer

status:

 loadBalancer:

   ingress:

   - ip: 104.197.138.206


kubectl get endpoints es1

NAME         ENDPOINTS                           AGE

es1          10.180.2.11:9200                       11d


  1. 在iptables表中,通過iptables-save可以看到在nat表中創建好的這些鏈。


:KUBE-MARK-DROP - [0:0] /*對於未能匹配到跳轉規則的traffic set mark 0x8000,有此標記的數據包會在filter表drop掉*/

:KUBE-MARK-MASQ - [0:0] /*對於符合條件的包 set mark 0x4000, 有此標記的數據包會在KUBE-POSTROUTING chain中統一做MASQUERADE*/

:KUBE-NODEPORTS - [0:0] /*針對通過nodeport訪問的package做的操作*/

:KUBE-POSTROUTING - [0:0]

:KUBE-SERVICES - [0:0] /*操作跳轉規則的主要chain*/


  1. 爲默認的prerouting,output和postrouting chain 增加規則,跳轉至kubernetes自定義的新chain。

-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES

-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES

-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING



  1. 對於KUBE-MARK-MASQ鏈中所有規則設置了kubernetes獨有MARK標記,在KUBE-POSTROUTING鏈中對NODE節點上匹配kubernetes獨有MARK標記的數據包,進行SNAT處理。


-A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000


  1. Kube-proxy接着對每個服務創建“KUBE-SVC-”鏈,並在nat表中將KUBE-SERVICES鏈中每個目標地址是service的數據包導入這個“KUBE-SVC-”鏈,如果endpoint尚未創建,KUBE-SVC-鏈中沒有規則,任何incomming packets在規則匹配失敗後會被KUBE-MARK-DROP。


-A KUBE-SERVICES ! -s 10.180.0.0/14 -d 10.0.147.93/32 -p tcp -m comment --comment "default/es1:http cluster IP" -m tcp --dport 9200 -j KUBE-MARK-MASQ  /*非Pod內部,針對cluster IP的請求,做snat操作*/

-A KUBE-SERVICES -d 10.0.147.93/32 -p tcp -m comment --comment "default/es1:http cluster IP" -m tcp --dport 9200 -j KUBE-SVC-LAS23QA33HXV7KBL  /*針對cluster IP的請求*/

-A KUBE-SERVICES -d 104.197.138.206/32 -p tcp -m comment --comment "default/es1:http loadbalancer IP" -m tcp --dport 9200 -j KUBE-FW-LAS23QA33HXV7KBL /*針對LB IP的請求,直接交由iptables轉發,防止來自cluster內部的請求給LB設備造成壓力*/

-A KUBE-FW-LAS23QA33HXV7KBL -m comment --comment "default/es1:http loadbalancer IP" -j KUBE-MARK-MASQ

-A KUBE-FW-LAS23QA33HXV7KBL -m comment --comment "default/es1:http loadbalancer IP" -j KUBE-SVC-LAS23QA33HXV7KBL

-A KUBE-FW-LAS23QA33HXV7KBL -m comment --comment "default/es1:http loadbalancer IP" -j KUBE-MARK-DROP


  1. 調用openLocalPort偵聽service nodePort,增加KUBE-NODEPORTS chain,並添加跳轉規則將此端口收到的packets轉到KUBE-SVC-LAS23QA33HXV7KBL鏈


-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS /*來自集羣外部,通過NodePort或者LoadBalancer訪問的請求*/

-A KUBE-NODEPORTS -p tcp -m comment --comment "default/es1:http" -m tcp --dport 32135 -j KUBE-MARK-MASQ

-A KUBE-NODEPORTS -p tcp -m comment --comment "default/es1:http" -m tcp --dport 32135 -j KUBE-SVC-LAS23QA33HXV7KBL


  1. Endpoint Chain,當接收到的 serviceInfo中包含endpoint信息時,爲endpoint創建跳轉規則。


-A KUBE-SVC-LAS23QA33HXV7KBL -m comment --comment "default/es1:http" -j KUBE-SEP-G4AX7RHRQVIX7P25

-A KUBE-SEP-G4AX7RHRQVIX7P25 -s 10.180.2.11/32 -m comment --comment "default/es1:http" -j KUBE-MARK-MASQ

-A KUBE-SEP-G4AX7RHRQVIX7P25 -p tcp -m comment --comment "default/es1:http" -m tcp -j DNAT --to-destination 10.180.2.11:9200


  1. 如果service類型爲nodePort,(從LB轉發至node的數據包均屬此類)那麼將KUBE-NODEPORTS鏈中每個目的地址是NODE節點端口的數據包導入這個“KUBE-SVC-”鏈;


-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS

-A KUBE-NODEPORTS -p tcp -m comment --comment "default/es1:http" -m tcp --dport 32135 -j KUBE-MARK-MASQ

-A KUBE-NODEPORTS -p tcp -m comment --comment "default/es1:http" -m tcp --dport 32135 -j KUBE-SVC-LAS23QA33HXV7KBL


  1. 如果一個service對應的pod有多個replicas,在iptables中會有多條記錄,並通過 -m statistic --mode random --probability 來控制比率。


-A KUBE-SVC-7BB4GED2QYDGC4GN -m comment --comment "kube-system/elasticsearch-logging:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-I7ND2XAHQESZGFZQ

-A KUBE-SVC-7BB4GED2QYDGC4GN -m comment --comment "kube-system/elasticsearch-logging:" -j KUBE-SEP-OECUK2RLRF65RRGG


Iptables chain支持嵌套並因爲依據不同的匹配條件可支持多種分支,比較難用標準的流程圖來體現調用關係,爲進一步歸納iptables的跳轉流程,上面的PREROUTING chain的最終跳轉規則,抽象爲下圖,僅供參考。


針對通過cluster LB轉發進來的外部請求,因爲LB設備的memeber是nodeIP: node Port,所以針對這類請求,在iptables 層走的是KUBE-NODEPORTS分支。


Ingress:更優雅的發佈服務

通過IP tables,kubernetes實現了數據的高效轉發,通過與集羣LB設備的整合,實現了服務對外的發佈,一切看起來已經working perfectly,實則不然。


全局IP不夠用怎麼辦

很多時候,我們的公共服務需要提供global routeable的IP,針對類型爲LoadBalancer的每一個service,系統都會自動分配一個全局IP。因爲kubernetes用戶擁有創建服務的自由,如果我們確保服務分配的IP都是global routeable的,很容易造成全局IP的濫用,甚至不夠用。


Dynamic dns

通常,我們提供給用戶的服務地址是域名而不是IP地址,我們需要通過某種方式(手工或者自動)在DNS server中寫入服務的dns record。雖然服務本身沒有生命週期,kubernetes的本意是希望serivce 長期存在的。因爲服務的IP是動態分配的,如果用戶重建服務,IP是會重新分配的,所以DNS server中的記錄也是動態的。這使得針對同一服務,可能存在TTL問題,客戶有可能會遭遇訪問失敗。


L7 rules

針對服務發佈,一種常見的場景是,用戶分配幾個專用的全局IP,將這些全局IP作爲服務訪問的入口,這些IP會預先在DNS server中創建好dns record。針對不同的服務,通過L7轉發規則,進行hostname/path到具體服務的跳轉。


TLS termination

因安全需求,面向用戶的服務,只支持安全訪問協議,如https。主流的LB設備都支持TLS termination,即面向用戶的服務是https的,https connection在LB設備結束,LB設備到提供服務的應用中間的連接是非secure,因爲這一段的連接往往在防火牆內部,屬於可信網絡。這種模式既提供了安全保證,又把安全配製從應用中分離出來,簡化應用開發。

Ingress

針對上述的問題,kubernetes從1.2 release開始提供Ingress來支持七層路由。對於大多數環境來講,服務和Pod通常只有在cluster網絡可以路由的IP,對於這樣的環境,來自internet的請求要麼被drop要麼被轉發到別處(在eBay我們的service IP 是global routable的)。


   internet
       |
 ------------
 [ Services ]

Ingress定義了一系列使得inbound 連接到達集羣服務的規則,在kubernetes中所處的地位如下。


    internet
       |
  [ Ingress ]
  --|-----|--
  [ Services ]


Ingress可以爲服務配製外部可達的URL,負載均衡traffic,SSL,提供基於名字的虛擬hosting。

Ingress可以指定包含TLS私鑰和證書的secret來傳遞TLS 連接所需的證書信息。secret信息可以通過如下步驟創建:


生成證書

$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout

/tmp/tls.key -out /tmp/tls.crt -subj "/CN=echoheaders/O=echoheaders"


創建證書對應的tls key和crt

$ echo "
apiVersion: v1
kind: Secret
metadata:

name: tls
data:
 tls.crt: `base64 -w 0 /tmp/tls.crt`
 tls.key: `base64 -w 0 /tmp/tls.key`
" | kubectl create -f



通過在ingress 定義中指定tls.secretName可以非常方便的指定證書,相應的,ingress controller需要實現證書上傳和配製的邏輯。


apiVersion: extensions/v1beta1
kind: Ingress
metadata:
 name: no-rules-map
spec:
 tls:
   - secretName: testsecret
 rules:
 - host: foo.bar.com
   http:
     paths:
     - path: /foo
       backend:
         serviceName: s1
         servicePort: 80

Ingress Controller

用戶通過向apiserver提交請求創建ingress對象,而我們需要對應的ingress controller來操作ingress 對象,實現Loadbalancer的配製。因爲不同的用戶環境,採用的Loadbalancer不盡相同,社區的ingress controller採用add-on的形式實現,目前有基於nginx和gclb(google cloud load balancer)的ingress controller的開源實現。


拿基於nginx的ingress controller爲例,該ingress controller監控apiserver,針對任何ingress的create 和 update事件,通過獲取ingress對應的服務,endpoint以及config,生成或更新nginx的配製文件,並reload nginx使配製即時生效。


eBay作爲e commercial公司,網絡環境與其它互聯網公司類似。區別於傳統的flat 模式,因爲traffic management的需要,我們採用兩層LB設備的拓撲結構,每個集羣有cluster local load balancer,在此之上有跨集羣的cross region load balancer。其中cluster local LB負責的是region內部的負載均衡,cross region LB負責的是跨region的負載均衡,爲避免單點故障和滿足流量管理的需求,針對同一應用,所有的cluster local LB pool的VIP都作爲cross region LB pool的memeber,形成如下圖的拓撲結構。

真對兩層loadbalancer的管理我們稱之爲Local Traffic Management,在此之上,我們需要與Global Traffic Manager整合,主要是全局DNS server(geography aware),使得用戶請求可以轉發至就近的處理節點。與GTM的整合由federation service/ingress controller來完成。


基於此拓撲,我們採用自己實現的Ingress controller來監控ingress 對象,針對任何ingress的創建和更新,查找對應的cluster local LB VIP,並且將這些VIP作爲memeber,創建cross region的LB設備的配製。同時,我們在評估可以應用在生產環境的software load balancer。

集羣聯邦:投入生產環境吧

我們分析了Kubernetes針對流量轉發的原理,介紹了將kubernetes服務對外發布的方式以及eBay的實踐,那麼部署生產系統的服務還欠缺什麼呢?跨Availability Zone的高可用。


雖然kubernetes藉助replicaset(或replicationcontroller)天然支持pod級別的高可用,但我們不能假定數據中心永遠不會出問題,數據中心也可能遭遇區域斷電,地震等大規模災難。


自1.2版本開始,kubernetes開始引入federation提供跨cluster的高可用,通過將不同AZ,不同Region的kubernetes集羣組成同一個聯邦,我們可以實現使kubernetes滿足生產系統的要求。


本文的圖一展示了聯邦層control plane的主要組件,下面的章節着重分析一下每個組件的具體作用。如果用戶希望部署跨集羣的應用和服務,建議將federation apiserver作爲唯一訪問入口,federation controller會將待創建資源轉發至相應的kubernetes集羣。

Cluster Controller

集羣要加入聯邦,首先要通過federation apiserver創建cluster對象,cluster controller負責針對集羣做healthcheck。

Federated Replicaset Controller

Replicaset是replicationcontroller的替代版本(在kubernetes中二者是等價的,但在federation control plane,replicationcontroller因爲未來會被deprecated而未獲支持)。Federated Replicaset Controller負責將用戶定義的replicaset,依據特定的調度算法,轉發至目標集羣。當用戶定義了replicaset,包括replica,pod,container等信息,可以通過annotation指定目標該replicaset在每個目標cluster要部署的replica數量。如果未指定目標集羣,那麼該replicaset會被平均分配到每個kubernetes中。

下面是一個指定特定cluster中replica數量的例子:


"federation.kubernetes.io/replica-set-preferences":

`{"rebalance": true,

"clusters": {

  "k8s-1": {"minReplicas": 10, "maxReplicas": 20, "weight": 2},

  "*": {"weight": 1}

}}

Replicaset controller同時會監控每個集羣中replicaset的狀態,確保所有集羣中的replicas總和與用戶期望吻合,如果承擔scale和failover等職責。

Federated Service Controller

Federated Service Controller負責將用戶定義的service spec轉發到所有狀態正常的集羣中(replicaset controller是依據調度算法調度,service和ingress不涉及調度)。

集羣的服務控制器接收到服務創建或更新事件後,如果該服務類型爲LoadBalancer,則調用loadbalancer provider 爲該服務分配load balancer IP,並將狀態彙報給集羣聯邦。

Federated Service Controller承擔更多的監控和協調職責,包括:

  1. 監控所有集羣的service 狀態,如果LoadBalancer IP發生變化,則更新Federation apiserver。

  2. 調用dns provider接口,將zone level,region level和global level的cname寫入 global dns server,


DNS name的pattern如下,其中federationname和dnsZoneName是在federation的配製文件中指定的聯邦名字和域名(如:ebay.com),zoneName和regionName是從每個cluster master node的label中獲取的zone和region信息。

Zone level: servicename.namespace.federationname.svc.zoneName.regionName.dnsZoneName

Region level:servicename.namespace.federationname.svc.regionName.dnsZoneName

Global level:servicename.namespace.federationname.svc.dnsZoneName


  1. 監控所有集羣中,service對應的endpoint信息。kubernetes endpoint controller會爲每個running pod創建endpoint對象,如果endpoint中存在ReadyAddress,說明該endpoint可達,federation service controller調用將該集羣的LB 信息作爲A records的IP地址寫入GLobal DNS。

  2. 維護服務狀態,如果某集羣不可達,或某集羣中的所有endpoint均爲不可達,則將該集羣對應的LB IP從dns中移除。

下圖展示了集羣拓撲下,服務創建的流程。



Federated Ingress Controller


Federated Ingress Controller的職責與工作原理非常相近,它監控Ingress的創建,更新或刪除實踐,將請求轉發至每個集羣Ingress Controller,並通過監控集羣來維護Ingress的狀態。

服務發現

集羣內部服務發現

Skydns作爲kubernetes的addon,保證集羣內部的服務發現。在1.2以及之前的版本,skydns由kube2sky,skydns和etcd組成。1.3針對dns addon做了較大改動,skydns被kubedns取代,職責是監控集羣中service和endpoint的變化,並維護基於內存查找的數據結構。etcd被移除,另外引入了dnsmasq來提高效率。


Skydns作爲built的addon,會在cluster創建時啓動。


在cluster bootstrap時指定 dns server ip


ENABLE_CLUSTER_DNS="${KUBE_ENABLE_CLUSTER_DNS:-true}"

DNS_SERVER_IP="${KUBE_DNS_SERVER_IP:-10.0.0.10}"

DNS_DOMAIN="${KUBE_DNS_DOMAIN:-cluster.local}"

DNS_REPLICAS=1


該配置會寫入kubelet配置,這使得該kubelet啓動的所有pod在做nslookup的時候,能夠向正確的dns server地址發送請求。

集羣外部服務發現

目前針對kubernetes外部訪問,kubernetes沒有天然集成DNS,但因爲kubernetes本身開放靈活的查×××的Rest API,CLI和UI,用戶可以查詢服務並根據loadbalancer IP:port或node IP:nodePort的方式訪問。


另外,集羣聯邦的服務控制器都與global dns server整合,dns name會依據既定模式自動寫入,用戶可以通過dns query獲取地址,或直接通過hostname服務。


如果定義了L7rule,則可以方便的通過預定義的URI訪問服務。



如果我們在eBay的kubernetes集羣中部署了一個web服務,在集羣聯邦的視角下,一個來自互聯網的訪問,經歷如下的轉發最終到達應用本身。



小結

kubernetes是一個高速發展的開源項目,此文適用的版本是1.4。還有更多跟服務相關的設計和開發正在進行中。一個典型的例子是Service Catalog的PR正在探討將類似cloud foundry中的Service Broker在kubernetes實現更便捷的全局服務註冊和發現。

如果您發現本文的內容有任何謬誤或者因爲kubernetes版本更新已經不再適用,請聯繫作者:[email protected]


參考資料

Kubernetes doc:http://kubernetes.io/docs/

Kubernetes source code:https://github.com/kubernetes/kubernetes/

Iptables flow chart:http://stuffphilwrites.com/2014/09/iptables-processing-flowchart/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章