一、為什么需要 Service?
-
Pod 的動態性:?Pod 是 Kubernetes 調度的基本單位。它們可能因為故障、滾動更新、擴縮容等原因隨時被創建或銷毀。
-
Pod IP 的不穩定性:?每個 Pod 都有自己的 IP 地址,但當 Pod 重建時,IP 地址會改變。
-
訪問需求:?集群內部的其他應用(前端訪問后端)、集群外部用戶(訪問 Web 應用)需要一種穩定可靠的方式來訪問一組提供相同功能的 Pod。
二、Service 是什么?
1.定義
? ? ? ?Service 是 Kubernetes 中的一個 API 對象,它定義了一組 Pod 的邏輯集合以及訪問這組 Pod 的策略(通常通過標簽選擇器?selector
)。service主要解決Pod的動態變化,提供統一的訪問入口。
2.核心功能
-
穩定訪問端點:?為動態變化的 Pod 集合提供一個虛擬的、穩定的?IP 地址 (ClusterIP) 或 DNS 名稱。
-
負載均衡:?基于iptables或者ipvs,將到達 Service 的請求自動分發到其后端健康的 Pod 上。
-
服務發現:基于標簽管理器關聯后端的Pod列表,?讓其他應用能夠輕松地找到并連接到這組 Pod。
3.endpoints對象
? ? ? ?由 Kubernetes?自動創建和管理(通常無需手動操作),與同名的 Service 關聯,存儲了當前匹配 Service 標簽選擇器的所有健康 Pod 的 IP:Port?列表,Service 的負載均衡器就是基于這個列表進行流量轉發的
三、service類型以及是用場景
1.ClusterIP
1.1 用途
? ? ? ?默認類型,為 Service 分配一個集群內部的虛擬 IP (VIP),僅限集群內部的其他 Pod 或 Service 訪問,用于后端服務間的內部通信(如前端訪問后端 API、數據庫訪問)。
1.2 示例代碼
[root@master-1 service]# cat 01-svc-ClusterIP.yaml
apiVersion: v1
kind: Service
metadata:name: myweb-service
spec:# 聲明Service的類型,主要有:ClusterIP, NodePort, LoadBalancer.# ClusterIP:# k8s集群內部使用的類型,僅供K8S集群內部訪問,外部無法訪問。默認值。# NodePort:# 在ClusterIP基礎之上,監聽了所有的worker節點的端口號,可供K8s集群外部訪問。# LoadBalancer:# 適合在公有云上對k8s集群外部暴露應用。type: ClusterIP# 聲明標簽選擇器,即該svc資源關聯哪些Pod,并將其加入到ep列表selector:apps: web# 配置端口映射ports:# 指定Service服務本身的端口號- port: 8888# 后端Pod提供服務的端口號targetPort: 80
[root@master-1 service]# cat nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx
spec:replicas: 3#基于標簽關聯pod,會關聯apps=test或者apps=prod的podselector:matchExpressions:- key: appsvalues: - "test"- "web"operator: Intemplate:metadata:#為pod設置了兩個標簽labels:apps: webspec:containers:- name: nginximage: nginx:latestimagePullPolicy: IfNotPresent#部署
[root@master-1 service]# kubectl apply -f .
#查看pod,service,endpoints
[root@master-1 service]# kubectl get pods,svc,endpoints -o wide
1.3?驗證結果
? ? ? ?如圖所示,該Service自動生成了集群內部專用的虛擬IP地址(ClusterIP)和端口。
? ? ? ?使用該ClusterIP地址(10.0.0.69:8888)成功訪問到了集群內部署的Web業務服務。
2.?NodePort
2.1 用途
? ? ? ?k8s集群外部訪問,NodePort機制在ClusterIP基礎上,將服務以<節點IP>:<靜態端口>
的形式暴露到集群外部,該端口可自動分配(30000-32767)或手動指定。端口范圍可以在api-server中查看。
查看端口范圍:
2.2 示例代碼
[root@master-1 service]# cat 02-svc-NodePort.yaml
apiVersion: v1
kind: Service
metadata:name: myweb-nodeport
spec:# 指定svc的類型為NodePort,也就是在默認的ClusterIP基礎之上多監聽所有worker節點的端口而已。type: NodePort# 基于標簽選擇器關聯Podselector:apps: web# 配置端口映射ports:# 指定Service服務本身的端口號- port: 8888# 后端Pod提供服務的端口號targetPort: 80# 如果是NodePort類型,可以指定NodePort監聽的端口號,若不指定,則隨機生成。nodePort: 30080#端口范圍以上提供了查詢方法,可以修改,修改api-server啟動時的參數.#nodePort: 8080#部署
[root@master-1 service]# kubectl apply -f 02-svc-NodePort.yaml
service/myweb-nodeport created
#查看
[root@master-1 service]# kubectl get pods,svc,endpoints -o wide
2.3 驗證結果
? ? ? ?如圖所示,該Service除了創建集群內部的ClusterIP和端口外,還開放了指定的NodePort端口30080用于外部訪問。
? ? ? ?通過任意節點IP加NodePort端口(如192.168.91.21:30080)均可成功訪問部署的Web業務服務。
? ? ?通過外部瀏覽器訪問(http://192.168.91.22:30080/),也可以成功訪問到web業務。
3.LoadBalance
3.1 用途
? ? ? ?在?NodePort
?基礎上,利用云提供商的基礎設施(如 AWS ELB, GCP Load Balancer, Azure LB)自動創建一個外部負載均衡器。該負載均衡器會將外部流量導向?NodePort
?Service (進而到 Pod)。通常用于公有云上向公網暴露服務。
3.2 示例代碼
#01 創建loadbalancer的service
[root@master-1 service]# cat 03-services-LoadBalance.yaml
kind: Service
apiVersion: v1
metadata:name: svc-loadbalancer
spec:# 指定service類型為LoadBalancer,注意,一般用于云環境type: LoadBalancerselector:app: webports:- protocol: TCPport: 80targetPort: 80nodePort: 30080#02 配置云環境的應用負載均衡器
#添加監聽器規則,比如訪問負載均衡器的80端口,反向代理到30080端口。
#簡而言之,就是訪問云環境的應用服務器的哪個端口,把他反向代理到K8S集群的node端口為30080即可。#03 用戶訪問應用負載均衡器的端口
#用戶直接訪問云環境應用服務器的80端口即可,請求會自動轉發到云環境nodePort的30080端口。
4.ExternalName
4.1 用途
? ? ? ?將 Service 映射到一個外部 DNS 名稱?(如?my.database.example.com
)。不創建任何代理或負載均衡。通過訪問該 Service 的 DNS 名稱,解析到外部服務的 DNS 名稱。
4.2 示例代碼
[root@master-1 service]# cat 04-svc-ExternalName.yaml
apiVersion: v1
kind: Service
metadata:name: svc-externalname
spec:# svc類型type: ExternalName# 指定外部域名externalName: www.baidu.com[root@master-1 service]# kubectl apply -f 04-svc-ExternalName.yaml
[root@master-1 service]# kubectl get svc svc-externalname
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc-externalname ExternalName <none> www.baidu.com <none> 98s#啟動容器后訪問名為"svc-externalname"的svc,請求會被cname到"www.baidu.com"的A記錄
5.類型對比
類型 | 訪問范圍 | 適用場景 | 依賴條件 |
ClusterIP | 僅集群內部 | 微服務間通信 | 無 |
NodePort | 集群外部 | 開發測試/臨時暴露 | 節點防火墻開放端口 |
LoadBalancer | 公網訪問 | 生產環境云集群 | 云廠商支持 |
ExternalName | 集群內部 | 集成外部服務(如RDS) | DNS 插件 |
四、?Service底層原理
1.?Service 工作流程
-
Endpoint 控制器:監控 Pod 狀態,更新 Service 關聯的 Endpoints 列表。
-
kube-proxy:監聽 Service/Endpoint 變化,生成代理規則。
-
流量轉發:
-
iptables 模式:默認,通過 NAT 規則轉發(適合小規模集群)。
-
IPVS 模式:基于哈希表,支持 RR/LC/WRR 等算法,萬級服務性能更優。
-
2.kube-proxy的工作模式
2.1 定義
? ?kube-proxy
?是運行在每個 Node 上的網絡代理組件,是實現集群內部的服務發現和負載均衡的關鍵。它監聽 API Server 的 Service 和 Endpoint 變化,并配置本機的網絡規則將流量路由到正確的后端 Pod。kube-proxy 支持多種工作模式,每種模式都有其特點和適用場景。
2.2 工作模式
01 iptables
?模式 (默認)
工作流程:
- kube-proxy 使用?
iptables
?規則配置 Linux 內核的 netfilter 包過濾框架。 -
當請求到達 Service 的 ClusterIP:Port?時,
iptables
?規則會進行 DNAT (目標地址轉換),將目標 IP:Port?修改為隨機選擇的一個后端 Pod 的 IP:Port。
優點:?效率高,工作在操作系統內核層。
缺點:
- 規則數量龐大(尤其是 Service 和 Pod 很多時),可能影響性能。
- 負載均衡算法單一(默認是隨機)。
- 不支持更高級的負載均衡策略(如會話保持、最少連接)。
-
如果第一個選中的 Pod 無響應,不會自動重試其他 Pod(除非應用層重試)。
02?ipvs
?模式 (推薦)
? ? ? ?kube-proxy 使用 Linux 內核的?IP Virtual Server
?模塊,IPVS 是 L4 負載均衡器,專門設計用于高性能負載均衡。
優點:
- 性能最高:?比 iptables 模式具有更低的延遲和更高的吞吐量,尤其在大規模集群中優勢明顯。
- 支持多種負載均衡算法:?
rr
?(輪詢),?lc
?(最少連接),?dh
?(目標地址哈希),?sh
?(源地址哈希),?sed
?(最短預期延遲),?nq
?(永不排隊)。 -
支持會話保持:?通過?
sh
?(源地址哈希) 算法實現。 -
更高效的數據結構:?規則數量與 Service/Endpoint 數量呈線性關系,而非像 iptables 那樣可能是指數關系。
缺點:
- 需要 Linux 內核支持 IPVS 模塊 (現代內核通常已支持)。
03 工作模式切換
#修改kube-proxy配置文件
[root@node-1 ~]# cat >/etc/kubernetes/cfg/kube-proxy.yaml<<EOF
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 192.168.91.21
clientConnection:kubeconfig: /etc/kubernetes/cfg/kube-proxy.kubeconfig
clusterCIDR: 10.0.0.0/24
healthzBindAddress: 192.168.91.21:10256
kind: KubeProxyConfiguration
metricsBindAddress: 192.168.91.21:10249
mode: "ipvs"
EOF#切換工作模式mode: "ipvs" 或者 mode: "iptables"
#修改完后重啟kube-proxy
[root@node-1 bin]# systemctl restart kube-proxy
? ? ? 重啟后重新部署web應用,如下圖,發現service基于rr輪詢的方式分發流量到pod
五、常見問題排查
1.無法通過 Service 訪問 Pod
-
檢查 Service?
selector
?是否與 Pod?labels
?匹配 。
kubectl describe svc <service-name>
kubectl get pods --show-labels
- 檢查 Endpoints 對象是否包含預期的 Pod IP,空的 Endpoints 意味著 selector 不匹配或 Pod 未就緒 (
readinessProbe
?失敗)。
kubectl get endpoints <service-name>
- 檢查 Pod 是否正常運行且監聽目標端口
kubectl logs <pod-name>
kubectl exec -it <pod-name> -- netstat -tuln
kubectl exec -it <pod-name> -- ss -tuln
- 檢查 Pod 的?
readinessProbe
?是否配置正確且通過。 - 檢查 kube-proxy 是否在所有節點正常運行。
systemctl status kube-proxy
kubectl get pods -n kube-system -l component=kube-proxy
- 檢查節點防火墻規則 (如果使用?
iptables
/ipvs
?模式)。
2.NodePort 無法從外部訪問
- 檢查 NodePort Service 是否已創建?
#看?PORT(S)?列是否有?80:3xxxx/TCP
kubectl get svc -A
-
確認使用的 Node IP 和 NodePort 正確。
-
檢查節點的防火墻/安全組是否允許外部訪問該 NodePort。
-
檢查 kube-proxy 是否在節點上正常運行
六、總結
優先使用 DNS 進行服務發現:避免環境變量的順序依賴問題。
內部服務使用?ClusterIP
:除非有特殊需求,否則這是最安全、最標準的內部通信方式
外部訪問:
- 開發/測試:
NodePort
。 - 公有云生產環境:
LoadBalancer
?(通常配合 Ingress Controller 處理 L7 流量)。 - 需要暴露多個 HTTP 服務:使用?
Ingress
?+?ClusterIP
?Service。
使用?ipvs
?代理模式:?尤其是在大型集群或需要高性能、多種負載均衡算法、會話保持時。
合理使用?Headless Service
:?主要用于 StatefulSets 或需要直接訪問所有 Pod IP 的場景。
配置?readinessProbe
:?確保 Service 只將流量路由到真正準備好接收請求的 Pod。
利用 Network Policies:?在 Service 之上實施網絡層面的安全控制。
監控:?監控 Service 的 Endpoints 變化、DNS 解析延遲、kube-proxy 狀態等。