Kubernetes是google開源的容器編排器,非常適合當下火熱的微服務架構,在容器編排領域,正逐步建立起主導地位。本文主要針對kubernetes service做一些剖析,先簡單介紹一下基本概念。
基本概念
Pod:kubernetes最小調度單位,是一組容器集合,可以理解成一個容器。
replication controller:副本控制器,保證pod個數始終與設定值一致,如果遇到pod故障,節點離線等,控制器會刪除這些狀態異常的pod,重新調度產生新的pod。通過label匹配pod,在Auto Scaling、滾動升級中發揮重要作用。
service:服務,是一個虛擬概念,邏輯上代理後端pod。眾所周知,pod生命週期短,狀態不穩定,pod異常後新產生的pod ip會發生變化,之前pod的訪問方式均不可達。通過service對pod做代理,service有固定的ip和port,ip:port組合自動關聯後端pod,即使pod發生改變,kubernetes內部更新這組關聯關係,使得service能夠匹配到新的pod。這樣,通過service提供的固定ip,使用者再也不用關心需要訪問哪個pod,以及pod會否發生改變,大大提高了服務品質。如果pod使用rc建立了多個副本,那麼service就能代理多個相同的pod,通過kube-proxy,實現負載平衡。
通過下面模版定義一個service,這個service代理了所有具有"app": "MyApp"標籤的pod,服務對外連接埠是80,服務ip在建立service的時候產生,也可以指定,這組ip:port在service的生命週期裡保持固定。訪問ip:port的流量會被重新導向到後端pod的9376連接埠上,就是targetPort指定的。
{ "kind": "Service", "apiVersion": "v1", "metadata": { "name": "my-service" }, "spec": { "selector": { "app": "MyApp" }, "ports": [ { "protocol": "TCP", "port": 80, "targetPort": 9376 } ] }}
說到service,繞不開的一個組件是kube-proxy,實際上這個組件是專門為service服務的,每個minion節點都會運行一個kube-proxy。通過kube-proxy,實現流量從service到pod的轉寄,kube-proxy還可以實現簡單的負載平衡功能。kube-proxy有多種代理模式,下面是userspace方式,kube-proxy在minion節點上為每一個服務建立一個臨時連接埠,service的ip:port過來的流量轉寄到這個臨時連接埠上,kube-proxy會用內部的負載平衡機制(一般是輪尋),選擇一個後端pod,然後建立iptables,把流量匯入到某個pod裡。
服務發現在微服務架構裡,服務之間經常要進行通訊,服務發現就是解決不同服務之間通訊的問題。比如一個nginx的pod,要訪問一個mysql服務,就需要知道mysql服務的ip的port,擷取ip和port的過程就是服務發現。Kubernetes 支援兩種服務發現模式,分別是環境變數和dns。
環境變數: pod建立的時候,服務的ip和port資訊以環境變數的形式注入到pod裡,比如pod建立時有一個redis-master服務,服務ip地址是10.0.0.11,port是6379,則會把下面一系列環境變數注入到pod裡,通過這些環境變數訪問redis-master服務。 REDIS_MASTER_SERVICE_HOST=10.0.0.11REDIS_MASTER_SERVICE_PORT=6379REDIS_MASTER_PORT=tcp://10.0.0.11:6379REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379REDIS_MASTER_PORT_6379_TCP_PROTO=tcpREDIS_MASTER_PORT_6379_TCP_PORT=6379REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11
dns伺服器: Kubernetes叢集內會內建一個dns伺服器,service建立成功後,會在dns伺服器裡匯入一些記錄,想要訪問某個服務,通過dns伺服器解析出對應的ip和port,從而實現服務訪問。
外部服務對於一些前端應用,可能需要暴露服務到外網,而其他服務只運行在內部。Service的Types欄位可以指定服務類型,預設的是ClusterIP類型。這是叢集內部的服務類型,服務ip是一個內部ip;NodePort 和LoadBalancer是兩種外部服務類型。
NodePortNodePort類型,會為服務在每個minion節點上暴露一個連接埠,通過節點ip和節點port可以訪問這個服務,同時服務依然會有ClusterIP類型的ip和連接埠,內部通過ClusterIP方式訪問,外部通過NodePort方式訪問。 LoadBalancer如果kubernetes叢集運行在第三方雲平台上,比如openstack,那麼可以通過外部的loadbalancer來暴露服務,還能借用第三方的負載平衡機制實現負載平衡。以openstack為例,藉助neutron的lbaas,訪問服務的流量會被直接轉寄到後端的pod,跳過了內建的kube-proxy負載平衡。