目錄
- 一、什么是服務service?
- 二、service分類
- 2.1 ClusterIP
- 2.2 NodePort
- 2.3 LoadBalancer(付費方案)
- 2.4 ExternalName (使用較少)
- 三、service和pod的關系
- 四、Service 之 ClusterIP 使用
- 4.1 在當前目錄下,創建一個deploy-nginx-pod.yaml,配置如下
- 4.2 暴露服務為 clusterIP 類型
- 4.3 查看服務
- 五、Service 之 NodePort 使用
- 5.1 關于NodePort
- 5.2 創建NodePort類型的服務
- 查看服務詳情
- 關于NodePort暴露對外端口說明
- 關于Endpoint參數說明
- 關于Service如何分發請求到后端的多個Pod
- NodePort 負載均衡機制驗證
一、什么是服務service?
在k8s里面,每個Pod都會被分配一個單獨的IP地址,但這個IP地址會隨著Pod的銷毀而消失,重啟pod的ip地址會發生變化,此時客戶如果訪問原先的ip地址則會報錯 ;
Service (服務)就是用來解決這個問題的, 對外服務的統一入口,防止pod失聯,定義一組pod的訪問策略(服務發現、負載均衡) ;
一個Service可以看作一組提供相同服務的Pod的對外訪問接口,作用于哪些Pod是通過標簽選擇器來定義的 ,Service是一個概念,主要作用的是節點上的kube-proxy服務進程 ;
舉例來說,定義了3個商品微服務,由網關作為統一訪問入口, 前端不需要關心它們調用了哪個后端副本。 然而組成這一組后端程序的 Pod 實際上可能會發生變化, 前端客戶端不應該也沒必要知道,而且也不需要跟蹤這一組后端的狀態。
簡而言之,Service 定義的這種抽象能夠解耦這種關聯;
二、service分類
根據使用場景的不同,service可以分成下面幾類
2.1 ClusterIP
默認類型,自動分配一個【僅集群內部】可以訪問的虛擬IP
2.2 NodePort
對外訪問應用使用,在ClusterIP基礎上為Service在每臺機器上綁定一個端口,就可以通過: ip+NodePort來訪問該服務 ,在之前搭建k8s集群部署nginx的時候我們使用過;
2.3 LoadBalancer(付費方案)
- 使在NodePort的基礎上,借助公有云創建一個外部負載均衡器,并將請求轉發到NodePort ;
- 可以實現集群外部訪問服務的另外一種解決方案,不過并不是所有的k8s集群都會支持,大多是在公有云托管集群中會支持該類型 ;
2.4 ExternalName (使用較少)
把集群外部的服務引入到集群內部來,在集群內部直接使用。沒有任何類型代理被創建,這只有 Kubernetes 1.7或更高版本的kube-dns才支持。
三、service和pod的關系
service和pod之間是通過 selector.app進行關聯的 ,對應到yaml中的核心配置如下:
spec: # 描述
selector: # 標簽選擇器,確定當前service代理控制哪些pod
app: test-nginx
yaml 配置模板文件
apiVersion: v1 kind: Service metadata: creationTimestamp: null name: test-svc spec: ports: - port: 80 # service服務端口 protocol: TCP targetPort: 80 # pod端口,常規和容器內部端口一致 selector: app: test-nginx-pod status: loadBalancer: {}
四、Service 之 ClusterIP 使用
ClusterIP 屬于service的一種,一般作為集群內部應用互相訪問時使用,接下來通過實際演示進行詳細的說明;
4.1 在當前目錄下,創建一個deploy-nginx-pod.yaml,配置如下
apiVersion: apps/v1 kind: Deployment metadata: name: congge-deploy namespace: dev spec: replicas: 3 selector: matchLabels: app: congge-nginx-pod template: metadata: labels: app: congge-nginx-pod spec: containers: - name: congge-nginx image: nginx:1.23.0
使用apply命令創建pod,
kubectl apply -f deploy-nginx-pod.yaml
可以看到,成功創建了一個3副本的pod集群;
4.2 暴露服務為 clusterIP 類型
kubectl expose deploy congge-deploy --name=svc-nginx1 --type=ClusterIP --port=80 --target-port=80 -n default
執行成功之后,可以看到創建了一個clusterIP類型的service;
有了這個clusterIp服務之后,后續不管nginx服務擴縮容,還是nginx的pod的IP地址如何變化,外部只需要統一訪問這個clusterIP分配的這個IP+端口即可;
4.3 查看服務
多了個類型是ClusterIP的,通過curl clusterIp+port可以訪問
kubectl get deployment,pod,svc -n dev -o wide
五、Service 之 NodePort 使用
上面了解到clusterIp這種方式一般作為集群內部各應用訪問時使用,但實際業務場景中,有些應用服務需要暴露出去,通過外網去訪問,這時候就需要創建NodePort,這個在k8s搭建篇中最后部署nginx的時候有提到;
5.1 關于NodePort
- 常規業務的場景不全是集群內訪問,也需要集群外業務訪問 ;
- 那么ClusterIP就滿足不了了,NodePort是其中的一種實現集群外部訪問的方案 ;
- 對外訪問應用使用,在ClusterIP基礎上為Service在每臺機器上綁定一個端口,就可以通過: ip+NodePort來訪問該服務 ;
5.2 創建NodePort類型的服務
在上面我們創建了一個基于clusterIp類型的service
使用下面的命令創建一個基于 NodePort 的service
kubectl expose deploy congge-deploy --name=svc-nodeport-nginx1 --type=NodePort --port=80 --target-port=80 -n default
執行完成之后,就多了一個NodePort的service
使用瀏覽器訪問下當前主機的公網IP就可以訪問了(master或者node節點都可以訪問);
查看服務詳情
通過這個命令,可以查看上述創建的NodePort詳細信息;
kubectl describe svc svc-nodeport-nginx1 -n default
關于NodePort暴露對外端口說明
Kubeadm部署,暴露端口對外服務,會隨機選端口,默認范圍是30000~32767,也可以手動修改和指定端口范圍
關于Endpoint參數說明
- 是k8s中的一個資源對象,存儲在etcd中,記錄service對應的所有pod的訪問地址 ;
- 里面有個Endpoints列表,就是當前service可以負載到的pod服務入口 ;
- service和pod之間的通信是通過endpoint實現的 ;
可以使用下面的命令查看endpoint列表
kubectl get ep svc-nodeport-nginx1 -n default -o wide
關于Service如何分發請求到后端的多個Pod
Service所處的位置就如同圖中展示的,處在客戶端和pod之間,這就很像nginx或者其他具備網關的組件的能力了,事實上,也差不多就是我們理解的那樣,一個Service的服務背后可能掛載著N多個Pod,那么具體來說,Service如何分發請求到后端的多個Pod的呢?
kubernetes提供了兩種負載均衡策略 :
- 默認,kube-proxy的策略,如隨機、輪詢 ;
- 使用會話保持模式,即同個客戶端的請求固定到某個pod,在spec中添加sessionAffinity:ClientIP即可 ;
NodePort 負載均衡機制驗證
查看pod信息,顯示了上面創建的以congge-deploy開頭的3個nginx
其實來說,這也就是對應了3個pod中的3個nginx容器,如果使用curl的方式查看其中某個nginx,可以正常輸出nginx歡迎頁面的內容;
接下來,我們只需要進入到nginx容器內部,修改下nginx歡迎頁的html內容,就可以看出Service的負載均衡效果了;
進入docker容器進行html內容的修改
#進入容器 kubectl exec -it congge-deploy-768455649c-2kv5r -n default /bin/sh kubectl exec -it congge-deploy-768455649c-mfkbf -n default /bin/sh kubectl exec -it congge-deploy-768455649c-xlh7s -n default /bin/sh #執行修改 echo "hello this is node1 " > /usr/share/nginx/html/index.html echo "hello this is node2 " > /usr/share/nginx/html/index.html echo "hello this is node3 " > /usr/share/nginx/html/index.html
執行過程
接下來使用當前主機節點IP+圖中的端口在瀏覽器訪問下
我們連續訪問多次,看下返回的內容如何
第一次:
第二次:
當然,可以通過在當前節點上通過curl cluserIP的方式,效果類似
其實也可以查看下當前創建這個SVC的時候默認的配置,使用yaml格式輸出一下
kubectl get svc svc-nodeport-nginx1 -n default -o yaml
總結:通過上面的實際操作,在默認情況下,負載均衡為基于隨機的這種策略;