首頁>技術>

建立服務之後,我們就擁有了一個單一的、固定的IP地址和埠號,透過它就可以訪問到pod。這個地址在服務的整個生命週期內都不會改變,而服務後面的pod可能變來變去。它們的IP地址可能變化,數量也會增減,但是始終可以透過服務的單一不變的IP地址訪問到這些pod。

但是客戶端pod如何知道服務的IP和埠?是否需要先建立服務,然後手動查詢它的IP地址並將IP地址傳遞給客戶端pod的配置選項?當然不是。Kubernetes為客戶端pod發現服務的IP地址和埠提供了幾種方法。

透過環境變數發現服務

當啟動pod時,Kubernetes會初始化一組環境變數,指向當前存在的每個服務。如果在建立客戶端pod之前就建立了服務,pod中的程序就可以透過檢查環境變數而獲取到服務的IP地址和埠。

當前環境中有三個pod:

執行如下命令可以檢視pod的環境變數:

kubectl exec test-rc-8n2b8 -- env
kubectl delete po --all

檢視自動建立的pod:

可以在容器中執行env命令檢視pod的環境變數:

kubectl exec test-rc-j9j4w -- env

TEST_SVC_SERVICE_HOST就是服務的叢集IP地址,TEST_SVC_PORT是服務的埠。

在上一節我們提到了前端web伺服器pod和後端資料庫伺服器pod的例子,如果前端pod需要使用後端資料庫伺服器pod,可以透過一個比如叫做backend-database的服務將後端pod暴露出去,然後讓前端pod透過環境變數BACKEND_DATABASE_SERVICE_HOST和BACKEND_DATABASE_SERVICE_PORT查詢服務的IP地址和埠。

服務名中的橫槓會被轉換成下劃線,當服務名被用作環境變數名字首的時候所有字母轉成大寫

環境變數是查詢服務IP地址和埠的一種方式。Kubernetes還包含了一個DNS伺服器,可以透過DNS來查詢服務IP地址。

透過DNS發現服務

在kube-system名稱空間下有一個叫做coredns的pod。從 K8S 1.11 開始,K8S 使用 CoreDNS替換KubeDNS作為DNS伺服器:

kubectl get po --namespace kube-system

在該名稱空間下還存在一個名為kube-dns的service:

kubectl get svc --namespace kube-system

透過名稱可以看出該pod中運行了一個DNS伺服器,叢集中執行的所有其他pod會自動地配置使用該DNS伺服器(Kubernetes透過修改每個容器的/etc/resolv.conf檔案來實現)。Pod中執行程序執行的任何DNS查詢都會被Kubernetes自身的DNS伺服器處理,它知道系統中執行的所有服務。

可以透過在每個pod的spec區段中配置dnsPolicy屬性來決定其是否使用內部的DNS伺服器

每個服務從內部的DNS伺服器中獲得一個DNS條目,客戶端pod在知道服務名的情況下可以透過它的全限定域名(FQDN=Fully Qualified Domain Name)來訪問服務,而不是使用環境變數。

透過FQDN連線服務

一個前端pod可以透過開啟一個到如下FQDN的連線來與後端資料庫服務建立連線:

backend-database.default.svc.cluster.local

backend-database對應於服務名稱,default表示服務所在的名稱空間,svc.cluster.local是一個在所有叢集本地服務名中使用的可配置的叢集domain字尾。

客戶端仍然必須知道服務的埠號。如果服務正在使用一個標準的埠(HTTP的80埠或者MySQL的3306埠),這樣是不會有問題的。如果使用的是非標準埠,客戶端可以從環境變數獲得埠號。

我們還可以去掉svc.cluster.local字尾,甚至名稱空間(如果前端pod和資料庫pod位於同一個名稱空間下),因此可以簡單地只通過backend-database引用服務。

現在我們試著透過FQDN來訪問之前建立的service,這需要在一個已有的pod中來完成。

可以使用kubectl exec命令在一個已有的pod中執行bash命令進入pod容器:

kubectl exec -it test-rc-j9j4w -- bash

當前我們處在容器中,因此可以透過如下幾種方式使用curl命令訪問test-svc服務:

curl http://test-svc.default.svc.cluster.local
curl http://test-svc.default
curl http://test-svc

在請求URL中,可以將服務名作為主機名來訪問服務,因為根據每個pod容器DNS解析器的配置方式,可以將名稱空間和svc.cluster.local字尾移除。

在容器中檢視/etc/resolv.conf檔案:

如果我們試著直接ping服務,會發現無法ping通:

ping test-svc

為什麼curl可以,而ping不可以呢?這是由於服務的叢集IP是一個虛擬的IP,而且只有和服務埠號結合使用的時候才有意義。這點我們在後面的學習中再慢慢了解具體原因以及服務的工作方式

18
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Python入門基礎知識,讓你少走點彎路