一、理論介紹
1.1、3W 法則
1、是什么?
- Service 是一種為一組功能相同的 pod 提供單一不變的接入點的資源。當 Service 存在時,它的IP地址和端口不會改變。客戶端通過IP地址和端口號與 Service 建立連接,這些連接會被路由到提供該 Service 的任意一個pod上。通過這種方式,客戶端不需要知道每個單獨的pod的地址,這樣這些pod就可以在集群中隨時被創建或移除。
2、為什么需要?
- Pod 的 IP 地址經常變化。
- Pod 的 IP 在集群外無法訪問。
- Pod 實例之間的負載均衡。
3、局限性
- Service 是一種四層代理。
- 所謂四層,是針對 OSI 七層網絡模型來說的。四層對應的是TCP/UDP協議,也就常說的IP+端口。
- 因此,所謂四層代理就是基于IP+端口的負載均衡;七層就是基于URL等應用層信息的負載均衡。
1.2、基礎信息
kubectl explain svc
# svc 是 service 的縮寫
- apiVersion:當前資源使用的 api 版本,與 VERSION 一致。
- kind:資源類型,跟 KIND 保持一致。
- metadata:元數據。定義資源名稱、標簽、注解等。
- spec:規范、規約。
- status:最近觀察到的 Service 狀態。由系統填充。只讀。
1.3、ServiceSpec 規約
kubectl explain svc.spec
allocateLoadBalancerNodePorts?? ?<boolean> | |
clusterIP?? ?<string> | |
clusterIPs?? ?<[]string> | |
externalIPs?? ?<[]string> | |
externalName?? ?<string> | |
externalTrafficPolicy?? ?<string> | |
healthCheckNodePort?? ?<integer> | |
internalTrafficPolicy?? ?<string> | |
ipFamilies?? ?<[]string> | |
ipFamilyPolicy?? ?<string> | |
loadBalancerClass?? ?<string> | |
loadBalancerIP?? ?<string> | |
loadBalancerSourceRanges?? ?<[]string> | |
ports?? ?<[]ServicePort> | 端口 |
publishNotReadyAddresses?? ?<boolean> | |
selector?? ?<map[string]string> | 標簽選擇器 |
sessionAffinity?? ?<string> | |
sessionAffinityConfig?? ?<SessionAffinityConfig> | |
trafficDistribution?? ?<string> | |
type?? ?<string> | 類型 |
1.4、Service 類型
kubectl explain svc.spec.type
type 類型有四種:
- ClusterIP:虛擬集群IP。通過集群的內部 IP 暴露服務,選擇該值時服務只能夠在集群內部訪問。默認類型。
- NodePort:節點端口。通過每個節點上的 IP 和靜態端口(NodePort)暴露服務。 NodePort 服務會路由到自動創建的 ClusterIP 服務。 通過請求 <節點 IP>:<節點端口>,你可以從集群的外部訪問一個 NodePort 服務。
- ExternalName:外部命名空間。通過返回 CNAME 和對應值,可以將服務映射到 externalName 字段的內容(例如,foo.bar.example.com)。 無需創建任何類型代理。
- LoadBalancer:負載均衡。使用云提供商的負載均衡器向外部暴露服務。 外部負載均衡器可以將流量路由到自動創建的 NodePort 服務和 ClusterIP 服務上。Kubernetes 不直接提供負載均衡組件; 你必須提供一個,或者將你的 Kubernetes 集群與某個云平臺集成。
其中 ClusterIP 為默認方式,只能集群內部訪問。NodePort、LoadBalancer 則是向外暴露服務的同時將流量路由到 ClusterIP服務。ExternalName 則是CNAME方式進行服務映射。
1.5、Service 端口
kubectl explain svc.spec.ports
appProtocol?? ?<string> | |
name?? ?<string> | |
nodePort?? ?<integer> | service 在節點映射的端口。 type 類型是?NodePort 或?LoadBalancer 時才指定。 通常是系統分配,也可以自己指定,范圍在?30000-32767。 |
port?? ?<integer> -required- | Service 將公開的端口。 |
protocol?? ?<string> | 協議。協議類型有 SCTP, TCP, UDP。默認 TCP。 |
targetPort?? ?<IntOrString> | pod 端口 |
二、鏡像準備
2.1、鏡像準備
docker pull mirrorgooglecontainers/serve_hostname:latest
docker pull kubedb/mysql-tools:8.0.14
docker pull curlimages/curl
?2.2、鏡像導出
docker save -o serve_hostname.tar.gz mirrorgooglecontainers/serve_hostname:latest
docker save -o mysql-tools.tar.gz mysql-tools:8.0.14
docker save -o curl.tar.gz curlimages/curl
?2.3、鏡像導入工作節點 containerd
# k8s31node1 執行
[root@k8s31node1 ~]# ctr -n=k8s.io images import serve_hostname.tar.gz
[root@k8s31node1 ~]# ctr -n=k8s.io images ls|grep serve_hostname
[root@k8s31node1 ~]# ctr -n=k8s.io images import mysql-tools.tar.gz
[root@k8s31node1 ~]# ctr -n=k8s.io images ls|grep mysql-tools
[root@k8s31node1 ~]# ctr -n=k8s.io images import curl.tar.gz
[root@k8s31node1 ~]# ctr -n=k8s.io images ls|grep curl# k8s31node2 執行
[root@k8s31node2 ~]# ctr -n=k8s.io images import serve_hostname.tar.gz
[root@k8s31node2 ~]# ctr -n=k8s.io images ls|grep serve_hostname
[root@k8s31node2 ~]# ctr -n=k8s.io images import mysql-tools.tar.gz
[root@k8s31node2 ~]# ctr -n=k8s.io images ls|grep mysql-tools
[root@k8s31node2 ~]# ctr -n=k8s.io images import curl.tar.gz
[root@k8s31node2 ~]# ctr -n=k8s.io images ls|grep curl
?2.4、環境準備
?假設有如下三個節點的 K8S 集群:
k8s31master 是控制節點
k8s31node1、k8s31node2?是工作節點
容器運行時是 containerd
三、實踐
3.1、創建 ClusterIP 類型 Service
假設有這么一個部署:
apiVersion: apps/v1
kind: Deployment
metadata:name: hostnames
spec:selector:matchLabels:app: hostnamesreplicas: 3template:metadata:labels:app: hostnamesspec:containers:- name: hostnamesimage: mirrorgooglecontainers/serve_hostnameimagePullPolicy: IfNotPresentports:- containerPort: 9376protocol: TCP
mirrorgooglecontainers/serve_hostname 這個應用的作用,就是每次訪問 9376 端口時,返回它自己的 hostname。
3.1.1、在不同的節點上訪問 PodIP:port
返回了各個 pod 自己的 hostname。
可以看到,在集群內的不同節點上, Pod IP 都能訪問。
3.1.2、在不同的容器內訪問 PodIP:port
假設現在新起一個 pod:
apiVersion: v1
kind: Pod
metadata:name: curl-tools
spec:containers:- name: curl-toolsimage: curlimages/curl:latestimagePullPolicy: IfNotPresentcommand: ["/bin/sh", "-c", "while true; do echo 'Hello from curl-tools'; sleep 30; done"]
- curlimages/curl 是一個 curl 調試工具。
- command:容器啟動后執行的命令,這里使用一個無限循環,每隔 30?秒輸出一次?
Hello from curl-tools。
- 像 Alpine 鏡像,或者基于?Alpine 制作的工具鏡像,容器內沒有運行服務,需要啟動后運行一個無限循環,防止容器被 K8S 殺掉。
?進入容器訪問 hostnames 服務:
kubectl exec -it curl-tools -- curl 10.244.165.57:9376
可以看到,在集群內的容器之間,Pod IP 都能訪問。
3.1.3、在集群外訪問 PodIP:port
我們再起一臺虛擬機 docker1,IP 地址跟?K8S 集群在一個網段。
訪問 hostnames 服務:
可以看到,即使?docker1 的?IP 地址跟?K8S 集群在一個網段,但 docker1 沒有用類似 kubeadm join 加入過集群,Pod IP 是不能訪問的。
3.1.4、誤刪一個 pod?
kubectl delete pod hostnames-d9d7674f5-2djvf
?可以看到,K8S 又幫我們重新拉起了一個新 pod:hostnames-d9d7674f5-n7mtn,以維持我們 Deployment 控制器希望的副本數?replicas: 3。但是這個新 pod 的 IP,跟原來舊 pod 的 IP 是不一樣的。
倘若我們是調用這些 pod 服務的客戶端,在 pod 擴縮容期間,維護這些 pod IP 的代價是非常大的。所以我們需要一個穩定的接入層,它的 IP 地址、端口不變,讓它來代理后端的一組 pod,而我們程序只需要跟這個接入層打交道就可以。這個接入層,就是 Service。
?3.1.5、新建一個?ClusterIP 類型 Service
apiVersion: v1
kind: Service
metadata:name: hostnames-svc
spec:type: ClusterIPselector:app: hostnamesports:- port: 80protocol: TCPtargetPort: 9376
- spec.selector:Service 通過標簽選擇器來查找 app=hostnames 標簽的 Pod。
- port: 80? 表示該服務的可用端口。
- targetPort: 9376 表示服務將連接轉發的 Pod 端口。
- port 跟 targetPort 配合起來表示?這個 Service 的 80 端口,代理的是 Pod 的 9376 端口。
- ?查看 service
kubectl get svc
- ?訪問 service
連續三次不斷地訪問 Service 的 CLUSTER-IP 和 端口 80:
- 依次返回了三個 Pod 的 hostname。
- 請求 Service IP:port 跟直接訪問 Pod IP:port 的結果一樣,這說明 Service 可以把請求代理到它所關聯的后端 Pod。
- 這也印證了 Service 提供的是 Round Robin (輪詢) 方式的負載均衡。
- 查看 endpoints
?K8S 創建 Service 的時候,如果 Service 帶有 selector 選擇器,則?K8S 會創建一個與?Service 同名的 Endpoints 對象。selector 選中的 Pod 的 IP 和 端口,都會記錄在?Endpoints 中。當一個新的 Pod 被創建并且它的標簽匹配了某個 Service 的選擇器時,該 Pod 的 IP 和端口會被添加到對應的 Endpoints 對象中;同樣地,當 Pod 被刪除時,它也會從 Endpoints 中移除。Endpoints 通常由 Service 引用, 以定義可以將流量發送到哪些 Pod。
kubectl get ep hostnames-svc
# ep endpoints 縮寫
kubectl get ep hostnames-svc -oyaml
?需要注意的是,只有處于 Running 狀態,且 readinessProbe 檢查通過的 Pod,才會出現在 Service 的 Endpoints 列表里。并且,當某一個 Pod 出現問題時,Kubernetes 會自動把它從 Service 里摘除掉。
?3.1.6、集群外訪問 Service ClusterIP:port
?在集群外的虛擬機 192.168.40.111 訪問 10.103.168.44:80
可以看到,訪問不到 Service。如果希望集群外的機器能訪問,需要創建 NodePort 類型的 Service 或 LoadBalancer 類型的 Service。
?3.1.7、通過 FQDN 訪問服務
在 Kubernetes (K8S) 環境中,FQDN(Fully Qualified Domain Name,完全限定域名)是指集群內部服務的完整域名,它包含了服務名、命名空間以及可選的服務后綴,用于唯一標識集群中的一個服務。
當你在 Kubernetes 中創建一個服務時,Kubernetes 會為該服務分配一個 FQDN。這個 FQDN 的格式通常是:
<service-name>.<namespace>.svc.cluster.local
- service-name 是你給服務起的名字。
- namespace 是服務所在的命名空間,默認是 default,除非你在創建服務時指定了不同的命名空間。
- svc 是固定的,代表這是一個服務。
- cluster.local 是集群的默認域,大多數情況下是這個值,但如果你的集群配置了不同的域名,則會有所不同。
例如,我們上面?hostnames-svc 服務,它的完整域名是:
hostnames-svc.default.svc.cluster.local
我們在集群的其他 pod 中,就可以使用這個域名訪問服務:
可以省略命名空間和 svc.cluster.local,因為已經幫我們解析了。
在節點上不能解析這個域名,Kubernetes 的 DNS 服務通常只服務于集群中的 Pod,而節點本身并不自動配置為使用它:
使用 FQDN 可以讓 Kubernetes 集群中的其他服務通過 DNS 解析來找到并訪問你的服務,而不需要知道服務的具體 IP 地址。這有助于實現服務發現和服務間的通信,并且提高了服務部署的靈活性和可移植性。在 Kubernetes 中,CoreDNS 通常被用來提供這種 DNS 服務發現的功能。
?3.1.8、Service 原理
我們以 3.1.2 小節 curl-tools 容器(假設運行在 node2 上)訪問 Service Cluster_IP : port 為例,來講解 Service 的工作原理。
首先介紹一下幾個組件:
- kube - proxy:是 Kubernetes 集群中每個節點上運行的一個組件。它負責在節點上維護網絡規則,實現了 Service 的代理和負載均衡功能,確保客戶端可以通過 Service 的 IP 和端口訪問到對應的后端 Pod。kube-proxy?會監視 API Server 中 Service 和 Endpoints 對象的變化。當有新的 Service 或 Endpoints 對象創建、更新或刪除時,kube-proxy 會收到通知,并相應地更新節點上的網絡規則(iptables)。kube-proxy 有?iptables 模式跟 ipvs 模式。
- Service:是 Kubernetes 提供的一種抽象層,它定義了一組 Pod 的邏輯集合以及訪問這些 Pod 的策略。Service 為 Pod 提供了一個穩定的 IP 地址(ClusterIP)和端口號,使得客戶端可以通過這個穩定的地址來訪問后端的 Pod,而不需要關心具體 Pod 的 IP 地址和生命周期。
- Endpoints:是 Kubernetes 中的一個資源對象,它記錄了 Service 對應的所有后端 Pod 的 IP 地址和端口信息。每當 Pod 的數量或狀態發生變化時,Endpoints 對象會自動更新。
curl-tools 容器內訪問 Service IP : port 流程:
- node2 上的 kube-proxy?監視 API Server 中 Service 和 Endpoints 對象的變化,更新節點上的網絡規則(iptables)。
- 客戶端 curl-tools 請求?Service IP : port,請求包目的地 Destination 初始設置為服務的IP和端口(10.103.168.44:80)。發送到網絡之前,node2 的內核會根據配置在該節點上的 iptables 規則處理數據包。內核會檢查數據包是否匹配任何這些 iptables 規則。其中有個規則規定如果有任何數據包的目的地IP等于10.103.168.44、目的地端口等于80,那么數據包的目的地IP和端口應該被替換為隨機選中的 hostnames pod的IP和端口。
- 本例中的數據包滿足規則,故而它的IP:端口被改變了。假設 pod hostnames-d9d7674f5-tjwzp 被輪詢算法隨機選中了,所以數據包的目的地IP變更為 10.244.165.56,端口改為9376(Service中定義的目標端口)。就好像是客戶端 curl-tools 直接發送數據包給 hostnames-d9d7674f5-tjwzp 而不是通過 Service。
3.1.9、iptables Or IPVS
kube-proxy 通過 iptables 處理 Service 的過程,其實需要在宿主機上設置相當多的 iptables 規則。而且,kube-proxy 還需要在控制循環里不斷地刷新這些規則來確保它們始終是正確的。
當宿主機上有大量 Pod 的時候,成百上千條 iptables 規則不斷地被刷新,很明顯會影響到整體性能。
IPVS 模式的工作原理,其實跟 iptables 模式類似。區別只在于當我們創建了前面的 Service 之后,kube-proxy 首先會在宿主機上創建一個虛擬網卡(叫作:kube-ipvs0),并為它分配 Service VIP 作為 IP 地址,如下所示:
?
而接下來,kube-proxy 就會通過 Linux 的 IPVS 模塊,為這個 IP 地址設置三個 IPVS 虛擬主機,并設置這三個虛擬主機之間使用輪詢模式 (rr) 來作為負載均衡策略。我們可以通過 ipvsadm 查看到這個設置,如下所示:
ipvsadm -ln
-l:這是 ipvsadm 命令的一個選項,代表 “list”,即列出當前 IPVS 規則。使用該選項可以查看已經配置的虛擬服務器(Virtual Server)及其對應的真實服務器(Real Server)信息。
-n:同樣是 ipvsadm 命令的選項,代表 “numeric”,表示以數字形式顯示地址和端口,而不是將 IP 地址解析為域名、端口號解析為服務名。使用這個選項可以避免 DNS 解析和服務名查找的過程,更直觀地顯示規則信息。
可以看到,這三個 IPVS 虛擬主機的 IP 地址和端口,對應的正是三個被代理的 Pod。rr 表示輪詢 round robin。
這時候,任何發往 10.103.168.44:80 的請求,就都會被 IPVS 模塊轉發到某一個后端 Pod 上了。 而相比于 iptables,IPVS 在內核中的實現其實也是基于 Netfilter 的 NAT 模式,所以在轉發這一層上,理論上 IPVS 并沒有顯著的性能提升。但是,IPVS 并不需要在宿主機上為每個 Pod 設置 iptables 規則,而是把對這些“規則”的處理放到了內核態,從而極大地降低了維護這些規則的代價。
不過需要注意的是,IPVS 模塊只負責上述的負載均衡和代理功能。而一個完整的 Service 流程正常工作所需要的包過濾、SNAT 等操作,還是要靠 iptables 來實現。
?3.1.10、Endpoints 與?readinessProbe 就緒探針
- 編寫服務 svc-hellok8s.yaml
apiVersion: v1
kind: Service
metadata:name: hellok8s-svc
spec:type: ClusterIPselector:app: hellok8sports:- port: 80protocol: TCPtargetPort: 8080
- ?執行并監控
kubectl apply -f svc-hellok8s.yaml
# -w 表示持續監控,注意這個時候不要關閉終端
kubectl get ep hellok8s-svc -w
- 編寫部署??deploy-hellok8s.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: hellok8s
spec:replicas: 3selector:matchLabels:app: hellok8sversion: "1.0"template:metadata:labels:app: hellok8sversion: "1.0"spec:containers:- name: hellok8simage: hellok8s:1.0imagePullPolicy: IfNotPresentports:- containerPort: 8080readinessProbe:httpGet:path: /port: 8080initialDelaySeconds: 15periodSeconds: 10
initialDelaySeconds: 表示容器啟動后延遲多少秒,開始就緒探測。這里特意設置成 15 秒,為了觀察就緒探針沒有完成時,?Endpoints 的列表里,會不會有 pod 的 IP。
- ?在另一個終端運行部署
kubectl apply -f deploy-hellok8s.yaml
可以看到,在 pod 還沒就緒前,endpoints 列表里面是不會有 pod IP 的。
- 刪除部署
kubectl delete -f deploy-hellok8s.yaml
可以看到 pod 被刪除,endpoints 列表也會移除 pod IP。
?3.1.11、原理圖
3.2、創建 NodePort 類型 Service
假設我們現在有如下 三個 pod:
kubectl get pod -l app=hostnames -owide
?IP 分別是?10.244.9.57、10.244.9.59、10.244.165.3
3.2.1、編寫服務
apiVersion: v1
kind: Service
metadata:name: hostnames-nodeport
spec:type: NodePortselector:app: hostnamesports:- port: 80protocol: TCPtargetPort: 9376nodePort: 32000
- spec.type:NodePort?通過每個節點上的 IP 和靜態端口(NodePort)暴露服務。
- spec.ports.nodePort:指定節點上暴露的端口 32000。
?3.2.2、訪問服務
在瀏覽器中、或者任何能訪問到集群三個節點的機器上,訪問 節點IP:32000
curl 192.168.40.10:32000
curl 192.168.40.20:32000
curl 192.168.40.30:32000
3.2.3、原理
每一個節點的防火墻規則里面,都有一條 節點IP:32000 的轉發規則。轉發到三個?pod上。
創建 NodePort 類型的 Service 會默認幫我們創建 Cluster_IP
它的數據轉發方式,跟 3.1 節講的是一樣的,走 kube-ipvs0 虛擬網橋。
如果節點上有安裝 docker,NodePort 不會走節點IP端口,會默認走 docker0 網橋,然后數據再通過 docker0 轉發給 pod。
3.3、創建 ExternalName 類型 Service
3.3.1、場景分析
Service,是無法代理到不同名稱空間下的 Pod 的。
假設我們默認名稱空間下,有三個這樣的 Pod:
kubectl get pod -l app=hostnames -A --show-labels
在名稱空間?external-demo 下,有這樣一個 Service:
apiVersion: v1
kind: Service
metadata:name: external-svc-anamespace: external-demo
spec:type: ClusterIPselector:app: hostnamesports:- port: 80protocol: TCPtargetPort: 9376
?Service 在?external-demo 名稱空間下,它的標簽選擇器選擇了上面的三個 Pod。
?查看 Service 詳情:
kubectl describe svc external-svc-a -n=external-demo
可以看到它并沒有代理到任何 Pod。
?此時,不管是在節點上直接訪問 Service?ClusterIP?10.100.211.127:80
還是在?external-demo 名稱空間下的 Pod:
apiVersion: v1
kind: Pod
metadata:name: curl-toolsnamespace: external-demo
spec:containers:- name: curl-toolsimage: curlimages/curl:latestimagePullPolicy: IfNotPresentcommand: ["/bin/sh", "-c", "while true; do echo 'Hello from curl-tools'; sleep 30; done"]
kubectl exec -it -n=external-demo curl-tools -- /bin/sh
都訪問不到任何 Pod。
那么,external-demo 名稱空間下的 Pod 要如何通過 Service 訪問 default 名稱空間下的 Pod 呢?
3.3.2、ExternalName 類型 Service
在 external-demo 名稱空間下新建一個 Service:
apiVersion: v1
kind: Service
metadata:name: external-svc-bnamespace: external-demo
spec:type: ExternalNameexternalName: hostnames-svc.default.svc.cluster.localselector:app: hostnamesports:- port: 80protocol: TCP
- type:?ExternalName。
- externalName:指定 default 名稱空間下的完全限定服務名。
相當于給 hostnames-svc 服務創建了一個軟連接。
- targetPort:在這種情況下可以忽略。
kubectl get svc -n=external-demo
此時,在 external-demo 名稱空間下的 curl-tools 就可以直接訪問這個服務,請求會被代理到 default 名稱空間下的 Pod:
3.4、使用自定義?Endpoints 連接集群外部服務
假設集群外的服務器 192.168.40.111 上運行著一個 mysql,端口 3306。
集群內的 pod 要如何使用服務名來連接這臺 mysql?
3.4.1、創建沒有選擇器的服務
apiVersion: v1
kind: Service
metadata:name: mysql-svc
spec:type: ClusterIPports:- port: 3306
?定義?個名為 mysql-svc 的服務,它將接收 3306 端口傳入的連接。并沒有為服務定義?個pod 選擇器。
?3.4.2、為沒有選擇器的服務創建 Endpoints 資源
Endpoints 是?個單獨的資源并不是服務的?個屬性。由于創建的 Service 中并不包含選擇器,相關的 Endpoints 資源并沒有自動創建,所以必須手動創建。
apiVersion: v1
kind: Endpoints
metadata: name: mysql-svc
subsets:
- addresses:- ip: 192.168.40.111ports:- port: 3306
Endpoints 對象需要與服務具有相同的名稱 mysql-svc,并包含該服務的目標 IP 地址和端口列表。服務和 Endpoints 資源都發布到服務器后,這樣服務就可以像具有 pod 選擇器那樣的服務正常使用。
?3.4.3、啟動 mysql-tools 工具
apiVersion: v1
kind: Pod
metadata:name: mysql-tools
spec:containers:- name: mysql-toolsimage: kubedb/mysql-tools:8.0.14imagePullPolicy: IfNotPresentcommand: ["/bin/sh", "-c", "while true; do echo 'Hello from curl-tools'; sleep 30; done"]
3.4.4、進入 mysql-tools pod 內部連接服務
kubectl exec -it mysql-tools -- /bin/sh
mysql -h mysql-svc -uroot -p123456
?3.5、CoreDNS 介紹
CoreDNS 是 Kubernetes 集群中的關鍵組件,負責提供 DNS 服務。
3.5.1、鏡像準備
docker pull mkrishnamurthy/nslookup
docker save -o nslookup-tools.tar.gz mkrishnamurthy/nslookup:latest
?3.5.2、鏡像導入工作節點 containerd
# k8s31node1 執行
[root@k8s31node1 ~]# ctr -n=k8s.io images import nslookup-tools.tar.gz
[root@k8s31node1 ~]# ctr -n=k8s.io images ls|grep nslookup-tools# k8s31node2 執行
[root@k8s31node2 ~]# ctr -n=k8s.io images import nslookup-tools.tar.gz
[root@k8s31node2 ~]# ctr -n=k8s.io images ls|grep nslookup-tools
?3.5.3、啟動 nslookup 工具
apiVersion: v1
kind: Pod
metadata:name: nslookup-tools
spec:containers:- name: nslookup-toolsimage: mkrishnamurthy/nslookup:latestimagePullPolicy: IfNotPresentcommand: ["/bin/sh", "-c", "while true; do echo 'Hello from nslookup-tools'; sleep 30; done"]
mkrishnamurthy/nslookup 鏡像安裝了 nslookup 命令。nslookup?是一個用于查詢 DNS 記錄的命令行工具,它可以幫助用戶檢查域名解析是否正常。
?進入 pod 執行命令:
[root@k8s31master]# kubectl exec -it nslookup-tools -- /bin/bash
bash-4.2# nslookup hostnames-svc
?10.103.168.44 是 hostnames-svc 服務的 ClusterIP
Server 10.96.0.10 是 K8S 集群 DNS 服務的?ClusterIP
這個 Service 后面代理著兩個 Pod
這兩個 Pod 就是實際提供 DNS 解析服務的 Pod
- 在 Kubernetes 集群中,CoreDNS 的服務(kube-dns)是一個 ClusterIP 類型的服務,背后由多個 CoreDNS Pod 提供支持。
- 當集群中的 Pod 發起 DNS 查詢時,Kubernetes 會通過 Service 的負載均衡機制,將請求分發到后端的 CoreDNS Pod 上。多個 CoreDNS 實例可以分擔查詢負載,避免單個實例因流量過大而成為性能瓶頸。
四、參考資料
官網:虛擬 IP 和服務代理
Kubernetes教程(五)---Service 的幾種訪問方式