Service 是 Kubernetes 的核心資源類型之一,通常被看作微服務(wù)的一種實(shí)現(xiàn)。它事實(shí)上是一種抽象:通過規(guī)則定義出由多個(gè) Pod 對象組合而成的邏輯集合,以及訪問這組 Pod 的策略。Service 關(guān)聯(lián) Pod 資源的規(guī)則要借助標(biāo)簽選擇器完成。
Service 對象的 IP 地址(可稱為 ClusterIP 或 ServiceIP)是虛擬 IP 地址,由 Kubernetes 系統(tǒng)在 Service 對象創(chuàng)建時(shí)在專用網(wǎng)絡(luò)(Service Network)地址中自動(dòng)分配或由用戶手動(dòng)指定,并且在 Service 對象的生命周期中保持不變。Service 基于端口過濾到達(dá)其 IP 地址的客戶端請求,并根據(jù)定義將請求轉(zhuǎn)發(fā)至其后端的 Pod 對象的相應(yīng)端口之上,因此這種代理機(jī)制也稱為“端口代理”或四層代理,工作于 TCP/IP 協(xié)議棧的傳輸層。
Service 并不直接連接至 Pod 對象,它們之間還有一個(gè)中間層——Endpoints 資源對象,該資源對象是一個(gè)由 IP 地址和端口組成的列表,這些 IP 地址和端口則來自由 Service 的標(biāo)簽選擇器匹配到的 Pod 對象。
一個(gè) Service 對象對應(yīng)于工作節(jié)點(diǎn)內(nèi)核之中的一組 iptables 或/和 ipvs 規(guī)則,這些規(guī)則能夠?qū)⒌竭_(dá) Service 對象的 ClusterIP 的流量調(diào)度轉(zhuǎn)發(fā)至相應(yīng) Endpoint 對象指向的 IP 地址和端口之上。內(nèi)核中的 iptables 或 ipvs 規(guī)則的作用域僅為其所在工作節(jié)點(diǎn)的一個(gè)主機(jī),因而生效于集群范圍內(nèi)的 Service 對象就需要在每個(gè)工作節(jié)點(diǎn)上都生成相關(guān)規(guī)則,從而確保任一節(jié)點(diǎn)上發(fā)往該 Service 對象請求的流量都能被正確轉(zhuǎn)發(fā)。
每個(gè)工作節(jié)點(diǎn)的 kube-proxy 組件通過 API Server 持續(xù)監(jiān)控著各 Service 及其關(guān)聯(lián)的 Pod 對象,并將 Service 對象的創(chuàng)建或變動(dòng)實(shí)時(shí)反映至當(dāng)前工作節(jié)點(diǎn)上相應(yīng)的 iptables 或 ipvs 規(guī)則上。
Service 對象的 ClusterIP 事實(shí)上是用于生成 iptables 或 ipvs 規(guī)則時(shí)使用的 IP 地址,它僅用于實(shí)現(xiàn) Kubernetes 集群網(wǎng)絡(luò)內(nèi)部通信,且僅能夠以規(guī)則中定義的轉(zhuǎn)發(fā)服務(wù)的請求作為目標(biāo)地址予以響應(yīng),這也是它之所以被稱作虛擬 IP 的原因之一。kube-proxy 把請求代理至相應(yīng)端點(diǎn)的方式有 3 種:userspace、iptables 和 ipvs。
userspace 代理模型,kube-proxy 負(fù)責(zé)跟蹤 API Server 上 Service 和 Endpoints 對象的變動(dòng)(創(chuàng)建或移除),并據(jù)此調(diào)整 Service 資源的定義。對于每個(gè) Service 對象,它會(huì)隨機(jī)打開一個(gè)本地端口(運(yùn)行于用戶空間的 kube-proxy 進(jìn)程負(fù)責(zé)監(jiān)聽),任何到達(dá)此代理端口的連接請求都將被代理至當(dāng)前 Service 資源后端的各 Pod 對象,至于哪個(gè) Pod 對象會(huì)被選中則取決于當(dāng)前 Service 資源的調(diào)度方式,默認(rèn)調(diào)度算法是輪詢(round-robin)。
iptables 代理模型,客戶端發(fā)來請求將直接由相關(guān)的 iptables 規(guī)則進(jìn)行目標(biāo)地址轉(zhuǎn)換(DNAT)后根據(jù)算法調(diào)度并轉(zhuǎn)發(fā)至集群內(nèi)的 Pod 對象之上,而無須再經(jīng)由 kube-proxy 進(jìn)程進(jìn)行處理。
ipvs 代理模型,kube-proxy 跟蹤 API Server 上 Service 和 Endpoints 對象的變動(dòng),并據(jù)此來調(diào)用 netlink 接口創(chuàng)建或變更 ipvs(NAT)規(guī)則,它與 iptables 規(guī)則的不同之處僅在于客戶端請求流量的調(diào)度功能由 ipvs 實(shí)現(xiàn),余下的其他功能仍由 iptables 完成。
ipvs 代理模型中 Service 的服務(wù)發(fā)現(xiàn)和負(fù)載均衡功能均基于內(nèi)核中的 ipvs 規(guī)則實(shí)現(xiàn)。類似于 iptables,ipvs 也構(gòu)建于內(nèi)核中的 netfilter 之上,但它使用 hash 表作為底層數(shù)據(jù)結(jié)構(gòu)且工作于內(nèi)核空間,因此具有流量轉(zhuǎn)發(fā)速度快、規(guī)則同步性能好的特性,適用于存在大量 Service 資源且對性能要求較高的場景。ipvs 代理模型支持 rr、lc、dh、sh、sed 和 nq 等多種調(diào)度算法。
Service 資源都可統(tǒng)一根據(jù)其工作邏輯分為 ClusterIP、NodePort、LoadBalancer 和 ExternalName 這 4 種類型。
通過將 Service 映射至由 externalName 字段的內(nèi)容指定的主機(jī)名來暴露服務(wù),此主機(jī)名需要被 DNS 服務(wù)解析至 CNAME 類型的記錄中。此種類型不是定義由 Kubernetes 集群提供的服務(wù),而是把集群外部的某服務(wù)以 DNS CNAME 記錄的方式映射到集群內(nèi),從而讓集群內(nèi)的 Pod 資源能夠訪問外部服務(wù)的一種實(shí)現(xiàn)方式,這種類型的 Service 沒有 ClusterIP 和 NodePort,沒有標(biāo)簽選擇器用于選擇 Pod 資源,也不會(huì)有 Endpoints 存在。
若需要將 Service 資源發(fā)布至集群外部,應(yīng)該將其配置為 NodePort 或 Load-Balancer 類型,而若要把外部的服務(wù)發(fā)布于集群內(nèi)部供 Pod 對象使用,則需要定義一個(gè) ExternalName 類型的 Service 資源。