入門Kubernetes-Service
一、前言
前一篇文章通過 Deployment 實現了Pod中服務實現滾動更新/回滾等操作;在真實應用場景中,需要將一組Pod提供給外部訪問。而且Pod生命週期是短暫的,在 Pod 的生命週期過程中,比如它建立或銷燬, IP 地址都會發生變化。不能使用傳統的部署方式使用IP方式訪問。
所以需要將Deployment 建立的Pod組統一提供一個訪問入口,需要提供給外部的使用者去呼叫的。此時就需要服務發現。那麼在k8s中怎麼實現呢?—Service
二、服務-Service
1、Service 的定義
Service是 k8s 的核心資源型別之一,Service是將執行在一組Pods上的應用程式公開為網路服務的抽象方法。
Service資源基於標籤選擇器將一組Pod定義成一個邏輯組合,並通過自己的IP地址和埠排程代理請求到組內的Pod物件
2、Service 的工作方式
在 k8s 叢集中,每個 Node 執行一個kube-proxy
程序。kube-proxy
負責為 Service 實現了一種 VIP(虛擬 IP)的形式,而不是ExternalName
的形式。
kube-proxy 這個元件始終監視著apiserver中有關service的變動資訊,獲取任何一個與service資源相關的變動狀態,通過watch監視,一旦有service資源相關的變動和建立,kube-proxy都要轉換為當前節點上的能夠實現資源排程規則(例如:iptables、ipvs)
-
userspace 代理模式
kube-proxy 會監視 Kubernetes 控制平面對 Service 物件和 Endpoints 物件的新增和移除操作。 對每個 Service,它會在本地 Node 上開啟一個埠(隨機選擇)。 任何連線到“代理埠”的請求,都會被代理到 Service 的後端Pods
中的某個上面(如Endpoints
所報告的一樣)。 使用哪個後端 Pod,是 kube-proxy 基於SessionAffinity
來確定的。
最後,它配置 iptables 規則,捕獲到達該 Service 的clusterIP
(是虛擬 IP) 和Port
的請求,並重定向到代理埠,代理埠再代理請求到後端Pod。
預設情況下,使用者空間模式下的 kube-proxy 通過輪轉演算法選擇後端。
-
iptables 代理模式
這種模式,kube-proxy
會監視 Kubernetes 控制節點對 Service 物件和 Endpoints 物件的新增和移除。 對每個 Service,它會配置 iptables 規則,從而捕獲到達該 Service 的clusterIP
和埠的請求,進而將請求重定向到 Service 的一組後端中的某個 Pod 上面。 對於每個 Endpoints 物件,它也會配置 iptables 規則,這個規則會選擇一個後端組合。
預設的策略是,kube-proxy 在 iptables 模式下隨機選擇一個後端。
使用 iptables 處理流量具有較低的系統開銷,因為流量由 Linux netfilter 處理, 而無需在使用者空間和核心空間之間切換。 這種方法也可能更可靠。
如果 kube-proxy 在 iptables 模式下執行,並且所選的第一個 Pod 沒有響應, 則連線失敗。 這與使用者空間模式不同:在這種情況下,kube-proxy 將檢測到與第一個 Pod 的連線已失敗, 並會自動使用其他後端 Pod 重試。
你可以使用 Pod就緒探測器驗證後端 Pod 可以正常工作,以便 iptables 模式下的 kube-proxy 僅看到測試正常的後端。 這樣做意味著你避免將流量通過 kube-proxy 傳送到已知已失敗的 Pod。
-
ipvs 代理模式
在ipvs
模式下,kube-proxy 監視 Kubernetes 服務和端點,呼叫netlink
介面相應地建立 IPVS 規則, 並定期將 IPVS 規則與 Kubernetes 服務和端點同步。 該控制迴圈可確保IPVS 狀態與所需狀態匹配。訪問服務時,IPVS 將流量定向到後端Pod之一。
IPVS代理模式基於類似於 iptables 模式的 netfilter 掛鉤函式, 但是使用雜湊表作為基礎資料結構,並且在核心空間中工作。 這意味著,與 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 重定向通訊的延遲要短,並且在同步代理規則時具有更好的效能。 與其他代理模式相比,IPVS 模 式還支援更高的網路流量吞吐量。
IPVS 提供了更多選項來平衡後端 Pod 的流量。 這些是:
-
rr
:輪替(Round-Robin)lc
:最少連結(Least Connection),即開啟連結數量最少者優先dh
:目標地址雜湊(Destination Hashing)sh
:源地址雜湊(Source Hashing)sed
:最短預期延遲(Shortest Expected Delay)nq
:從不排隊(Never Queue)
3、Service的使用
a、服務型別:建立Service物件,指定型別為NodePort
apiVersion: v1 kind: Service # 定義Kubernetes資源的型別為Service metadata: name: k8sdemoweb-service # 定義資源的名稱 spec: selector: # 指定對應的Pod app: k8demosweb # 指定Pod的標籤為k8sweb ports: - protocol: TCP # 協議型別 port: 80 # 指定Service訪問的埠 targetPort: 80 # 指定Service轉發請求的埠 nodePort: 31001 type: NodePort # 指定Service的型別,在這裡使用NodePort來對外訪問
對一些應用的某些部分(如前端),可能希望將其暴露給 Kubernetes 叢集外部 的 IP 地址
KubernetesServiceTypes
允許指定你所需要的 Service 型別,預設是ClusterIP
。
Type
的取值以及行為如下:
-
-
ClusterIP
:通過叢集的內部 IP 暴露服務,選擇該值時服務只能夠在叢集內部訪問。 這也是預設的ServiceType
。 -
NodePort
:通過每個節點上的 IP 和靜態埠(NodePort
)暴露服務。NodePort
服務會路由到自動建立的ClusterIP
服務。 通過請求<節點 IP>:<節點埠>
,你可以從叢集的外部訪問一個NodePort
服務。 -
LoadBalancer
:使用雲提供商的負載均衡器向外部暴露服務。 外部負載均衡器可以將流量路由到自動建立的NodePort
服務和ClusterIP
服務上。 -
ExternalName
:通過返回CNAME
和對應值,可以將服務對映到externalName
欄位的內容(例如,foo.bar.example.com
)。 無需建立任何型別代理。
-
b、Headless Services(無頭服務)
有時不需要或不想要負載均衡,以及單獨的 Service IP。 遇到這種情況,可以通過指定 Cluster IP(spec.clusterIP
)的值為"None"
來建立Headless
Service。
- 帶選擇算符的服務
對定義了選擇算符的無頭服務,Endpoint 控制器在 API 中建立了 Endpoints 記錄, 並且修改 DNS 配置返回 A 記錄(IP 地址),通過這個地址直接到達Service
的後端 Pod 上。
- 無選擇算符的服務
對沒有定義選擇算符的無頭服務,Endpoint 控制器不會建立Endpoints
記錄。 然而 DNS 系統會查詢和配置,無論是:
-
- 對於
ExternalName
型別的服務,查詢其 CNAME 記錄 - 對所有其他型別的服務,查詢與 Service 名稱相同的任何
Endpoints
的記錄
- 對於
三、使用Service訪問應用:
訪問在前面建立的服務:由於本機IP為:192.168.0.109,直接訪問192.168.0.109:31001 時,直接訪問失敗。安裝Service型別的描述,該Service型別為NodePort;應該就可以直接訪問成功。
但由於本機的k8s環境是使用:minikube 執行在Docker環境中。真實的k8s Node不是本機,導致訪問失敗。
啟動服務訪問:
//開啟服務訪問 PS > minikube service k8sdemoweb-service |-----------|--------------------|-------------|---------------------------| | NAMESPACE | NAME | TARGET PORT | URL | |-----------|--------------------|-------------|---------------------------| | default | k8sdemoweb-service | 80 | http://192.168.49.2:31001 | |-----------|--------------------|-------------|---------------------------| * Starting tunnel for service k8sdemoweb-service. |-----------|--------------------|-------------|------------------------| | NAMESPACE | NAME | TARGET PORT | URL | |-----------|--------------------|-------------|------------------------| | default | k8sdemoweb-service | | http://127.0.0.1:29752 | |-----------|--------------------|-------------|------------------------| * 正通過預設瀏覽器開啟服務 default/k8sdemoweb-service... ! Because you are using a Docker driver on windows, the terminal needs to be open to run it.
訪問地址:http://127.0.0.1:29752
通過上圖看到,訪問應用通過Service負載到不同的Pod節點上。