服務是一種為一組功能相同的 pod 提供單一不變的接入點的資源。當服務存在時,它的 IP 地址和端口不會改變。 客戶端通過 IP 地址和端口號建立連接,
這些連接會被路由到提供該服務的任意一個 pod 上。
- pod 是短暫,會刪除增加,調度到其他節點,數量變更。
- 在 pod 啟動前會給已經調度到節點上的pod 分配 IP 地址,即客戶端提前不知道Pod的IP地址。
- 水平仲縮意味著多個 pod 可能會提供相同的服務。 無需關注提供服務 pod 的數量,以及每個Pod的IP。
1 服務與服務發現
1 創建Service 服務
創建了一個名叫kubia的服務,它將在端口80接收請求并將連接路由到具有標簽選擇器是app=kubia的pod的8080端口上。 Kubernetes服務代理截取的該連接, 在根據標簽選擇器選中的Pod 中,任意選擇了一個pod, 然后將請求轉發給它。
apiVersion: vl
kind: Service
metadata:name: kubia
spec: ports: - name: http port: 80targetPort: 8080 轉發到容器端口- name: https 同一服務暴露多個端口port: 443targetPort: 8443selector: 標簽選擇器適用的服務app: kubiasessionAffinity: ClientIP 會話親和性,統一客戶端產生的所有請求每次都指向同一個pod
kubectl get svcNAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.111.240.1 <none> 443/TCP 30d
kubia 10.111.249.153 <none> 80/TCP 6m 分配給服務的IP地址是10.111.249.153kubectl exec kubia-7nogl -- curl -s http: //10 .111. 249 .153 雙橫杠(--)代表著kubectl命令項的結束。 之后的內容是指在pod內部需要執行的命令
2 使用命名的端口
通過數字來指定端口,但是在服務中也可以給不同的端口號命名,通過名稱來指定。是即使更換端口號無須更改服務的spec, 通過改變Pod 中的 spec pod 端口號。
kind : Pod
spec : containers: - name: kubia ports : - name : http 將8080端口命名為httpcontainerPort: 8080 - name : https containerPort: 8080 apiVersion: vl
kind: Service
metadata:name: kubia
spec: ports: - name: http port: 80targetPort: http 將80端口映射到容器被稱為http 的端口- name: https port: 443targetPort: https
3 服務發現
集群內客戶端 pod 如何知道服務的 IP 和端口?
通過環境變量發現服務
pod 開始運行的時候,會初始化環境變量指向現在存在服務。 服務創建早于Pod的創建, pod 上的進程可以根據環境變量獲得服務 IP 地址和端口號。所以的Pod 都可以看到該服務。
kubectl delete po --all #在無須知道 pod 的名字的情況下就能刪除所有 pod
kubectl get po # 后面創建的服務,所以先刪除pod, pod 會自動重建
kubectl exec kubia-3inly env KUBIA SERVICE HOST=l0.111.249.153 服務的集群Ip
KUBIA SERVICE PORT=80 服務所在的端口
服務名稱中的橫杠被轉換為下畫線,并且當服務名稱用作環境變量名稱中
的前級時,所有的字母都是大寫的。
環境變量是獲得服務 IP 地址和端口 種方式。
通過 DNS 發現服務
一個pod 被稱作 kube-dns ,這個 pod 運行 DNS 服務,在集群中的其他 pod 都被配置成使用其作為 dns (通過修改每 容器的/ etc/reso conf 實現), pod 是否使用 內部的 DNS 服務器是根據 pod 中 spec dnsPolicy 屬性來決定的。
每個服務從內部 DNS 服務器中獲得 DNS 條目, 客戶端 pod 在知道服務名稱的情況下 通過全限定域名 (FQDN )來訪問,而不是訴諸于環境變量。
FQDN 的連接來訪后端數據庫服務: backend-database.default.svc.cluster.local
- backend-database 對應于服務名稱,
- default 表示服務在其中定義的名稱間,
- svc.cluster.local 是在所有集群本地服務名稱 中使用的可配置集群域后綴。
嘗試使用 FQDN 來代替 IP 去訪問 kubia 服務。另外,必須在一個存在的 pod 上才能這樣做。 客戶端仍然必須知道服務的端口號,如果并不是標準端口,客戶端可以從環境變量中獲取端口號。
2 連接集群外部的服務
不要讓服務將連接重定向到集群中的 pod ,而是讓它重定向到外部 IP 和端口。
2.1 介紹服務 endpoint
服務并不是和 pod 直接相連的。相反,有一種資源介于兩者之間-—-它就是 Endpoint 資源。
kubectl describe svc kubiakubectl get endpoints kubia
NAME ENDPOINTS AGE
kubia 10.108.l.4:8080,10.108.2.5:8080,10.108.2.6:8080 lh
服務的 endpoint 與服務解耦后,可以分別手動配置和更新他們。
2.2 手動配置服務的 endpoint
如果創建了不包含 pod選擇器的服務,Kubemetes 將不會創建 Endpoint 資源(畢竟,缺少選擇器,將不會知道服務中包含哪些 pod)。這樣就需要創建 Endpoint 資源來指定該服務的 endpoint 列表。
Endpoint是一個單獨的資源并不是服務的一個屬性。由于創建的資源中并不包含選擇器,相關的Endpoints 資源并沒有自動創建,所以必須手動創建。
Endpoint對象需要與服務具有相同的名稱,并包含該服務的目標IP地址和端口
列表。服務和Endpoint資源都發布到服務器。
在服務創建后創建的容器將包含服務的環境變量,并且與其IP : port對的所有連接都將在服務端點之間進行負載均衡。
apiVersion: vl
kind: EndpointS Endpoint的名稱必須和服務的名稱相匹配
metadata:name: external-service
subsets: - addresses:- ip: 11. 11. 11. 11 服務將連接重定向到endpoint的IP地址 (集群外部地址)- ip: 22.22.22.22ports: - port: 80 endpoint的目標端口apiVersion: vl
kind: Service
metadata: name: exernal-service
spec: ports: - port: 80 服務中沒有定義選擇器
2.3 為外部服務創建別名
手動配置服務的Endpoint來代替公開外部服務方法,有一種更簡單的方法,
就是通過其完全限定域名(FQDN)訪問外部服務。
服務創建完成后,pod可以 通 過external-service.default.svc.cluster.loca l域名(甚至是external-service)連接到外部服務。
apiVersion: vl
kind: Service
metadata: name: external-service
spec: type: ExternalName type 為ExternalNameexternalName: someapi.somecompany.com 實際服務的完全限定域名ports: - port: 80
3 將服務暴露給外部客戶端
-
將服務的類型設置成NodePort
– 每個集群節點都會在節點上打 開一個端口, 對于NodePort服務, 每個集群節點在節點本身(因此得名叫NodePort)上打開一個端口,并將在該端口上接收到的流量重定向到基礎服務。
– 該服務僅在內部集群 IP 和端口上才可訪間, 但也可通過所有節點上的專用端口訪問。 -
將服務的類型設置成LoadBalance, NodePort類型的一 種擴展。
– 這使得服務可以通過一個專用的負載均衡器來訪問, 這是由Kubernetes中正在運行的云基礎設施提供的。 負載均衡器將流量重定向到跨所有節點的節點端口。
客戶端通過負載均衡器的 IP 連接到服務。 -
創建一 個Ingress資源, 這是一 個完全不同的機制, 通過一 個IP地址公開多
個服務——它運行在 HTTP 層(網絡協議第7 層)上, 因此可以提供比工作
在第4層的服務更多的功能。
3.1 使用 NodePort 類型的服務
將一組pod公開給外部客戶端的第一種方法是創建一個服務并將其類型設置為NodePort。 通過創建NodePort服務, 可以讓Kubemetes在其所有節點上保留一個端口(所有節點上都使用相同的端口號), 并將傳入的連接轉發給作為服務部分的pod。
apiVersion: vl
kind: Service
metadata: name: kubia-nodeport
spec: type: NodePort 服務類型ports: - port: 80 服務集群端口號targetPort: 8080 背后Pod 的端口號nodePort: 30123 通過集群節點的30123端口訪問該服務selector: app: kubiakubectl get svc kubia-nodeport NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubia-nodeport 10.111.254.223 <nodes> 80:30123/TCP 2m
EXTERNAL-IP列。 它顯示nodes,表明服務可通過任何集群節點的IP地址訪問。 PORT(S)列顯示集群IP (8 0) 的內部端口和節點端口(30123), 可以通過以下地址訪問該服務:
- 10.11.254.223:80
- <lst node’s IP>:30123
- <2nd node’s IP>:30123, 等等
3.2 通過負載均衡器將服務暴露出來
云提供商上提供負載平衡器。 負載均衡器擁有自己獨一無二的可公開訪問的 IP 地址, 并將所有連接重定向到服務。可以通過負載均衡器的 IP 地址訪問服務
apiVersion: vl
kind: Service
metadata:name: kubia-loadbalancer
spec: type: LoadBalancer portS:- port: 80 targetPort: 8080selector:app: kubiakubectl get svc kubia-loadbalancerNAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubia-loadbalancer 10.111.241.153 130.211.53.173 80:32143/TCP lm
3.3 了解外部連接的特性
防止不必要的網絡跳數,服務配置為僅將外部通信重定向到接收連接的節點上運行的pod來阻止此額外跳數。
spec: exernalTrafficPolicy: Local
- 如果服務定義包含此設置, 并且通過服務的節點端口打開外部連接, 則服務代理將選擇本地運行的pod。 如果沒有本地pod存在, 則連接將掛起。
- 使用local外部流量策略的服務可能會導致跨pod的負載分布不均衡。