K8S Service 原理、圖例——深度好文

一、理論介紹

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 流程:

  1. node2 上的 kube-proxy?監視 API Server 中 Service 和 Endpoints 對象的變化,更新節點上的網絡規則(iptables)。
  2. 客戶端 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和端口。
  3. 本例中的數據包滿足規則,故而它的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 的幾種訪問方式

    本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
    如若轉載,請注明出處:http://www.pswp.cn/pingmian/78634.shtml
    繁體地址,請注明出處:http://hk.pswp.cn/pingmian/78634.shtml
    英文地址,請注明出處:http://en.pswp.cn/pingmian/78634.shtml

    如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

    相關文章

    Alibaba Cloud Linux 3.2104 LTS 64位 容器優化版安裝docker docker compose記錄

    整個安裝過程耗時4小時。&#xff08;包含以下檢查內容:&#xff09; 檢查該linux版本信息&#xff08;并通過監控指標檢查運行狀態/cpu占用/內存占用/磁盤讀取寫入IOPS /同時連接數&#xff09; 1&#xff1a;根據當前的系統進行yum與dnf的升級&#xff0c;保持穩定修復的版本…

    STM32N6570-DK ISP調試

    STM32N6570-DK之ISP調試應用 準備工作-下載安裝軟件包:一、使用STM32CubeProgrammer給板子燒入STM32N6_ISP_IQTune_App_revC01-v1.1.0-trusted.bin。二、打開STM32 ISP IQTune.exe ,出現可連接端口:三、根據教程進行相應調試:準備工作-下載安裝軟件包: https://www.st.co…

    12.thinkphp驗證

    一&#xff0e;驗證器定義 1. 驗證器的使用&#xff0c;我們必須先定義它&#xff0c;系統提供了一條命令直接生成想要的類&#xff1b; php think make:validate User 2. 這條命令會自動在應用目錄下生成一個validate文件夾&#xff0c;并生成User.php類&#xff1b; class…

    OpenWrt 與 Docker:打造輕量級容器化應用平臺技術分享

    文章目錄 前言一、OpenWrt 與 Docker 的集成前提1.1 硬件與內核要求1.2 軟件依賴 二、Docker 環境部署與驗證2.1 基礎服務配置2.2 存儲驅動適配 三、容器化應用部署實踐3.1 資源限制策略3.2 Docker Compose 適配 四、性能優化與監控4.1 容器資源監控4.2 鏡像精簡策略 五、典型問…

    EasyRTC音視頻實時通話嵌入式SDK,打造社交娛樂低延遲實時互動的新體驗

    一、方案背景 在數字化時代&#xff0c;社交娛樂已經成為人們生活中不可或缺的一部分。隨著移動互聯網和智能設備的普及&#xff0c;用戶對實時互動的需求越來越高。EasyRTC作為一款基于WebRTC技術的實時音視頻通信解決方案&#xff0c;憑借其低延遲、高穩定性和跨平臺兼容性&…

    軟件編程命名規范

    編程命名規范是保證代碼可讀性、可維護性和團隊協作效率的重要基礎。以下是涵蓋主流編程語言的通用命名規范&#xff0c;結合行業最佳實踐和常見規范&#xff08;如Google、Microsoft、Airbnb等風格指南&#xff09;&#xff1a; 一、通用命名原則 清晰優先&#xff1a;名稱應…

    換張電話卡能改變IP屬地嗎?一文解讀

    在互聯網時代&#xff0c;IP屬地&#xff08;即網絡定位信息&#xff09;的顯示引發了許多用戶的關注。有人好奇&#xff1a;更換電話卡&#xff08;SIM卡&#xff09;是否能改變自己的IP屬地&#xff1f;本文將解析IP屬地的定義、電話卡的作用&#xff0c;并深入探討兩者之間的…

    前端:純HTML、CSS和JS菜單樣式

    實現了一個多級折疊菜單系統,使用純HTML、CSS和JavaScript(無任何框架) 一、二級菜單展開 1、實現效果 初始狀態-展示全部一級菜單 選中共狀態,一級標題選中共為藍色背景色,二級標題選中共為藍色文字,展開右側圖標為-,后縮狀態右側圖標為+ 2、實現 ??HTML結構?? …

    Centos8 安裝 Docker

    yum 更換國內源 1. 備份原 yum 配置 cd /etc/yum.repos.d/ mkdir backup mv *.repo backup/2. 下載新 yum 配置&#xff08;阿里源&#xff09; wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo3. 替換源中的系統版本變量 sed -…

    AI測試工具Testim——告別自動化測試維護難題

    隨著人工智能技術的快速發展&#xff0c;AI測試工具正在成為提升軟件研發效能的關鍵。每款AI的特性各有差異&#xff0c;今天&#xff0c;我們就給大家介紹一款專注于Web和移動應用的端到端的AI測試工具--Testim。 Testim的簡介 官網地址&#xff1a;https://www.testim.io/ 簡…

    【默子AI】萬字長文:MCP與A2A協議詳解

    【默子AI】萬字長文&#xff1a;MCP與A2A協議詳解 引言&#xff1a; 讓一個大模型憑空解決所有問題&#xff0c;就像讓一個書呆子不借助工具就去修汽車 即便他腦子里裝滿了理論知識&#xff0c;也缺少實踐的“手腳”。 長期以來&#xff0c;AI助手&#xff08;尤其是LLM&#x…

    LeNet5 神經網絡的參數解析和圖片尺寸解析

    1.LeNet-5 神經網絡 以下是針對 LeNet-5 神經網絡的詳細參數解析和圖片尺寸變化分析&#xff0c;和原始論文設計&#xff0c;通過分步計算說明各層的張量變換過程。 經典的 LeNet-5架構簡化版&#xff08;原始論文輸入為 32x32&#xff0c;MNIST 常用 28x28 需調整&#xff09…

    第二節:文件系統

    理論知識 文件系統的基本概念&#xff1a;文件系統是操作系統中負責管理持久數據的子系統&#xff0c;它將數據組織成文件和目錄的形式&#xff0c;方便用戶存儲和訪問數據。Linux文件系統的類型&#xff1a;常見的 Linux 文件系統類型有 Ext2、Ext3、Ext4、XFS、Btrfs 等。Ex…

    Python數據結構與算法(5)——動態規劃

    Python數據結構與算法(5)——動態規劃 0. 學習目標1. 動態規劃的基本概念1.1 什么是動態規劃1.2 動態規劃的核心思想1.3 動態規劃的適用條件2. 動態規劃的實現思路2.1 自頂向下:備忘錄法 (Memoization)2.2 自底向上:表格法(Tabulation)3. 0/1 背包問題4. 最長公共子序列5…

    【JAVA ee初階】多線程(3)

    一、出現線程安全的原因 1.【根本原因】線程的調度執行時隨機的&#xff08;搶占式執行&#xff09;->罪魁禍首 2.多個線程同時修改同一個變量 如果是一個線程修改一個變量 或者 多個線程讀取同一個變量 或者 多個線程修改不同變量 這些都沒事。 3.修改操作不是原子的&a…

    Halcon 3D 表面匹配基于形狀

    文章目錄 prepare_object_model_3d 準備 3D 物體模型read_shape_model_3d — 讀取3D匹配模型create_shape_model_3d 準備要匹配的3D模型find_shape_model_3d ——發現匹配模型project_shape_model_3d 將三維形狀模型的邊緣投影到圖像坐標中。示例ignore_part_polarity&#xff…

    【Linux】Java 開發者的 Linux 常用命令指南

    Java 開發者的 Linux 常用命令指南 目錄標題 Java 開發者的 Linux 常用命令指南1. Linux 目錄結構2. 系統信息命令3. 服務管理系統服務防火墻管理 4. 文本編輯 (vi/vim)常用模式 5. 文件和目錄操作查看與導航創建與刪除查看文件內容查找文件 6. 用戶管理7. 壓縮和解壓8. 權限管…

    每日c/c++題 備戰藍橋杯(P1252洛谷 馬拉松接力賽)

    洛谷P1060 馬拉松接力賽題解&#xff1a;貪心算法在資源分配中的巧妙應用 題目描述 P1060 馬拉松接力賽是一道結合貪心策略與動態規劃思想的資源分配問題。題目要求將25公里的馬拉松接力賽合理分配給5名選手&#xff0c;使得總耗時最短。每位選手可跑1-10公里的整數距離&…

    Nginx 中間件

    Nginx&#xff08;發音為 "engine-x"&#xff09;是一款開源的高性能 HTTP 服務器和反向代理服務器&#xff0c;最初由 Igor Sysoev 開發。 它以其高性能、穩定性、豐富的功能集和低資源消耗而聞名&#xff0c;廣泛應用于全球的 Web 服務架構中。 作為中間件&#…

    Neo4j在win下安裝教程(docker環境)

    1. 安裝命令 1.1 基于正式neo4j安裝–不用 docker run --name neo4j-container -p 7474:7474 -p 7687:7687 -d neo4j1.2 基于community安裝 需要部署兩個Neo4j&#xff0c;一個正式庫prod&#xff0c;一個測試庫dev。 neo4j默認監聽7474&#xff08;HTTP-也就是瀏覽器端口&…