k8s的service

1.service簡介

本節開始學習 Service。
咱們不該該指望 Kubernetes Pod 是健壯的,而是要假設 Pod 中的容器極可能由於各類緣由發生故障而死掉。Deployment 等 controller 會經過動態建立和銷燬 Pod 來保證應用總體的健壯性。換句話說,Pod 是脆弱的,但應用是健壯的。html

每一個 Pod 都有本身的 IP 地址。當 controller 用新 Pod 替代發生故障的 Pod 時,新 Pod 會分配到新的 IP 地址。這樣就產生了一個問題:node

若是一組 Pod 對外提供服務(好比 HTTP),它們的 IP 頗有可能發生變化,那麼客戶端如何找到並訪問這個服務呢?後端

Kubernetes 給出的解決方案是 Service。api

 

2.建立 Service

Kubernetes Service 從邏輯上表明瞭一組 Pod,具體是哪些 Pod 則是由 label 來挑選。Service 有本身 IP,並且這個 IP 是不變的。客戶端只須要訪問 Service 的 IP,Kubernetes 則負責創建和維護 Service 與 Pod 的映射關係。不管後端 Pod 如何變化,對客戶端不會有任何影響,由於 Service 沒有變。服務器

來看個例子,建立下面的這個 Deploymentapp

 

apiVersion: apps/v1beta1                                                                                    
kind: Deployment                                                                                            
metadata:                                                                                                   
  name: httpd                                                                                               
spec:                                                                                                       
  replicas: 3                                                                                                
  template:                                                                                                 
    metadata:                                                                                               
      labels:                                                                                               
        run: httpd                                                                                          
    spec:                                                                                                   
      containers:                                                                                           
      - name: httpd                                                                                         
        image: httpd                                                                                        
        ports:                                                                                              
        - containerPort: 80 

咱們啓動了三個 Pod,運行 httpd 鏡像,label 是 run: httpd,Service 將會用這個 label 來挑選 Pod。負載均衡

 

Pod 分配了各自的 IP,這些 IP 只能被 Kubernetes Cluster 中的容器和節點訪問。ide

 接下來建立 Service,其配置文件以下:post

[root@k8s-master k8s]# cat httpd-service.yml 
apiVersion: v1
kind: Service
metadata:
  name: httpd-service
spec:
  selector:
    run: httpd
  ports:
  - protocal: TCP
    port: 8080
    targetPort: 80

① v1 是 Service 的 apiVersion學習

② 指明當前資源的類型爲 Service

③ Service 的名字爲 httpd-service

④ selector 指明挑選那些 label 爲 run: httpd 的 Pod 做爲 Service 的後端。

⑤ 將 Service 的 8080 端口映射到 Pod 的 80 端口,使用 TCP 協議。

執行 kubectl apply 建立 Service httpd-service

httpd-service 分配到一個 CLUSTER-IP 10.111.195.121。能夠經過該 IP 訪問後端的 httpd Pod。

 

根據前面的端口映射,這裏要使用 8080 端口。另外,除了咱們建立的 httpd-service,還有一個 Service kubernetes,Cluster 內部經過這個 Service 訪問 kubernetes API Server。

經過 kubectl describe 能夠查看 httpd-svc 與 Pod 的對應關係。Endpoints中的地址正好和前面的建立的3個pod的地址相對應

 

3.Service-IP的工做原理

Service Cluster IP 是一個虛擬 IP,是由 Kubernetes 節點上的 iptables 規則管理的。

能夠經過 iptables-save 命令打印出當前節點的 iptables 規則,由於輸出較多,這裏只截取與httpd-service  Cluster IP 10.111.195.121 相關的信息

 

這兩條規則的含義是:

  1. 若是 Cluster 內的 Pod(源地址來自 10.244.0.0/16)要訪問 httpd-service,則容許。

  2. 其餘源地址訪問 httpd-service,跳轉到規則KUBE-SVC-X2P42VLQEZCHLPKZ。

KUBE-SVC-X2P42VLQEZCHLPKZ 規則以下:

 

  1. 1/3 的機率跳轉到規則  KUBE-SEP-XXIX5IS7GC2GUSM2

  2. 1/3 的機率(剩下 2/3 的一半)跳轉到規則  KUBE-SEP-LXY54WDLWY2BJFLU

  3. 1/3 的機率跳轉到規則 KUBE-SEP-R7HFCFW5PWEDBIAO

上面的轉發規則經過DNAT目標地址轉換來實現請求轉發

iptables 將訪問 Service 的流量轉發到後端 Pod,並且使用相似輪詢的負載均衡策略。

另外須要補充一點:Cluster 的每個節點都配置了相同的 iptables 規則,這樣就確保了整個 Cluster 都可以經過 Service 的 Cluster IP 訪問 Service。

 

每一個節點均可以經過統一clusterIP 來訪問,並且自動實現了應用之間的負載均衡。

4.經過DNS來訪問service

 

在 Cluster 中,除了能夠經過 Cluster IP 訪問 Service,Kubernetes 還提供了更爲方便的 DNS 訪問。

kubeadm 部署時會默認安裝 kube-dns 組件。

kube-dns 是一個 DNS 服務器。每當有新的 Service 被建立,kube-dns 會添加該 Service 的 DNS 記錄。Cluster 中的 Pod 能夠經過 <SERVICE_NAME>.<NAMESPACE_NAME> 訪問 Service。

 

 好比能夠用 httpd-service.default 訪問 Service httpd-service

 

如上所示,咱們在一個臨時的 busybox Pod 中驗證了 DNS 的有效性。另外,因爲這個 Pod 與 httpd-service同屬於 default namespace,能夠省略 default 直接用 httpd-service 訪問 Service。

 若是要訪問其餘 namespace 中的 Service,就必須帶上 namesapce 了。kubectl get namespace 查看已有的 namespace。

在 kube-public 中部署 Service httpd2-service,配置以下:

 

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: httpd2
  namespace: kube-public
spec:
  replicas: 3
  template:
    metadata:
      labels:
        run: httpd2
    spec:
      containers:
      - name: httpd2
        image: httpd
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: httpd2-service
  namespace: kube-public
spec:
  selector:
    run: httpd2
  ports:
  - protocol: TCP 
    port: 8080
    targetPort: 80

 

查看 kube-public 的 Service:

 

5.外網訪問Service

除了 Cluster 內部能夠訪問 Service,不少狀況咱們也但願應用的 Service 可以暴露給 Cluster 外部。Kubernetes 提供了多種類型的 Service,默認是 ClusterIP。

ClusterIP 
Service 經過 Cluster 內部的 IP 對外提供服務,只有 Cluster 內的節點和 Pod 可訪問,這是默認的 Service 類型,前面實驗中的 Service 都是 ClusterIP。

NodePort 
Service 經過 Cluster 節點的靜態端口對外提供服務。Cluster 外部能夠經過 <NodeIP>:<NodePort> 訪問 Service。

LoadBalancer 
Service 利用 cloud provider 特有的 load balancer 對外提供服務,cloud provider 負責將 load balancer 的流量導向 Service。目前支持的 cloud provider 有 GCP、AWS、Azur 等。

下面咱們來實踐 NodePort,Service httpd-service 的配置文件修改以下:

添加 type: NodePort,從新建立 httpd-service

 

Kubernetes 依然會爲 httpd-svc 分配一個 ClusterIP,不一樣的是:

  1. EXTERNAL-IP 爲 nodes,表示可經過 Cluster 每一個節點自身的 IP 訪問 Service。

  2. PORT(S) 爲 8080:31650  8080 是 ClusterIP 監聽的端口,32312 則是節點上監聽的端口。Kubernetes 會從 30000-32767 中分配一個可用的端口,每一個節點都會監聽此端口並將請求轉發給 Service。

 下面測試 NodePort 是否正常工做。

經過三個節點 IP + 31650 端口都可以訪問 httpd-servicee

接下來咱們深刻探討一個問題:Kubernetes 是如何將 <NodeIP>:<NodePort> 映射到 Pod 的呢?

與 ClusterIP 同樣,也是藉助了 iptables。與 ClusterIP 相比,每一個節點的 iptables 中都增長了下面兩條規則

規則的含義是:訪問當前節點 32312 端口的請求會應用規則 KUBE-SVC-X2P42VLQEZCHLPKZ ,內容爲:

 

其做用就是負載均衡到每個 Pod。

NodePort 默認是的隨機選擇,不過咱們能夠用 nodePort 指定某個特定端口

 

 

如今配置文件中就有三個 Port 了:
nodePort 是節點上監聽的端口。
port 是 ClusterIP 上監聽的端口。
targetPort 是 Pod 監聽的端口。

最終,Node 和 ClusterIP 在各自端口上接收到的請求都會經過 iptables 轉發到 Pod 的 targetPort

應用新的 nodePort 並驗證:

 

nodePort: 30000 已經生效了。

相關文章
相關標籤/搜索