聶永的博客

          記錄工作/學習的點點滴滴。

          K8S Service 多種類型 Types 測試手記

          前言

          這里基于whoami示范服務,部署3個實例,分別一一驗證各種類型的K8S Service服務范疇。

          大致逐一從下面列表逐一驗證每種類型的Service訪問方式:

          • Service Name
          • 域名解析結果等
          • CLUSTER-IP
          • EXTERNAL-IP

          一些設定如下:

          • 測試環境K8S版本號為v1.27.3
          • K8S集群Node節點IP地址段范圍:10.0.1.0/24
          • K8S集群自動生成Pod網段為10.43.0.0/24
          • 本書所列代碼皆可拷貝直接粘貼到終端界面直接運行

          首先,部署whoami服務

          先部署包含3個實例的whoami

          # cat << 'EOF' | kubectl apply -f -
          apiVersion: apps/v1
          kind: Deployment
          metadata:
            name: whoami
            labels:
              app: whoami
          spec:
            replicas: 3
            selector:
              matchLabels:
                app: whoami
            template:
              metadata:
                labels:
                  app: whoami
              spec:
                containers:
                - name: whoami
                  image: containous/whoami
                  ports:
                  - containerPort: 80
                    name: web
          EOF
          

          查看一下:

          # kubectl get all
          NAME                                                      READY   STATUS      RESTARTS         AGE
          pod/whoami-767d459f67-qffqw                               1/1     Running     0                23m
          pod/whoami-767d459f67-xdv9p                               1/1     Running     0                23m
          pod/whoami-767d459f67-gwpgx                               1/1     Running     0                23m
          
          NAME                                                  READY   UP-TO-DATE   AVAILABLE   AGE
          deployment.apps/whoami                                3/3     3            3           23m
          
          NAME                                                            DESIRED   CURRENT   READY   AGE
          replicaset.apps/whoami-767d459f67                               3         3         3       23m
          

          其次,安裝busybox進行調試

          安裝一個包含有curl的busybox方便后續調試:

          kubectl run busybox-curl --image=yauritux/busybox-curl --command -- sleep 3600
          

          另起一個終端,輸入下面命令進入:

          kubectl exec -ti busybox-curl -n default -- sh
          

          環境準備好之后,下面逐一測試各種類型:

          默認Cluster IP模式

          K8S默認Service為Cluster IP模式,面向內部Pod以及通過Ingress對外提供服務。

          下面一張圖很清晰解釋清楚了PortTargetPort適用情景,Port為Service對外輸出的端口,TargetPort為服務后端Pod的端口,兩者之間有一個轉換:port -> targetPort -> containerPort

          創建一個Service:

          cat << 'EOF' | kubectl apply -f -
          apiVersion: v1
          kind: Service
          metadata:
            labels:
              name: whoami-clusterip
            name: whoami-clusterip
          spec:
            ports:
            - port: 80
              targetPort: 80
              protocol: TCP
            selector:
              app: whoami
          EOF
          

          部署后可以查看一下:

          NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
          service/whoami-clusterip      ClusterIP      10.43.247.74    <none>        80/TCP         57s
          

          下面就需要逐一測試了。

          域名形式:

          # curl whoami-clusterip
          Hostname: whoami-767d459f67-gwpgx
          IP: 127.0.0.1
          IP: 10.42.8.35
          RemoteAddr: 10.42.9.32:35968
          GET / HTTP/1.1
          Host: whoami-clusterip
          User-Agent: curl/7.81.0
          Accept: */*
          

          Cluster IP形式:

          # curl 10.43.247.74
          Hostname: whoami-767d459f67-qffqw
          IP: 127.0.0.1
          IP: 10.42.3.73
          RemoteAddr: 10.42.9.32:42398
          GET / HTTP/1.1
          Host: 10.43.247.74
          User-Agent: curl/7.81.0
          Accept: */*
          

          域名解析,只解析到Cluster IP上:

          # nslookup whoami-clusterip
          Server:		10.43.0.10
          Address:	10.43.0.10:53
          
          Name:	whoami-clusterip.default.svc.cluster.local
          Address: 10.43.247.74
          

          External IP模式

          原理同Cluster IP模式,為指定服務綁定一個額外的一個IP地址。當終端訪問該IP地址,將流量一樣轉發到Service。

          當訪問external IP,其端口轉換過程:port -> targetPort -> containerPort

          與默認Service相比,端口轉換流程沒有增加,但好處對外暴露了一個可訪問的IP地址,不過可能需要在交換機/路由器層面提供動靜態路由支持。

          cat << 'EOF' | kubectl apply -f -
          apiVersion: v1
          kind: Service
          metadata:
            labels:
              name: whoami-externalip
            name: whoami-externalip
          spec:
            ports:
            - port: 80
              targetPort: 80
              protocol: TCP
            selector:
              app: whoami
            externalIPs:
            - 10.10.10.10
          EOF
          

          服務顯示如下,綁定了指定的擴展IP地址10.10.10.10

          # NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
          service/whoami-externalip     ClusterIP      10.43.192.118   10.10.10.10   80/TCP         57s
          

          kube-proxy 將在每一個Node節點為10.10.10.10上建立一個轉發規則,該IP地址的80端口將直接轉發到對應的后端三個whoami Pod 上。

          -A KUBE-SERVICES -d 10.10.10.10/32 -p tcp -m comment --comment "default/whoami-externalip external IP" -m tcp --dport 80 -j KUBE-EXT-QN5HIEVYUPDP6UNK
          
          ......
          -A KUBE-EXT-QN5HIEVYUPDP6UNK -j KUBE-SVC-QN5HIEVYUPDP6UNK
          ......
          
          -A KUBE-SVC-QN5HIEVYUPDP6UNK ! -s 10.42.0.0/16 -d 10.43.192.118/32 -p tcp -m comment --comment "default/whoami-externalip cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
          -A KUBE-SVC-QN5HIEVYUPDP6UNK -m comment --comment "default/whoami-externalip -> 10.42.2.79:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-JSAT6D2KFCSF4YLF
          -A KUBE-SVC-QN5HIEVYUPDP6UNK -m comment --comment "default/whoami-externalip -> 10.42.3.77:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-2R66UI3G2AY2IMNM
          -A KUBE-SVC-QN5HIEVYUPDP6UNK -m comment --comment "default/whoami-externalip -> 10.42.8.42:80" -j KUBE-SEP-ZHHIL2SAN2G37GCM
          

          訪問域名:

          # curl whoami-externalip
          Hostname: whoami-767d459f67-gwpgx
          IP: 127.0.0.1
          IP: 10.42.8.35
          RemoteAddr: 10.42.9.32:46746
          GET / HTTP/1.1
          Host: whoami-externalip
          User-Agent: curl/7.81.0
          Accept: */*
          

          訪問ClusterIP形式:

          # curl 10.43.192.118
          Hostname: whoami-767d459f67-qffqw
          IP: 127.0.0.1
          IP: 10.42.3.73
          RemoteAddr: 10.42.9.32:47516
          GET / HTTP/1.1
          Host: 10.43.192.118
          User-Agent: curl/7.81.0
          Accept: */*
          

          訪問暴露的External IP:

          # curl 10.10.10.10
          Hostname: whoami-767d459f67-gwpgx
          IP: 127.0.0.1
          IP: 10.42.8.35
          RemoteAddr: 10.42.9.0:38477
          GET / HTTP/1.1
          Host: 10.10.10.10
          User-Agent: curl/7.81.0
          Accept: */*
          

          域名解析結果只解析到其對應的Cluster IP:

          # nslookup whoami-externalip
          Server:		10.43.0.10
          Address:	10.43.0.10:53
          
          Name:	whoami-externalip.default.svc.cluster.local
          Address: 10.43.192.118
          

          NodePort 模式

          Cluster IP相比,多了一個nodePort,這個NodePort會在K8S所有Node節點上都會開放。

          這里有一個端口轉換過程:nodePort -> port -> targetPort -> containerPort,多了一層數據轉換過程。

          服務定義如下:

          cat << 'EOF' | kubectl apply -f -
          apiVersion: v1
          kind: Service
          metadata:
            labels:
              name: whoami-nodeport
            name: whoami-nodeport
          spec:
            type: NodePort
            ports:
            - port: 80
              targetPort: 80
              nodePort: 30080
              protocol: TCP
            selector:
              app: whoami
          EOF
          

          查看一下服務分配地址:

          NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
          service/whoami-nodeport       NodePort       10.43.215.233   <none>        80:30080/TCP   57s
          

          訪問域名:

          # curl whoami-nodeport
          Hostname: whoami-767d459f67-xdv9p
          IP: 127.0.0.1
          IP: 10.42.2.75
          RemoteAddr: 10.42.9.32:36878
          GET / HTTP/1.1
          Host: whoami-nodeport
          User-Agent: curl/7.81.0
          Accept: */*
          

          測試 CLUSTER IP :

          # curl 10.43.215.233
          Hostname: whoami-767d459f67-qffqw
          IP: 127.0.0.1
          IP: 10.42.3.73
          RemoteAddr: 10.42.9.32:40552
          GET / HTTP/1.1
          Host: 10.43.215.233
          User-Agent: curl/7.81.0
          Accept: */*
          

          因為是在每一個K8S Node節點上都會開放一個30080端口,因此可以這樣訪問 {Node IP}:{nodePort},如下Node IP地址為10.0.1.11

          # curl 10.0.1.11:30080
          Hostname: whoami-767d459f67-qffqw
          IP: 127.0.0.1
          IP: 10.42.3.73
          RemoteAddr: 10.42.1.0:1880
          GET / HTTP/1.1
          Host: 10.0.1.11:30080
          User-Agent: curl/7.81.0
          Accept: */*
          

          域名還是只解析到對應Cluster IP:

          # nslookup whoami-nodeport
          Server:		10.43.0.10
          Address:	10.43.0.10:53
          
          Name:	whoami-nodeport.default.svc.cluster.local
          Address: 10.43.215.233
          

          LoadBalancer 模式

          LoadBalancer模式,會強制K8S Service自動開啟nodePort

          這里有一張圖,詳細解析數據流向。

          服務數據端口轉換過程:port -> nodePort -> port -> targetPort -> containerPort

          • 與默認Cluster IP相比,多了兩層數據轉換過程
          • nodePort相比,對了一層數據轉換過程
          • externalIP相比,在小流量場景下就沒有什么優勢了

          具體服務定義:

          cat << 'EOF' | kubectl apply -f -
          apiVersion: v1
          kind: Service
          metadata:
            labels:
              name: whoami-clusterip-none
            name: whoami-clusterip-none
          spec:
            clusterIP: None
            ports:
            - port: 80
              targetPort: 80
              protocol: TCP
            selector:
              app: whoami
          EOF
          

          查看一下部署結果:

          NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
          service/whoami-loadbalancer   LoadBalancer   10.43.63.92     <pending>     80:30906/TCP   57s
          

          服務域名形式:

          # curl whoami-loadbalancer
          Hostname: whoami-767d459f67-qffqw
          IP: 127.0.0.1
          IP: 10.42.3.73
          RemoteAddr: 10.42.9.32:57844
          GET / HTTP/1.1
          Host: whoami-loadbalancer
          User-Agent: curl/7.81.0
          Accept: */*
          

          測試 CLUSTER-IP

          # curl 10.43.63.92
          Hostname: whoami-767d459f67-xdv9p
          IP: 127.0.0.1
          IP: 10.42.2.75
          RemoteAddr: 10.42.9.32:42400
          GET / HTTP/1.1
          Host: 10.43.63.92
          User-Agent: curl/7.81.0
          Accept: */*
          

          域名解析到Cluster IP:

          #  nslookup whoami-loadbalancer
          Server:		10.43.0.10
          Address:	10.43.0.10:53
          
          Name:	whoami-loadbalancer.default.svc.cluster.local
          Address: 10.43.63.92
          

          安裝LoadBalancer

          此時whoami-loadbalancer服務對應的EXTERNAL-IP<pending>,我們需要安裝一個負載均衡器,可以選擇MetalLB作為負載均衡器。

          # kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.11/config/manifests/metallb-native.yaml
          

          稍后分配可用的LoadBalaner可分配的地址池:

          cat << 'EOF' | kubectl apply -f -
          apiVersion: metallb.io/v1beta1
          kind: IPAddressPool
          metadata:
            name: default-pool
            namespace: metallb-system
          spec:
            addresses:
            - 10.0.1.100-10.0.1.200
          ---
          apiVersion: metallb.io/v1beta1
          kind: L2Advertisement
          metadata:
            name: default
            namespace: metallb-system
          spec:
            ipAddressPools:
            - default-pool
          EOF
          

          等安裝完成之后,可以看到服務whoami-loadbalancer分配的IP地址為 10.0.1.101

          NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
          ......
          service/whoami-loadbalancer LoadBalancer   10.43.63.92     10.0.1.101         80:30906/TCP   27h
          ......
          

          測試負載均衡IP地址

          測試一下:

          # curl 10.0.1.101
          Hostname: whoami-767d459f67-xdv9p
          IP: 127.0.0.1
          IP: 10.42.2.78
          RemoteAddr: 10.42.8.0:33658
          GET / HTTP/1.1
          Host: 10.0.1.101
          User-Agent: curl/7.79.1
          Accept: */*
          

          我們看到該服務分配的端口為80:30906/TCP30906為K8S為該服務自動生成的NodePort類型端口。

          可以找任一K8S Node節點IP地址測試一下:

          # curl 10.0.1.12:30906
          Hostname: whoami-767d459f67-qffqw
          IP: 127.0.0.1
          IP: 10.42.3.77
          RemoteAddr: 10.42.2.0:9717
          GET / HTTP/1.1
          Host: 10.0.1.12:30906
          User-Agent: curl/7.81.0
          Accept: */*
          

          分析一下路由表,可以分析到該負載均衡的External_IP:80的打流量到NodePort:30906上,然后走Service對應{Pod:80}流量分發邏輯。

          -A KUBE-NODEPORTS -p tcp -m comment --comment "default/whoami-loadbalancer" -m tcp --dport 30906 -j KUBE-EXT-NBTYBEEXACZI7DPC
          
          ......
          
          -A KUBE-SERVICES -d 10.0.1.101/32 -p tcp -m comment --comment "default/whoami-loadbalancer loadbalancer IP" -m tcp --dport 80 -j KUBE-EXT-NBTYBEEXACZI7DPC
          
          ......
          
          -A KUBE-EXT-NBTYBEEXACZI7DPC -m comment --comment "masquerade traffic for default/whoami-loadbalancer external destinations" -j KUBE-MARK-MASQ
          -A KUBE-EXT-NBTYBEEXACZI7DPC -j KUBE-SVC-NBTYBEEXACZI7DPC
          
          ......
          
          -A KUBE-SVC-NBTYBEEXACZI7DPC ! -s 10.42.0.0/16 -d 10.43.63.92/32 -p tcp -m comment --comment "default/whoami-loadbalancer cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
          -A KUBE-SVC-NBTYBEEXACZI7DPC -m comment --comment "default/whoami-loadbalancer -> 10.42.2.79:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-E3K3SUYNFWT2VICE
          -A KUBE-SVC-NBTYBEEXACZI7DPC -m comment --comment "default/whoami-loadbalancer -> 10.42.3.77:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-HG5MYVVID7GJOZA7
          -A KUBE-SVC-NBTYBEEXACZI7DPC -m comment --comment "default/whoami-loadbalancer -> 10.42.8.42:80" -j KUBE-SEP-GFJH72YCBKBFB6OG
          

          Headless 無頭模式

          一般應用在有狀態的服務,或需要終端調用者自己實現負載均衡,等一些特定場景。

          通過調用者從端口角度分析,數據轉換流程:targetPort -> containerPort

          在意服務性能的場景,不妨試試無頭模式。


          服務定義:

          cat << 'EOF' | kubectl apply -f -
          apiVersion: v1
          kind: Service
          metadata:
            labels:
              name: whoami-clusterip-none
            name: whoami-clusterip-none
          spec:
            clusterIP: None
            ports:
            - port: 80
              targetPort: 80
              protocol: TCP
            selector:
              app: whoami
          EOF
          

          查看服務部署情況:

          NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
          service/whoami-clusterip-none   ClusterIP      None            <none>                     80/TCP         9h
          

          通過service域名訪問,K8S會自動根據服務域名whoami-clusterip-none進行pick后端對應Pod IP地址。

          # curl whoami-clusterip-none
          Hostname: whoami-767d459f67-xdv9p
          IP: 127.0.0.1
          IP: 10.42.2.75
          RemoteAddr: 10.42.9.32:34998
          GET / HTTP/1.1
          Host: whoami-clusterip-none
          User-Agent: curl/7.81.0
          Accept: */*
          

          查詢DNS會把所有節點都列出來。

          # nslookup whoami-clusterip-none
          Server:		10.43.0.10
          Address:	10.43.0.10:53
          
          Name:	whoami-clusterip-none.default.svc.cluster.local
          Address: 10.42.3.73
          Name:	whoami-clusterip-none.default.svc.cluster.local
          Address: 10.42.2.75
          Name:	whoami-clusterip-none.default.svc.cluster.local
          Address: 10.42.8.35
          

          External Name模式

          用于引進帶域名的外部服務,這里引入內部服務作為測試。

          多了一層域名解析過程,端口轉換流程依賴于所引入服務的服務設定。

          服務定義:

          cat << 'EOF' | kubectl apply -f -
          apiVersion: v1
          kind: Service
          metadata:
            labels:
              name: whoami-externalname
            name: whoami-externalname
          spec:
            type: ExternalName
            externalName: whoami-clusterip.default.svc.cluster.local
          EOF
          

          這里外聯的是whoami-clusterip服務的完整訪問域名。

          查看服務部署情況:

          NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
          service/whoami-externalname     ExternalName   <none>          whoami-clusterip.default   <none>         9h
          

          根據域名訪問測試:

          # curl whoami-externalname
          Hostname: whoami-767d459f67-qffqw
          IP: 127.0.0.1
          IP: 10.42.3.77
          RemoteAddr: 10.42.9.35:36756
          GET / HTTP/1.1
          Host: whoami-externalname
          User-Agent: curl/7.81.0
          Accept: */*
          

          DNS解析結果:

          # nslookup whoami-externalname
          Server:		10.43.0.10
          Address:	10.43.0.10:53
          
          whoami-externalname.default.svc.cluster.local	canonical name = whoami-clusterip.default.svc.cluster.local
          Name:	whoami-clusterip.default.svc.cluster.local
          Address: 10.43.247.74
          

          小結

          簡要分析了各種類型Service定義、服務引用場景以及測試流程等,整理清楚了,也方便在具體業務場景中進行抉擇選擇具體服務類型。

          posted on 2023-09-13 10:13 nieyong 閱讀(206) 評論(0)  編輯  收藏 所屬分類: 容器

          公告

          所有文章皆為原創,若轉載請標明出處,謝謝~

          新浪微博,歡迎關注:

          導航

          <2023年9月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          1234567

          統計

          常用鏈接

          留言簿(58)

          隨筆分類(130)

          隨筆檔案(151)

          個人收藏

          最新隨筆

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 论坛| 永新县| 定襄县| 盐津县| 麟游县| 名山县| 介休市| 河池市| 中卫市| 宜兴市| 梁河县| 白银市| 集安市| 菏泽市| 宜章县| 宜兰市| 屏东县| 阜平县| 吕梁市| 武乡县| 怀安县| 安西县| 甘孜县| 许昌县| 集安市| 永寿县| 潜江市| 容城县| 崇州市| 东阳市| 永昌县| 虹口区| 宁强县| 喀喇沁旗| 通海县| 黄浦区| 商丘市| 澄城县| 池州市| 安丘市| 陆良县|