關(guān)于 K8s Service,你真的理解了嗎?詳細(xì)版了解一下
一、相關(guān)概念
1. 什么是Service?
在 Kubernetes 中,Service 是一種抽象的資源,它提供了穩(wěn)定的訪問(wèn)接口,將外部或集群內(nèi)部的流量路由到對(duì)應(yīng)的 Pod 上。 Pod 是 Kubernetes 中的基本調(diào)度單元,但它們是臨時(shí)的,IP 地址和生命周期都可能發(fā)生變化。Service 為 Pod 提供一個(gè)穩(wěn)定的訪問(wèn)方式,解決了 Pod 的動(dòng)態(tài) IP 問(wèn)題。
Kubernetes 的 Service 有幾種不同的類(lèi)型,能夠幫助我們根據(jù)不同的需求將服務(wù)暴露給外部用戶(hù)或者集群內(nèi)部的其他服務(wù)。
2. Service的核心概念
(1) Pod 和 Service
在 Kubernetes 中,Pod 是部署應(yīng)用的基本單位。每個(gè) Pod 都會(huì)有一個(gè) IP 地址,但這個(gè) IP 地址只在 Pod 生命周期內(nèi)有效。當(dāng) Pod 被銷(xiāo)毀、重建或調(diào)度到其他節(jié)點(diǎn)時(shí),Pod 的 IP 地址會(huì)發(fā)生變化。這使得直接依賴(lài) Pod IP 地址來(lái)訪問(wèn)服務(wù)變得不可行。
Service 解決了這個(gè)問(wèn)題,它為一組 Pod 提供一個(gè)穩(wěn)定的訪問(wèn)入口,不會(huì)隨著 Pod 的變化而變化。Service 將流量路由到匹配標(biāo)簽的 Pod 上,并為客戶(hù)端提供一個(gè)固定的 IP 地址和 DNS 名稱(chēng)來(lái)訪問(wèn)這些 Pod。
(2) Service 和 Endpoints
Endpoints 是與 Service 關(guān)聯(lián)的資源,它記錄了與該 Service 匹配的 Pod 的 IP 地址。當(dāng) Service 創(chuàng)建時(shí),Kubernetes 會(huì)根據(jù)標(biāo)簽選擇器(selector)找到符合條件的 Pod,并自動(dòng)生成 Endpoints,確保流量能夠正確地路由到這些 Pod。
容易混淆的幾個(gè)端口的關(guān)系:
3. Service 類(lèi)型
Kubernetes 提供了幾種不同的 Service 類(lèi)型,適應(yīng)不同的網(wǎng)絡(luò)通信需求。每種類(lèi)型都有自己的特性和應(yīng)用場(chǎng)景。
(1) ClusterIP(默認(rèn)類(lèi)型)
功能:ClusterIP 類(lèi)型的 Service 只能在集群內(nèi)部訪問(wèn),外部無(wú)法直接訪問(wèn)該服務(wù)。它為服務(wù)分配一個(gè)虛擬 IP 地址(ClusterIP),客戶(hù)端通過(guò)該 IP 與服務(wù)進(jìn)行通信。
用途:適用于集群內(nèi)部的微服務(wù)通信,常見(jiàn)于服務(wù)間通信。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app # 選擇標(biāo)簽為 app=my-app 的 Pod
ports:
- protocol: TCP
port: 80 # 服務(wù)對(duì)外暴露的端口
targetPort: 8080 # 實(shí)際服務(wù)運(yùn)行的 Pod 端口
clusterIP: 10.96.0.1 # Kubernetes 自動(dòng)分配 ClusterIP
這個(gè) Service 會(huì)將請(qǐng)求轉(zhuǎn)發(fā)到符合條件的 Pod 上(標(biāo)簽為 app=my-app)。 訪問(wèn)該服務(wù)時(shí),Kubernetes 會(huì)自動(dòng)通過(guò)虛擬 IP 地址 10.96.0.1 來(lái)路由流量。
(2) NodePort
功能:NodePort 類(lèi)型的 Service 將服務(wù)暴露到每個(gè) Node 上的指定端口,外部客戶(hù)端可以通過(guò)訪問(wèn)任意 Node 的 IP 地址和指定端口來(lái)訪問(wèn)該服務(wù)。
用途:適用于開(kāi)發(fā)和測(cè)試場(chǎng)景,或者希望通過(guò)某個(gè)特定端口暴露服務(wù)的場(chǎng)景。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80 # 外部客戶(hù)端訪問(wèn)的端口
targetPort: 8080 # Pod 上的目標(biāo)端口
nodePort: 30001 # 每個(gè) Node 暴露的端口
type: NodePort
在這個(gè)例子中,nodePort 為 30001,可以通過(guò)集群中任意一個(gè)節(jié)點(diǎn)的 NodeIP:30001 訪問(wèn)服務(wù)。
(3) LoadBalancer
功能:LoadBalancer 類(lèi)型的 Service 會(huì)在云環(huán)境中創(chuàng)建一個(gè)外部負(fù)載均衡器,將外部流量自動(dòng)分發(fā)到集群中的多個(gè) Pod 上。
用途:適用于需要對(duì)外暴露服務(wù),并且需要自動(dòng)負(fù)載均衡的生產(chǎn)環(huán)境。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80 # 外部訪問(wèn)的端口
targetPort: 8080 # Pod 上的目標(biāo)端口
type: LoadBalancer
創(chuàng)建該 Service 后,Kubernetes 會(huì)自動(dòng)請(qǐng)求云平臺(tái)(如 AWS、阿里云,華為云)創(chuàng)建一個(gè)負(fù)載均衡器,將流量轉(zhuǎn)發(fā)到集群中的 Pod 上。
(4) ExternalName
功能:ExternalName 類(lèi)型的 Service 將流量路由到外部的 DNS 名稱(chēng),而不是內(nèi)部的 Pod。
用途:適用于需要訪問(wèn)集群外部服務(wù)(如外部數(shù)據(jù)庫(kù)或第三方 API)的場(chǎng)景。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: ExternalName
externalName: example.com # 外部服務(wù)的 DNS 名稱(chēng)
在這種配置下,my-service 將請(qǐng)求轉(zhuǎn)發(fā)到 example.com,而不是集群內(nèi)部的 Pod。
二、Service 工作原理
1. Pod 的 IP 和生命周期管理
每個(gè) Pod 都有一個(gè)自己的 IP 地址,當(dāng) Pod 被刪除或重新調(diào)度時(shí),IP 地址會(huì)發(fā)生變化。Kubernetes 會(huì)監(jiān)控這些變化,并確保流量能夠正確地轉(zhuǎn)發(fā)到新的 Pod 上。
2. 標(biāo)簽選擇器
Service 通過(guò)標(biāo)簽選擇器來(lái)匹配需要暴露的 Pod。當(dāng) Service 創(chuàng)建時(shí),Kubernetes 會(huì)根據(jù)該標(biāo)簽選擇器找到所有匹配的 Pod,并通過(guò) Endpoints 記錄它們的 IP 地址。
3. DNS 解析
Kubernetes 會(huì)為每個(gè) Service 分配一個(gè) DNS 名稱(chēng),Pod 可以通過(guò) DNS 名稱(chēng)訪問(wèn) Service,而不需要關(guān)心具體的 IP 地址。這使得服務(wù)發(fā)現(xiàn)變得非常容易。
三、Service常用操作
1. 創(chuàng)建service
# 命令行創(chuàng)建,通過(guò)暴露deployment創(chuàng)建Service
kubectl expose deployment <deployment-name> --type=<service-type> --port=<port> --target-port=<target-port>
kubectl expose deploy nginx --port=80 --target-port=80 --type=NodePort
# 基于yaml文件創(chuàng)建
# 創(chuàng)建Service資源清單
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30080 # 指定節(jié)點(diǎn)上的端口
type: type: NodePort
# 創(chuàng)建
kubectl apply -f service.yaml
2. 查看service
# 查看所有service信息
kubectl get svc
kubectl get svc -o wide -n prod
# 查看指定service的詳細(xì)信息
kubectl get svc nginx -o yaml -n prod
kubectl describe svc nginx -n prod
# 查看Service的endpoint信息
kubectl get endpoints <service-name>
kubectl get ep nginx
3. 編輯更新Service
注意:修改后,service會(huì)立即重啟
kubectl edit service <service-name>
kubectl edit svc nginx -n prod
# 更新端口
kubectl patch service my-service -p '{"spec":{"ports":[{"port":80,"targetPort":8081}]}}'
4. 刪除Service
# 命令行刪除
kubectl delete svc <service-name>
kubectl delete svc nginx
# 基于yaml文件刪除
kubectl delete -f service.yaml
Service為 Pod 提供了穩(wěn)定的訪問(wèn)入口,解決了 Pod 生命周期變化帶來(lái)的網(wǎng)絡(luò)問(wèn)題。通過(guò)不同類(lèi)型的 Service(如 ClusterIP、NodePort、LoadBalancer 和 ExternalName),Kubernetes 可以滿(mǎn)足各種網(wǎng)絡(luò)通信需求。
在生產(chǎn)環(huán)境中,Service 不僅可以幫助實(shí)現(xiàn)服務(wù)間的可靠通信,還能為外部用戶(hù)提供負(fù)載均衡和高可用的訪問(wèn)入口。