1. 程式人生 > 其它 >Docker與k8s的恩怨情仇(七)—— “服務發現”大法讓你的內外互動原地起飛

Docker與k8s的恩怨情仇(七)—— “服務發現”大法讓你的內外互動原地起飛

轉載請註明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。

第一章:Docker與k8s的恩怨情仇(一)—成為PaaS前浪的Cloud Foundry

第二章:Docker與k8s的恩怨情仇(二)—用最簡單的技術實現“容器”

第三章:Docker與k8s的恩怨情仇(三)—後浪Docker來勢洶洶

第四章:Docker與k8s的恩怨情仇(四)-雲原生時代的閉源落幕

第五章:Docker與k8s的恩怨情仇(五)——Kubernetes的創新

第六章:Docker與k8s的恩怨情仇(六)—— “容器編排”上演“終結者”大片

在上節中我們介紹了活字格公有云版在k8s上部署,以及如何實現容器之間的編排與管理控制。為了進一步實現內外互動呼叫,則需要實現服務發現的功能。也就是我們前面提到“人與狗”之間的關係。

做過微服務的同學可能瞭解過什麼叫服務發現,spring cloud專案中的Eureka框架就是完成這個功能的,其主要工作就是註冊內部的服務,以供其他叢集的服務可以呼叫、訪問這個服務。

我們合理猜測Kubernetes的存在很有可能激發了各種微服務框架產生服務發現機制。

在Kubernetes中服務發現對應的模組是Service與Ingress,接下來,我們分別來說說這兩個功能。

Service與Ingress

Service類似於服務的註冊功能。

其邏輯很簡單,在kubernetes宣告一個服務,從而生成一個VIP(虛擬網路),所有Kubernetes叢集中的其他元件,都可以通過這個VIP來訪問這個服務,並且這個服務是不會隨Service的改變而改變的,只要建立就是終生存在。

Service

而服務的內容是什麼呢?這部分和上述的Deployment一樣,是通過selector選擇器確定的。我們可以通過下述yaml來建立一個服務:

apiVersion:v1

kind:Service

metadata:

name:hostnames

spec:

selector:

app:hostnames

ports:

-name:default

protocol:TCP

port:80

targetPort:9376

通過上一篇的介紹,我們可以瞭解這個服務所需要代理的內容是app==hostnames的Pod。同時這裡也有一個新的欄位ports,這個欄位是說明該代理的服務的請求方式(protocol)、對外暴露的埠(port)、內部的埠(targetPort)分別是什麼。

我們可以通過這個sample-service.yaml的檔案建立一個Service並且檢視一個Service:


#建立

kubectlapply-fsample-service.yaml



#檢視

kubectlgetserviceshostnames

在這個service中存在一個ClusterIP,這個IP就是這個Service生成的VIP,在叢集內部的其他成員,都可以通過這個VIP來訪問這個Service。但是由於我們現在沒有任何的具體服務讓這個Service代理,因此現在請求這個IP是不會成功的。

那麼,我們需要為這個Service建立一個具體實現:以下的sample-deployment.yaml檔案是建立一個多副本的Pod,其Pod的功能是返回自己的podname:


apiVersion:apps/v1

kind:Deployment

metadata:

name:hostnames

spec:

selector:

matchLabels:

app:hostnames

replicas:3

template:

metadata:

labels:

app:hostnames

spec:

containers:

-name:hostnames

image:k8s.gcr.io/serve_hostname

ports:

-containerPort:9376

protocol:TCP

~

在這段程式碼中,我們把容器的9376埠暴露的出來,因為這個Pod是通過這個埠與外部通行的。同樣我們執行以下命令建立和檢視這個pod副本:

#建立

kubectlapply-fsample-deployment.yaml



#檢視

kubectlgetpods-lapp=hostnames

在這部分內容中可以看到這個pod副本已經建立成功了。此時,根據我上一節所說的控制器模式,Service也有對應的處理Service的控制器,其內部發現了有滿足app==hostnames的服務,即將這個服務和Service進行了繫結 。此時,我們就可以通過任意一臺叢集內的主機來請求剛才上文中的ClusterIP:

在這一部分可以看到,我們進行了很多次請求,但是每次返回的結果都不同,這是因為Service在其內部通過網路外掛(CNI)做了負載均衡處理,所以我們可以通過Service來實現的負載均衡功能。

學習過程中的“誤入歧路”

在學習瞭解這部分內容的時候,我一直有一個誤解:認為Service是必須對應Deployment這種Pod的編排控制器物件才能工作的,所以把Service --> Deployment --> Pods這條邏輯關係熟記於心,但這種理解其實是錯誤的。

在Kubernetes中,每個功能元件各司其職,他們只會處理自己該做的事,比如這裡,Service繫結Pod所依賴的是選擇器中的app==hostnames,而這個定義是出現在Deployment中定義在Pod中的,因此Service和Deployment完全沒有關係,它們倆誰也不認識誰,關係可以用下圖來描述:

並且,在之前的學習中還錯誤地認為負載均衡服務是由Deployment提供的,其實這個功能是Service中的網路外掛來處理的,並且使用者同樣也可以自定義使用的網路查件或者負載均衡演算法是什麼,Kubernetes給了使用者足夠大的自由度。

Ingress

有了Service之後,我們的服務就可以在叢集中隨意訪問達到服務之間的交流關係了, 但是要想讓我們的服務讓最終的使用者訪問到,我們還需要最後一個元件Ingress。

Ingress是Kubernetes中的反向代理服務,它可以解析配置的域名指向到我們內部的Service中,其定義可以通過下述的yaml來實現:

apiVersion:extensions/v1beta1

kind:Ingress

metadata:

name:sample-ingress

spec:

rules:

-host:hostname.sample.com

http:

paths:

-path:/

backend:

serviceName:hostnames

servicePort:80

上述程式碼中,我們將hostname.sample.com這個域名指向了剛才定義的hostnames這個Service。通過這樣的操作,我們的服務便就可以通過定義域名配置供外部的服務進行訪問了。而Ingress的建立命令,也和前面所說的一樣:

kubectlapply-fsample-ingress.yaml

有了這部分配置,我們的功能原則上就能夠讓外部訪問了。但在實際應用中我們本地沒有可供測試的環境,本地的Kubernetes環境是通過kindD生成的,其核心是多個Docker Container而不是多臺機器。上述內容在Container內部執行,是使用Docker模擬Kubernetes的功能,因此這也是本文中唯一無法驗證成功的一個功能模組。

完整部署一個活字格應用

通過上節我們一起學習了Pod間的編排控制器的使用,本節中實現了內外互動呼叫,進一步實現服務發現的功能,我們現在就可以再次回到之前提出的問題: 究竟如何成功部署一個活字格應用。

通過介紹整個Kubernetes的基礎使用的流程,我們可以看到一個服務在Kubernetes變成Pod,通過Deployment部署,通過Service服務發現,通過Ingress反向代理的全過程,經過這些模組的協力配合之後,我們的活字格應用終於可以部署在這個Kubernetes叢集中了。

希望這張圖片展示,能夠為大家帶來更加直觀的感覺。

總結

截止到本章,我們已經完整介紹了活字格公有云版做k8s部署的全過程。下一節將會為大家帶來本系列文章的最後一篇——Kubernetes總覽,讓大家對Kubernetes叢集內容部分有一個整體性印象,對一些深層次功能做一個總結。

感興趣的小夥伴不要錯過~我們下篇接著聊。



本文是由葡萄城技術開發團隊釋出,轉載請註明出處:葡萄城官網