了解Kubernetes中的Service和Endpoint
Srevice
Service 是將運(yùn)行在一組 Pods 上的應(yīng)用程序公開為網(wǎng)絡(luò)服務(wù)的抽象方法。如果我們使用 Deployment 部署 pod,則可以以 Deployment 為對象創(chuàng)建 Service。
在 K8S 中,每個 Pod 都有其自己唯一的 ip 地址,而 Service 可以為多個 Pod(一組)提供相同的 DNS 名,并且可以在他們直接進(jìn)行負(fù)載均衡。
假如有一組 nginx pod,如果 nginx 動態(tài)伸縮改變或因?yàn)槟承┰?ip/端口發(fā)生改變,那么其 ip 和 端口都不是固定的,而且我們很難確定它新擴(kuò)容的 pod 的地址是什么,又萬一 pod 被刪除,ip 不再可用。
又假如一組 pod 稱為前端,如 web 服務(wù),另一組 pod 稱為后端,例如 mysql。那么 前端 如何查找并跟蹤要連接的 ip 地址,以便前端可以使用工作負(fù)載的后端部分?
這真是 Service 要解決的問題。Kubernetes Service 定義了一種抽象:邏輯上的一組 Pod,一種可以訪問它們的策略 —— 通常稱為微服務(wù)。當(dāng)使用 Service 為一組 pod (Deployment 的方式創(chuàng)建的)創(chuàng)建服務(wù)時,無論我們創(chuàng)建了多少個 pod 副本,這些 pod 怎么變化,前端不需要關(guān)心它們調(diào)用了哪個后端副本,而且不需要知道后端 pod 的狀態(tài)也不需要跟蹤 pod。Service 把前后端的這種關(guān)聯(lián)抽象化,把它們解耦了。
Service 的創(chuàng)建及現(xiàn)象
現(xiàn)在按照下面的命令快速創(chuàng)建 pod,pod 將會在各個節(jié)點(diǎn)中部署運(yùn)行。
kubectl create deployment nginx --image=nginx:latest --replicas=3
kubectl expose deployment nginx --type=LoadBalancer --port=80
然后執(zhí)行命令查看 Service:
kubectl get services
也就是說外部訪問端口是 30424。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d6h nginx LoadBalancer 10.101.132.236 <pending> 80:30424/TCP 39s
這時,我們可以通過公網(wǎng)和端口訪問這個 Service。
我們可以查看此 Service 的 yaml 文件:
kubectl get service nginx -o yaml
apiVersion: v1 kind: Service metadata: creationTimestamp: "2021-04-23T07:40:35Z" labels: app: nginx name: nginx namespace: default resourceVersion: "369738" uid: 8dc49805-2fc8-4407-adc0-8e31dc24fa79 spec: clusterIP: 10.101.132.236 clusterIPs: - 10.101.132.236 externalTrafficPolicy: Cluster ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - nodePort: 30424 port: 80 protocol: TCP targetPort: 80 selector: app: nginx sessionAffinity: None type: LoadBalancer status: loadBalancer: {}
有了標(biāo)準(zhǔn)的 yaml 文件模板,我們可以很方便地修改并定制一個 Service。
我們查看通過 Deployment 創(chuàng)建的 pod:
kubectl get pods -o wide
NAME IP NODE NOMINATED NODE READINESS GATES nginx-55649fd747-9fzlr 192.168.56.56 instance-2 <none> <none> nginx-55649fd747-ckhrw 192.168.56.57 instance-2 <none> <none> nginx-55649fd747-ldzkf 192.168.23.138 instance-1 <none> <none>
注:pod 在哪個節(jié)點(diǎn)中運(yùn)行,我們是不一樣的。
當(dāng)我們通過外部網(wǎng)絡(luò)訪問時,Service 會自動提供其中一個 pod 給我們,但是這個過程較為復(fù)雜,我們這里先將表面現(xiàn)象。
------------ | | --- 公網(wǎng)ip --> | pod1 | | pod2 | | pod3 | ------------
然后我們通過命令查看 iptables 配置:
iptables-save
然后查找 random 關(guān)鍵字:
你可以看到有三個 default/nginx
, 第一個 pod 被訪問的機(jī)會都是 0.33333...
,然后 2/3 的概率中,2/3 的 0.5 的概率選擇第二個 pod,剩下的 1/3 概率選擇第三個 pod。
如果要訪問 pod,可以以任意部署了 nginx pod 的節(jié)點(diǎn)的 ip 進(jìn)行訪問。由于 master 不能部署 pod,所以不能通過 master 的 ip 進(jìn)行訪問。
當(dāng)然,它并不是直接都是 0.33333..
這樣的,iptables 的規(guī)則有點(diǎn)復(fù)雜,這里難以講清楚,我們只需要知道 外網(wǎng)能夠訪問 Service,而 Service 通過 iptable 為我們轉(zhuǎn)發(fā)流量。即使 Deployment 部署的 pod 不在同一個節(jié)點(diǎn)上, k8s 的 dns 服務(wù)等會正確處理的,我們不需要手動配置這些網(wǎng)絡(luò)。
Service 定義
在上一小節(jié)中,介紹了 Service 的創(chuàng)建方法(kubectl expose ...
),也介紹了其依賴的 iptables,這里將繼續(xù)學(xué)習(xí) Service 的定義方法。
因?yàn)橹拔覀兪峭ㄟ^ Deployment 進(jìn)行操作,直接為一個 deployment 中的 pod (副本)統(tǒng)一映射。當(dāng)然我們也可以為不同的 pod 進(jìn)行網(wǎng)絡(luò)映射。
apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: MyApp ports: - protocol: TCP port: 6666 targetPort: 80
這里我們使用了 selector
選擇器,一般 pod 的 Label 都會有 app
,表示此 pod 的名稱(一般是鏡像名稱)。port、targetPort 分別是 pod 端口、提供給外界訪問的端口。
當(dāng)我們不通過 Deployment 或者 job 等對象處理 pod 時,可以通過 selector
來選擇合適的 pod。
Service 能夠?qū)⒁粋€接收 容器或者 pod 的端口 targetPort
映射到任意的 port 端口,port 是外部可以訪問的端口。 如果使用 kubectl expose
去映射端口,會默認(rèn)隨機(jī)提供一個 30xxx
端口。而使用 yaml ,默認(rèn)情況下,targetPort
將被設(shè)置為與 port
字段相同的值。
Endpoint slices
”端點(diǎn)切片(Endpoint Slices) 提供了一種簡單的方法來跟蹤 Kubernetes 集群中的網(wǎng)絡(luò)端點(diǎn) (network endpoints)。它們?yōu)?Endpoints 提供了一種可伸縮和可拓展的替代方案。“
在 Kubernetes 中,EndpointSlice
包含對一組網(wǎng)絡(luò)端點(diǎn)的引用。 指定選擇器后控制面會自動為設(shè)置了 選擇算符 的 Kubernetes 服務(wù)創(chuàng)建 Endpoint。
也就是說創(chuàng)建 Service(帶選擇運(yùn)算符) 會自動創(chuàng)建 Endpiont。
我們查看默認(rèn)命名空間的 endpoint:
kubectl get endpoints
NAME ENDPOINTS AGE kubernetes 10.170.0.2:6443 3d7h nginx 192.168.56.24:80,192.168.56.25:80,192.168.56.26:80 59m
這些都是 pod 的 ip 和端口,也就是說,通過 Endpoint 我們跟蹤 Kubernetes 集群中的網(wǎng)絡(luò)端點(diǎn) (network endpoints)變得更加任意。不過這樣解釋是很難明白的,筆者翻了很多次資料,一點(diǎn)點(diǎn)試錯才搞懂。接下來我們一步步來上手操作,然后一點(diǎn)點(diǎn)理解這些操作的含義。
創(chuàng)建 Endpoint、Service
接下來我們手動創(chuàng)建 Service 和 Endpoint 和 ,需要先創(chuàng)建 Service ,再創(chuàng)建 Endpoint (這兩者創(chuàng)建順序可以隨意)。
Service
我們先刪除之前創(chuàng)建的 service。
kubectl delete service nginx
編寫 service.yaml 文件內(nèi)容如下如下:
apiVersion: v1 kind: Service metadata: name: nginx spec: ports: - protocol: TCP port: 6666 targetPort: 80
應(yīng)用這個 Service:
kubectl apply -f service.yaml
查看 service :
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d12h nginx ClusterIP 10.98.113.242 <none> 6666/TCP 6s
由于此 Service 沒有映射任何 pod 等,因此沒有任何用處,但是此時已經(jīng)可以給開發(fā)人員一個交待了,或者說確定下 nginx 的 Service 端口和地址。至于真正的 nginx 服務(wù),后面再確定。創(chuàng)建 Service 和 Endpoint 的順序是任意的,只是這里我們提出抽象,先約定 端口,再提供服務(wù),所以先創(chuàng)建 Service。
創(chuàng)建應(yīng)用
我們隨便找臺 worker 或者 master 節(jié)點(diǎn),創(chuàng)建一個 nginx 容器:
docker run -itd -p 80:80 nginx:latest
為什么不用 pod,直接創(chuàng)建容器?因?yàn)槲覀兲幱陂_發(fā)階段,如果把 nginx 改成 mysql,我們要 Debug 呢?測試自己的數(shù)據(jù)庫呢?要模擬數(shù)據(jù)呢?我們在生產(chǎn)時再通過 Deployment 創(chuàng)建應(yīng)用,但是此時我們可以使用自己的數(shù)據(jù)庫或者本地應(yīng)用。
官方文檔說:
- 希望在生產(chǎn)環(huán)境中使用外部的數(shù)據(jù)庫集群,但測試環(huán)境使用自己的數(shù)據(jù)庫。
- 希望服務(wù)指向另一個 名字空間(Namespace) 中或其它集群中的服務(wù)。
- 你正在將工作負(fù)載遷移到 Kubernetes。 在評估該方法時,你僅在 Kubernetes 中運(yùn)行一部分后端。
總之,我們創(chuàng)建了 Service,可以提供了抽象,至于怎么提供這個服務(wù),我們可以使用 pod ,也可以直接使用命令執(zhí)行機(jī)器上的二進(jìn)制程序,也可以通過 docker 提供。而且 mysql 可能是在外部服務(wù)提供的,或者 mysql 直接部署在宿主機(jī)上,而不使用容器和 pod,我們可以通過 Endpoint 來跟蹤 mysql 服務(wù)的端口。
然后查詢這個容器的 ip,:
docker inspect {容器id} | grep IPAddress
筆者得到的是:"IPAddress": "172.17.0.2"
,可以試試 curl 172.17.0.2
,看看是否能夠訪問 nginx,如果沒問題我們來進(jìn)行下一步。
創(chuàng)建 Endpoint
創(chuàng)建一個 endpoint.yaml 文件,內(nèi)容如下(注意替換ip為你容器訪問ip):
apiVersion: v1 kind: Endpoints metadata: name: nginx subsets: - addresses: - ip: 172.17.0.2 ports: - port: 80
然后應(yīng)用 yaml:
kubectl apply -f endpoint.yaml
查看 endpoint:
kubectl get endpoints # 不能填寫成 endpoint
然后訪問 Service 的 ip:
curl 10.99.142.242:6666
也可以通過公網(wǎng)訪問此 IP。
如果 Endpoint 需要跟蹤多個 ip (多個 pod 或者容器或者應(yīng)用),可以使用:
- addresses: - ip: 172.17.0.2 - ip: 172.17.0.3 - ip: 172.17.0.4 ... ...
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Kubernetes中Deployment的升級與回滾
- Kubernetes控制節(jié)點(diǎn)的部署
- Kubernetes部署實(shí)例并配置Deployment、網(wǎng)絡(luò)映射、副本集
- Kubernetes關(guān)鍵組件與結(jié)構(gòu)組成介紹
- 配置Kubernetes外網(wǎng)訪問集群
- 使用kubeadm命令行工具創(chuàng)建kubernetes集群
- Minikube搭建Kubernetes集群
- kubernetes中的namespace、node、pod介紹
- Kubernetes集群的組成介紹
- Dashboard管理Kubernetes集群與API訪問配置
相關(guān)文章
CentOS 出現(xiàn)no space left on device錯誤解決辦法
這篇文章主要介紹了CentOS 出現(xiàn)no space left on device錯誤解決辦法的相關(guān)資料,需要的朋友可以參考下2017-04-04Dashboard管理Kubernetes集群與API訪問配置
這篇文章介紹了Dashboard管理Kubernetes集群與API訪問配置的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04了解Kubernetes中的Service和Endpoint
這篇文章介紹了Kubernetes中的Service和Endpoint,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04Kubernetes(K8S)容器集群管理環(huán)境完整部署詳細(xì)教程-上篇
本系列文章主要介紹了Kubernetes(K8S)容器集群管理環(huán)境完整部署的詳細(xì)教程,分為上中下三篇文章,此為上篇,需要的朋友可以參考下2022-01-01使用kubeadm命令行工具創(chuàng)建kubernetes集群
這篇文章介紹了使用kubeadm命令行工具創(chuàng)建kubernetes集群的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03