Kubernetes之十一---service資源詳解

1、認識service

1.1 爲什麼要使用service

  Kubernetes Pod 是有生命週期的,它們可以被創建,也可以被銷燬,然而一旦被銷燬生命就永遠結束。 通過 ReplicationController 能夠動態地創建和銷燬 Pod(例如,需要進行擴縮容,或者執行 滾動升級)。 每個 Pod 都會獲取它自己的 IP 地址,即使這些 IP 地址不總是穩定可依賴的。 這會導致一個問題:在 Kubernetes 集羣中,如果一組 Pod(稱爲 backend)爲其它 Pod (稱爲 frontend)提供服務,那麼那些 frontend 該如何發現,並連接到這組 Pod 中的哪些 backend 呢?答案是:Service。

 

1.2 service介紹

  Kubernetes Service 定義了這樣一種抽象:一個 Pod 的邏輯分組,一種可以訪問它們的策略 —— 通常稱爲微服務。 這一組 Pod 能夠被 Service 訪問到,通常是通過 Label Selector(下面我們會講到我們爲什麼需要一個沒有label selector的服務)實現的。

  舉個例子,考慮一個圖片處理 backend,它運行了3個副本。這些副本是可互換的 —— frontend 不需要關心它們調用了哪個 backend 副本。 然而組成這一組 backend 程序的 Pod 實際上可能會發生變化,frontend 客戶端不應該也沒必要知道,而且也不需要跟蹤這一組 backend 的狀態。 Service 定義的抽象能夠解耦這種關聯。

  對 Kubernetes 集羣中的應用,Kubernetes 提供了簡單的 Endpoints API,只要 Service 中的一組 Pod 發生變更,應用程序就會被更新。 對非 Kubernetes 集羣中的應用,Kubernetes 提供了基於 VIP 的網橋的方式訪問 Service,再由 Service 重定向到 backend Pod。

 

1.3 三種代理模式

  •  userspace 代理模式(K8S 1.1之前版本)
  •  iptables 代理模式(K8S 1.10之前版本)
  •  ipvs 代理模式(K8S 1.11 之後版本,激活ipvs需要修改配置)

1.3.1 userspace 代理模式

  這種模式,kube-proxy 會監視 Kubernetes master 對 Service 對象和 Endpoints 對象的添加和移除。 對每個 Service,它會在本地 Node 上打開一個端口(隨機選擇)。 任何連接到“代理端口”的請求,都會被代理到 Service 的backend Pods 中的某個上面(如 Endpoints 所報告的一樣)。 使用哪個 backend Pod,是基於 Service 的 SessionAffinity 來確定的。 最後,它安裝 iptables 規則,捕獲到達該 Service 的 clusterIP(是虛擬 IP)和 Port 的請求,並重定向到代理端口,代理端口再代理請求到 backend Pod。

  網絡返回的結果是,任何到達 Service 的 IP:Port 的請求,都會被代理到一個合適的 backend,不需要客戶端知道關於 Kubernetes、Service、或 Pod 的任何信息。

  默認的策略是,通過 round-robin 算法來選擇 backend Pod。 實現基於客戶端 IP 的會話親和性,可以通過設置 service.spec.sessionAffinity 的值爲 "ClientIP" (默認值爲 "None")。

 

 1.3.2 iptables 代理模式

  這種模式,kube-proxy 會監視 Kubernetes master 對 Service 對象和 Endpoints 對象的添加和移除。 對每個 Service,它會安裝 iptables 規則,從而捕獲到達該 Service 的 clusterIP(虛擬 IP)和端口的請求,進而將請求重定向到 Service 的一組 backend 中的某個上面。 對於每個 Endpoints 對象,它也會安裝 iptables 規則,這個規則會選擇一個 backend Pod。

  默認的策略是,隨機選擇一個 backend。 實現基於客戶端 IP 的會話親和性,可以將 service.spec.sessionAffinity 的值設置爲 "ClientIP" (默認值爲 "None")。

  和 userspace 代理類似,網絡返回的結果是,任何到達 Service 的 IP:Port 的請求,都會被代理到一個合適的 backend,不需要客戶端知道關於 Kubernetes、Service、或 Pod 的任何信息。 這應該比 userspace 代理更快、更可靠。然而,不像 userspace 代理,如果初始選擇的 Pod 沒有響應,iptables 代理能夠自動地重試另一個 Pod,所以它需要依賴 readiness probes。

 

1.3.3 ipvs代理模式

  ipvs (IP Virtual Server) 實現了傳輸層負載均衡,也就是我們常說的4層LAN交換,作爲 Linux 內核的一部分。ipvs運行在主機上,在真實服務器集羣前充當負載均衡器。ipvs可以將基於TCP和UDP的服務請求轉發到真實服務器上,並使真實服務器的服務在單個 IP 地址上顯示爲虛擬服務。

  在kubernetes v1.8 中引入了 ipvs 模式,在 v1.9 中處於 beta 階段,在 v1.11 中已經正式可用了。 iptables 模式在 v1.1 中就添加支持了,從 v1.2 版本開始 iptables 就是 kube-proxy 默認的操作模式,ipvs 和 iptables 都是基於netfilter的, ipvs 模式和 iptables 模式之間的差異:

  •  ipvs 爲大型集羣提供了更好的可擴展性和性能
  •  ipvs 支持比 iptables 更復雜的複製均衡算法(最小負載、最少連接、加權等等)
  •  ipvs 支持服務器健康檢查和連接重試等功能

  同時ipvs 也依賴 iptables,ipvs 會使用 iptables 進行包過濾、SNAT、masquared(僞裝)。具體來說,ipvs 將使用ipset來存儲需要DROP或masquared的流量的源或目標地址,以確保 iptables 規則的數量是恆定的,這樣我們就不需要關心我們有多少服務了

ipvs雖然在v1.1版本中已經支持,但是想要使用,還需激活ipvs:

① 修改配置文件

1
2
[root@master ~]# vim /etc/sysconfig/kubelet
KUBE_PROXY=MODE=ipvs

② 編寫腳本,讓kubelet所在的主機,啓動時裝入以下幾個模塊,由於前面部署的K8s集羣是手動部署的,無法啓用ipvs規則:

ip_vs,ip_vs_rr,ip_vs_wrr,ip_vs_sh,nf_conntrack_ipv4

在每個master和node節點上創建ipvs規則

1、創建內核模塊載入相關的腳本文件/etc/sysconfig/modules/ipvs.modules,設定自動載入的內核模塊。文件內容如下: 

#!/bin/bash
ipvs_mods_dir="/usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs"
for mod in $(ls $ipvs_mods_dir | grep -o "^[^.]*"); do
    /sbin/modinfo -F filename $mod  &> /dev/null
    if [ $? -eq 0 ]; then
        /sbin/modprobe $mod
    fi
done

2、修改文件權限,並手動爲當前系統加載內核模塊:

~]# chmod +x /etc/sysconfig/modules/ipvs.modules 
~]# bash /etc/sysconfig/modules/ipvs.modules  

3、修改ipvs規則:

[root@master ~]# kubectl edit cm kube-proxy -n kube-system
apiVersion: v1
data:
  config.conf: |-
    apiVersion: kubeproxy.config.k8s.io/v1alpha1
    bindAddress: 0.0.0.0
    clientConnection:
      acceptContentTypes: ""
      burst: 0
      contentType: ""
      kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
      qps: 0
    clusterCIDR: 10.224.0.0/16
    configSyncPeriod: 0s
    conntrack:
      maxPerCore: null
      min: null
      tcpCloseWaitTimeout: null
      tcpEstablishedTimeout: null
    detectLocalMode: ""
    enableProfiling: false
    healthzBindAddress: ""
    hostnameOverride: ""
    iptables:
      masqueradeAll: false
      masqueradeBit: null
      minSyncPeriod: 0s
      syncPeriod: 0s
    ipvs:
      excludeCIDRs: null
      minSyncPeriod: 0s
      scheduler: ""
      strictARP: false
      syncPeriod: 0s
      tcpFinTimeout: 0s
      tcpTimeout: 0s
      udpTimeout: 0s
    kind: KubeProxyConfiguration
    metricsBindAddress: ""
    mode: "ipvs"         # 只需要在第一次初始化k8s未支持的模塊上加載ipvs即可

4、此時我們可以看到kube-proxy上沒有重構新的pod,此時的kube-proxy還是運行了44h。

[root@master ~]# kubectl get pods -n kube-system
NAME                             READY   STATUS    RESTARTS   AGE
coredns-546565776c-fl859         1/1     Running   20         44h
coredns-546565776c-mwt5p         1/1     Running   18         44h
etcd-master                      1/1     Running   5          44h
kube-apiserver-master            1/1     Running   7          44h
kube-controller-manager-master   1/1     Running   5          44h
kube-flannel-ds-amd64-rpdk6      1/1     Running   4          43h
kube-flannel-ds-amd64-rsb4s      1/1     Running   6          44h
kube-flannel-ds-amd64-vcqcz      1/1     Running   4          43h
kube-proxy-75gjn                 1/1     Running   5          43h
kube-proxy-fj6js                 1/1     Running   6          44h   # 可以看到此時的kube-proxy已經運行了44h,不是最新的kube-proxy
kube-proxy-kpfrl                 1/1     Running   5          43h
kube-scheduler-master            1/1     Running   5          44h

刪除kube-proxy的pod標籤

1、在node1節點上先安裝一個ipvsadm客戶端,方便查看此時的ipvs規則

[root@node1 ~]# yum install ipvsadm -y  # 安裝ipvs客戶端
[root@node1 ~]# ipvsadm -ln             # 此時可以看到沒有任何ipvs規則,說明ipvs規則還是沒有被加載進來
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
[root@node1 ~]# 

2、刪除舊的kube-proxy標籤,自動重構新的kube-proxy標籤

[root@master ~]# kubectl get pods -n kube-system --show-labels  # 查看此時舊的kube-proxy標籤
NAME                             READY   STATUS    RESTARTS   AGE   LABELS
coredns-546565776c-fl859         1/1     Running   20         44h   k8s-app=kube-dns,pod-template-hash=546565776c
coredns-546565776c-mwt5p         1/1     Running   18         44h   k8s-app=kube-dns,pod-template-hash=546565776c
etcd-master                      1/1     Running   5          44h   component=etcd,tier=control-plane
kube-apiserver-master            1/1     Running   7          44h   component=kube-apiserver,tier=control-plane
kube-controller-manager-master   1/1     Running   5          44h   component=kube-controller-manager,tier=control-plane
kube-flannel-ds-amd64-rpdk6      1/1     Running   4          43h   app=flannel,controller-revision-hash=56c5465959,pod-template-generation=1,tier=node
kube-flannel-ds-amd64-rsb4s      1/1     Running   6          44h   app=flannel,controller-revision-hash=56c5465959,pod-template-generation=1,tier=node
kube-flannel-ds-amd64-vcqcz      1/1     Running   4          43h   app=flannel,controller-revision-hash=56c5465959,pod-template-generation=1,tier=node
kube-proxy-75gjn                 1/1     Running   5          43h   controller-revision-hash=77fcbc7cf9,k8s-app=kube-proxy,pod-template-generation=1
kube-proxy-fj6js                 1/1     Running   6          44h   controller-revision-hash=77fcbc7cf9,k8s-app=kube-proxy,pod-template-generation=1
kube-proxy-kpfrl                 1/1     Running   5          43h   controller-revision-hash=77fcbc7cf9,k8s-app=kube-proxy,pod-template-generation=1
kube-scheduler-master            1/1     Running   5          44h   component=kube-scheduler,tier=control-plane

[root@master ~]# kubectl delete pods -l k8s-app=kube-proxy -n kube-system  # 使用-l 選項,過濾關鍵的標籤進行刪除。
pod "kube-proxy-75gjn" deleted
pod "kube-proxy-fj6js" deleted
pod "kube-proxy-kpfrl" deleted

 

3、查看此時重構新的kube-proxy標籤,此時可以看到已經成爲最新的kube-proxy標籤

[root@master ~]# kubectl get pods -n kube-system
NAME                             READY   STATUS    RESTARTS   AGE
coredns-546565776c-fl859         1/1     Running   20         44h
coredns-546565776c-mwt5p         1/1     Running   18         44h
etcd-master                      1/1     Running   5          44h
kube-apiserver-master            1/1     Running   7          44h
kube-controller-manager-master   1/1     Running   5          44h
kube-flannel-ds-amd64-rpdk6      1/1     Running   4          43h
kube-flannel-ds-amd64-rsb4s      1/1     Running   6          44h
kube-flannel-ds-amd64-vcqcz      1/1     Running   4          43h
kube-proxy-djvh5                 1/1     Running   0          50s
kube-proxy-r8lc5                 1/1     Running   0          51s
kube-proxy-xkh9j                 1/1     Running   0          53s
kube-scheduler-master            1/1     Running   5          44h

 

4、此時在node1上查看ipvs的規則信息,默認的調度方式是rr方式

[root@node1 ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  127.0.0.1:30081 rr
TCP  172.17.0.1:30081 rr
TCP  172.17.0.1:31180 rr
TCP  192.168.7.102:30081 rr
TCP  192.168.7.102:31180 rr
TCP  10.96.0.1:443 rr
  -> 192.168.7.101:6443           Masq    1      0          0         
TCP  10.96.0.10:53 rr
  -> 10.224.0.26:53               Masq    1      0          0         
  -> 10.224.0.27:53               Masq    1      0          0         
TCP  10.96.0.10:9153 rr
  -> 10.224.0.26:9153             Masq    1      0          0         
  -> 10.224.0.27:9153             Masq    1      0          0         
TCP  10.97.97.97:80 rr
  -> 10.224.1.36:80               Masq    1      0          0         
  -> 10.224.2.33:80               Masq    1      0          0         
TCP  10.97.107.135:80 rr
TCP  10.99.99.99:6380 rr
  -> 10.224.1.41:6380             Masq    1      0          0         
TCP  10.99.99.244:6380 rr
TCP  10.102.139.95:80 rr
TCP  10.105.2.202:80 rr
  -> 10.224.2.35:80               Masq    1      0          0         
TCP  10.107.67.151:80 rr
  -> 10.224.2.35:80               Masq    1      0          0         
TCP  10.224.1.0:30081 rr
TCP  10.224.1.0:31180 rr
TCP  10.224.1.1:30081 rr
TCP  10.224.1.1:31180 rr
TCP  127.0.0.1:31180 rr
UDP  10.96.0.10:53 rr
  -> 10.224.0.26:53               Masq    1      0          0         
  -> 10.224.0.27:53               Masq    1      0          0 

 

5、驗證此時的服務還可以進行訪問

[root@master ~]# kubectl get pods  -o wide      # 查看創建所有pod的詳細信息
NAME                          READY   STATUS    RESTARTS   AGE    IP            NODE    NOMINATED NODE   READINESS GATES
liveness-httpget-pod          1/1     Running   2          17h    10.224.2.32   node2   <none>           <none>
myapp-79476667f5-jqhvt        1/1     Running   1          13h    10.224.1.39   node1   <none>           <none>
myapp-79476667f5-xljzk        1/1     Running   1          13h    10.224.1.38   node1   <none>           <none>
nginx-6dd57bccf7-mkrmx        1/1     Running   3          43h    10.224.1.37   node1   <none>           <none>
nginx-dep-84b6dfdcd5-gm9dd    1/1     Running   3          43h    10.224.2.36   node2   <none>           <none>
ngx-dep-5d855b5b54-98rc2      1/1     Running   3          43h    10.224.2.35   node2   <none>           <none>
ngx-deploy-65fb6c8459-2zm44   1/1     Running   1          13h    10.224.2.33   node2   <none>           <none>
ngx-deploy-65fb6c8459-whgxx   1/1     Running   1          13h    10.224.1.36   node1   <none>           <none>
redis-658fb45c88-9clst        1/1     Running   0          111m   10.224.1.41   node1   <none>           <none>

[root@master ~]# curl 10.224.1.39  # 可以看到之前創建的pod服務還是可以訪問到
Hello MyApp | Version: v3 | <a href="hostname.html">Pod Name</a>

  

 

第二種方法初始化k8s集羣方式:由於前面已經使用kubeadm初始化了k8s集羣,此時無法啓動ipvs規則,以下是在開始使用kubeadm初始化k8s集羣部署時使用的方法,kubeadm也可通過配置文件加載配置,以定製更豐富的部署選項。以下是個符合前述命令設定方式的使用示例,不過,它明確定義了kubeProxy的模式爲ipvs,並支持通過修改imageRepository的值修改獲取系統鏡像時使用的鏡像倉庫。

apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
kubernetesVersion: v1.13.3   # 指定k8s版本
api:
  advertiseAddress: 172.20.0.71
  bindPort: 6443
  controlPlaneEndpoint: ""
imageRepository: k8s.gcr.io
kubeProxy:
  config:
    mode: "ipvs"                  # 只需要在此處改爲指定的ipvs規則
    ipvs:
      ExcludeCIDRs: null
      minSyncPeriod: 0s
      scheduler: ""
      syncPeriod: 30s    
kubeletConfiguration:
  baseConfig:
    cgroupDriver: cgroupfs
    clusterDNS:
    - 10.96.0.10
    clusterDomain: cluster.local
    failSwapOn: false
    resolvConf: /etc/resolv.conf
    staticPodPath: /etc/kubernetes/manifests
networking:
  dnsDomain: cluster.local
  podSubnet: 10.244.0.0/16            # 指定Pod網段
  serviceSubnet: 10.96.0.0/12        # 指定的service網段

將上面的內容保存於配置文件中,例如kubeadm-config.yaml,而後執行相應的命令:

~]# kubeadm init --config kubeadm-config.yaml --ignore-preflight-errors=Swap

 

1.4 service定義資源清單幾個字段

  •  apiVersion: v1  版本
  •  kind: Service  類型
  •  metadata  元數據
  •  spec  期望狀態
    •  ports:服務公開的端口列表;把哪個端口和後端建立聯繫
      •  port:此服務將公開的端口
      •  targetPort:要在服務所針對的pod上訪問的端口的編號或名稱
      •  nodePort:K8S 集羣節點上的端口
    •  selector:標籤選擇器;關聯到哪些pod資源上程序。 
    •  clusterIP:服務的IP地址,通常由主服務器隨機分配,Service 資源的默認類型爲 ClusterIP, 它僅能接收來自於集羣中的 Pod 對象中的客戶端程序的訪問請求。 
    •  type:確定服務的公開方式。 默認爲ClusterIP
      •  ClusterIP(默認)
      •  NodePort
      •  LoadBalancer
      •  ExternelName
    •  sessionAffinity:service負載均衡,默認值是None,根據iptables規則隨機調度;可使用sessionAffinity保持會話連線;
  •  status  當前狀態

 

1.5 service的4中類型

  •  ClusterIP(默認):僅用於集羣內通信,集羣內部可達,可以被各pod訪問,節點本身可訪問;
  •  NodePort:構建在ClusterIP上,並在路由到clusterIP的每個節點上分配一個端口;
    •  client ---> NodeIP:NodePort ---> ClusterIP:ServicePort ---> PodIP:containePort
  •  LoadBalancer:構建在NodePort上,並創建一個外部負載均衡器(如果在當前雲中受支持),它將路由到clusterIP;
  •  ExternelName:通過CNAME將service與externalName的值(比如:foo.bar.example.com)映射起來. 要求kube-dns的版本爲1.7或以上.

 

2、創建clusterIP類型的service

(1)編寫yaml文件並創建名爲redis的service

先創建一個deployment,啓動一個redis pod;在使用service綁定這個pod,其中三個"---"是資源分割符,不能多也不能少

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
[root@master manifests]# vim redis-svc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
      role: logstor
  template:
    metadata:
      labels:
        app: redis
        role: logstor
    spec:
      containers:
      - name: redis
        image: redis:4.0-alpine
        ports:
        - name: redis
          containerPort: 6379  # 後端容器端口
---
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: default
spec:
  selector:
    app: redis
    role: logstor
  clusterIP: 10.99.99.99
  type: ClusterIP
  ports:
  - port: 6380
    targetPort: 6379  # 要與後端的容器端口一致
[root@master manifests]# kubectl apply -f redis-svc.yaml
deployment.apps/redis created
service/redis created

  

(2)查詢驗證

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP    142d
redis        ClusterIP   10.99.99.99   <none>        6380/TCP   12s
---查詢service詳細信息,pod綁定成功
[root@master ~]# kubectl describe svc redis
Name:              redis
Namespace:         default
Labels:            <none>
Annotations:       kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"redis","namespace":"default"},"spec":{"clusterIP":"10.99.99.99","ports":[{"por...
Selector:          app=redis,role=logstor
Type:              ClusterIP
IP:                10.99.99.99
Port:              <unset>  6380/TCP
TargetPort:        6379/TCP
Endpoints:         10.244.2.94:6379
Session Affinity:  None
Events:            <none>

  

3、創建NodePort類型的service

3.1 創建service

(1)編寫yaml文件並創建名爲myapp的service

先創建一個deployment,啓動3個myapp pod;在使用service綁定這3個pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[root@master manifests]# vim myapp-svc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: http
          containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  clusterIP: 10.97.97.97
  type: NodePort # 與下面自定義的31180端口對應
  ports:
  - port: 80
    targetPort: 80  # 要與後端服務器端口一致
    nodePort: 31180 # 自定義了一個端口,一般不會去手動定義
[root@master manifests]# kubectl apply -f myapp-svc.yaml
deployment.apps/myapp-deploy unchanged
service/myapp created

  

(2)查詢驗證

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        145d
myapp        NodePort    10.97.97.97   <none>        80:31180/TCP   39s
redis        ClusterIP   10.99.99.99   <none>        6380/TCP       2d
[root@master ~]# kubectl describe svc myapp
Name:                     myapp
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"clusterIP":"10.97.97.97","ports":[{"nod...
Selector:                 app=myapp,release=canary
Type:                     NodePort
IP:                       10.97.97.97
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  31180/TCP
Endpoints:                10.244.1.96:80,10.244.2.101:80,10.244.2.102:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

  

(3)在集羣外訪問服務

 

 

3.2 使用sessionAffinity保持會話連接

(1)sessionAffinity默認是None,沒有修改前,訪問業務是隨機調度

1
2
3
4
5
6
[root@master ~]# while true; do curl 192.168.10.103:31180/hostname.html; sleep 1; done
myapp-deploy-69b47bc96d-mmb5v
myapp-deploy-69b47bc96d-wtbx7
myapp-deploy-69b47bc96d-wtbx7
myapp-deploy-69b47bc96d-cj48v
... ...

  

(2)打補丁修改sessionAffinity爲clientip;實現會話連接

也可以使用exec修改;或者直接修改yaml文件也可以;

1
2
[root@master ~]# kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"ClientIP"}}'
service/myapp patched

  

(3)查詢驗證

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@master ~]# kubectl describe svc myapp
Name:                     myapp
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"clusterIP":"10.97.97.97","ports":[{"nod...
Selector:                 app=myapp,release=canary
Type:                     NodePort
IP:                       10.97.97.97
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  31180/TCP
Endpoints:                10.244.1.96:80,10.244.2.101:80,10.244.2.102:80
Session Affinity:         ClientIP
External Traffic Policy:  Cluster
Events:                   <none>

  

(4)訪問業務查詢驗證;發現同一客戶端的請求始終發往同一pod

1
2
3
4
5
6
[root@master ~]# while true; do curl 192.168.10.103:31180/hostname.html; sleep 1; done
myapp-deploy-69b47bc96d-cj48v
myapp-deploy-69b47bc96d-cj48v
myapp-deploy-69b47bc96d-cj48v
myapp-deploy-69b47bc96d-cj48v
... ...

  

(5)重新打補丁修改爲None,立即恢復爲隨機調度

1
2
3
4
5
6
7
[root@master ~]# kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"None"}}'
service/myapp patched
[root@master ~]# while true; do curl 192.168.10.103:31180/hostname.html; sleep 1; done
myapp-deploy-69b47bc96d-cj48v
myapp-deploy-69b47bc96d-mmb5v
myapp-deploy-69b47bc96d-cj48v
myapp-deploy-69b47bc96d-mmb5v

  

4、創建無頭service

(1)編寫yaml文件並創建名爲myapp-svc的service

綁定上面創建myapp的3個pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@master manifests]# vim myapp-svc-headless.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  clusterIP: None  # 將clusterIP改爲None就是隨機的IP地址,也就是無頭Service
  ports:
  - port: 80
    targetPort: 80
[root@master manifests]# kubectl apply -f myapp-svc-headless.yaml
service/myapp-svc created

  

(2)查詢驗證

1
2
3
4
5
6
[root@master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        145d
myapp        NodePort    10.97.97.97   <none>        80:31180/TCP   2h
myapp-svc    ClusterIP   None          <none>        80/TCP         6s
redis        ClusterIP   10.99.99.99   <none>        6380/TCP       2d

  

(3)和有頭正常myapp的service對比

無頭service的解析:

1
2
3
4
5
6
7
[root@master manifests]# dig -t A myapp-svc.default.svc.cluster.local. @10.96.0.10
... ...
;; ANSWER SECTION:
myapp-svc.default.svc.cluster.local. 5 IN A 10.244.1.96
myapp-svc.default.svc.cluster.local. 5 IN A 10.244.2.101
myapp-svc.default.svc.cluster.local. 5 IN A 10.244.2.102
... ...

有頭正常myapp的service的解析:

[root@master manifests]# dig -t A myapp.default.svc.cluster.local. @10.96.0.10
... ...
;; ANSWER SECTION:
myapp.default.svc.cluster.local. 5 IN   A   10.97.97.97
... ...

  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章