Kubernetes Service之ClusterIP

liuxuhui發表於2021-09-09
Kubernetes Service ClusterIP

Kubernetes的service有三種型別:ClusterIP,NodePort,LoadBalancer,今天我們來看看ClusterIP。

建立Deployment

首先我們先建立一個Deployment,這個Deployment是一個Python實現的HTTP服務,請求這個Web Server的時候,會發回給我們這個server的hostname(如果是container,那就是container的hostname)。

這個Deployment有四個Replica。

$ more deployment_python_http.yml
apiVersion:  apps/v1
kind: Deployment
metadata:
  name: service-test
spec:
  replicas: 4
  selector:
    matchLabels:
      app: service_test_pod
  template:
    metadata:
      labels:
        app: service_test_pod
    spec:
      containers:
      - name: simple-http
        image: python:2.7
        imagePullPolicy: IfNotPresent
        command: ["/bin/bash"]
        args: ["-c", "echo "

Hello from $(hostname)

" > index.html; python -m SimpleHTTPServer 8080"] ports: - name: http containerPort: 8080 $ kubectl create -f deployment_python_http.yml deployment.apps "service-test" created

建立完我們看到pod是這樣的;

$ kubectl get pod -o wide
NAME                            READY     STATUS    RESTARTS   AGE       IP          NODE
service-test-54b5b4b547-8l9s4   1/1       Running   0          1m        10.36.0.0   ks8-node2
service-test-54b5b4b547-c2t85   1/1       Running   0          1m        10.36.0.1   ks8-node2
service-test-54b5b4b547-nxn9z   1/1       Running   0          1m        10.40.0.1   k8s-node1
service-test-54b5b4b547-vlpff   1/1       Running   0          1m        10.40.0.0   k8s-node1

這四個pod IP我們都可以在k8s cluster任意一個節點上訪問,每一個都會返回自己的container name。

$ curl 10.36.0.0:8080

Hello from service-test-54b5b4b547-8l9s4

建立Service

透過kubectl expose給剛才這個deployment建立一個service,埠繫結為8088.

kubectl expose deployment service-test --port 8088 --target-port=8080
service "service-test" exposed

這樣,就給我們生成了一個型別為ClusterIP的service,這個service有一個Cluster IP,其實就一個VIP。

kubectl get service -o wide
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE       SELECTOR
kubernetes     ClusterIP   10.96.0.1               443/TCP    1d        
service-test   ClusterIP   10.101.90.210           8088/TCP   11s       app=service_test_pod

首先我們可以透過這個Cluster IP加埠8088訪問我們的deployment。

$ for i in `seq 4`; do curl 10.101.90.210:8088; done

Hello from service-test-54b5b4b547-nxn9z

Hello from service-test-54b5b4b547-vlpff

Hello from service-test-54b5b4b547-vlpff

Hello from service-test-54b5b4b547-nxn9z

並且我們發現,這個VIP實現了負載均衡,每次返回的hostname不同。

VIP和負載均衡的實現

為什麼我們訪問VIP就能訪問我們的四個pod,並且還做了負載均衡呢?下面我們就看一下,

其實呢,我們剛才建立這個deployment,service的時候,k8s叢集下面的幾個部件參與了相關的工作。

  • apiserver kubectl命令向apiserver傳送建立service的命令,apiserver接收到請求以後將資料儲存到etcd中。
  • kube-proxy kubernetes的每個節點中都有一個叫做kube-proxy的程式,這個程式負責感知service,pod的變化,並將變化的資訊寫入本地的iptables中。
  • iptables 使用NAT等技術將virtualIP的流量轉至endpoint中。

那麼IPtable到底是如何轉發我們的流量的呢,我們到任意一臺k8s節點執行 sudo iptables -L -v -n -t nat

首先找到我們的ClusterIP 10.101.90.210,發現他在一個iptables chain中

Chain KUBE-SERVICES (2 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-MARK-MASQ  tcp  --  *      *      !172.100.0.0/16       10.101.90.210        /* default/service-test: cluster IP */ tcp dpt:8088
    0     0 KUBE-SVC-LY73ZDGF4KGO4YFJ  tcp  --  *      *       0.0.0.0/0            10.101.90.210        /* default/service-test: cluster IP */ tcp dpt:8088

這個chain類似一個鏈條,那麼訪問10.101.90.210:8088的流量到底怎麼被轉發了呢,我們需要看一下 KUBE-SVC-LY73ZDGF4KGO4YFJ 這個Chain, 找到這個chain

Chain KUBE-SVC-LY73ZDGF4KGO4YFJ (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-SEP-YOQWVZZ4NQDNEBVN  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/service-test: */ statistic mode random probability 0.25000000000
    0     0 KUBE-SEP-WHOFXZ2VQXEUUKVO  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/service-test: */ statistic mode random probability 0.33332999982
    0     0 KUBE-SEP-3TBKTCTGJZ27RFOH  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/service-test: */ statistic mode random probability 0.50000000000
    0     0 KUBE-SEP-6LDVTIHDBDOU3D3G  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/service-test: */

這個Chain比較有意思,過來的流量它按照隨機的機率,分別以0.25000000000, 0.33332999982,0.50000000000的機率,轉發到這三個Chain,這三個Chain其實就是我們的pod,那為啥有一個pod不會被轉發呢,這個應該是負載均衡的配置,最大幾個負載均衡的問題。

我們隨便拿出一個

Chain KUBE-SEP-WHOFXZ2VQXEUUKVO (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-MARK-MASQ  all  --  *      *       10.36.0.1            0.0.0.0/0            /* default/service-test: */
    0     0 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/service-test: */ tcp to:10.36.0.1:8080

好的,那經過這麼一轉發,我們的流量就可以轉發到正確的pod上了,不知道大家明白沒有。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/756/viewspace-2810084/,如需轉載,請註明出處,否則將追究法律責任。

相關文章