摘要:慶幸,引入了這個(gè)抽象的概念。會虛擬出一個(gè),并在它銷毀之前保持該地址保持不變。通過對它的訪問,以代理的方式負(fù)載到對應(yīng)的上,同時(shí)生命周期的變換,也會及時(shí)反應(yīng)在代理上。該與同名,它所暴露的地址信息正是對應(yīng)的地址。由此猜測是維護(hù)了與的映射關(guān)系。
帶著問題學(xué) Kubernetes 抽象對象 Service
摘要:本文屬于原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請保留出處:https://github.com/jasonGeng88/blog
文章一:帶著問題學(xué) Kubernetes 架構(gòu)
文章二:帶著問題學(xué) Kubernetes 基本單元 Pod
當(dāng)前環(huán)境Mac OS 10.11.x
kubectl == v1.6.4
minikube == v0.19.1
docker == 1.11.1
知識點(diǎn)Service 的 Selector 與 Label 匹配機(jī)制
Service 與 Pods 的地址映射關(guān)系
kube-proxy 的 iptables 代理機(jī)制
Service 的服務(wù)發(fā)現(xiàn)機(jī)制
Service 的服務(wù)暴露方式
前言上一篇講述了 Pod 的相關(guān)內(nèi)容,了解了 Pod 的定義、生命周期以及通信機(jī)制等。正如上文說的,Pod 是存在生命周期的,它的崩潰、更新都是以創(chuàng)建新 Pod 替換原有的 Pod 的方式進(jìn)行的,所以通過固定 Pod 地址的訪問變得不太可行。我們需要通過一種上層調(diào)用的方式,來解決底層 Pod 的動態(tài)變化的場景。
慶幸,K8S 引入了 Service 這個(gè)抽象的概念。Service 會創(chuàng)建一個(gè)虛擬的服務(wù),由它來整合集群內(nèi)的 Pod。Service 會虛擬出一個(gè) VIP,并在它銷毀之前保持該 VIP 地址保持不變。通過對它的訪問,以代理的方式負(fù)載到對應(yīng)的 Pod 上,同時(shí) Pod 生命周期的變換,也會及時(shí)反應(yīng)在代理上。
下面我們幾種常見的場景,來具體看看 Service 是如何工作的。
環(huán)境準(zhǔn)備 演示鏡像鏡像名:jasonn/php-echoserver
作用:打印當(dāng)前容器的 IP
K8S Pod 創(chuàng)建文件名:deploy-echoserver.yml (這里以 Deployment 的方式來創(chuàng)建與管理 Pod)
文件內(nèi)容:
apiVersion: apps/v1beta1 kind: Deployment metadata: # Deployment 實(shí)例名稱 name: echoserver spec: # 設(shè)置 Pod 個(gè)數(shù) replicas: 2 template: metadata: # 設(shè)置 Pod 標(biāo)簽 labels: app: echoserver spec: # 運(yùn)行 docker 鏡像 containers: - name: echoserver image: jasonn/php-echoserver
啟動命令:
kubectl create -f deploy-echoserver.yml
至此,準(zhǔn)備工作全部完成。短暫的等待后,Pod 創(chuàng)建成功,并且也由 deployment 管理著。
查看 deployment 啟動情況:
對 Pod 的訪問情況如下(通過kubectl describe pods獲取 Pod 的 IP 地址):
問題 場景1:現(xiàn)在 K8S 上運(yùn)行著2個(gè) Pod。我們希望通過上述所說的 Service 來整合這兩個(gè) Pod 的訪問,完成對它們的統(tǒng)一訪問,而不用向具體的 Pod 發(fā)出請求。 Q1: Service 如何對 Pod 進(jìn)行整合這里所說的 Pod 默認(rèn)都是帶有標(biāo)簽(label)的,我們之前創(chuàng)建的兩個(gè) Pod 所賦予的標(biāo)簽是 app: echoserver,所以我們在創(chuàng)建 Service 時(shí),就要通過選擇器(selector)來獲取符合條件的 Pod 進(jìn)行整合。
Service 創(chuàng)建腳本內(nèi)容如下(service-echoserver.yml):
apiVersion: v1 kind: Service metadata: # Service 實(shí)例名稱 name: svc-echoserver spec: ports: - protocol: TCP # Service 端口地址 port: 8080 # Pod 端口地址 targetPort: 80 selector: # 匹配符合標(biāo)簽條件的 Pod app: echoserver
創(chuàng)建 Service 命令:
kubectl create -f service-echoserver.yml
由此,我們創(chuàng)建好了一個(gè) Service,同時(shí)也生成了一個(gè)對應(yīng)的 VIP。
查看 Serivce 創(chuàng)建情況:
下面,我們來驗(yàn)證下是否如之前所說,對 VIP 的訪問能訪問到 Pod 的內(nèi)容。
我們發(fā)現(xiàn)不僅能成功訪問,而且還提供了負(fù)載均衡的功能。后面會講負(fù)載是怎么實(shí)現(xiàn)的
PS: 標(biāo)簽篩選查找范圍僅在同個(gè)命名空間(namespace)內(nèi)。
這里引出了另一個(gè)概念 Endpoints。我們先來看看它的一個(gè)具體情況。
發(fā)現(xiàn)在 Service 創(chuàng)建的同時(shí),還生成了一個(gè) Endpoints。 該 Endpoints 與 Service 同名,它所暴露的地址信息正是對應(yīng) Pod 的地址。由此猜測是 Endpoints 維護(hù)了 Service 與 Pod 的映射關(guān)系。
為了驗(yàn)證我們的猜測,我們手動刪除 Endpoints,發(fā)現(xiàn)之前能成功訪問到 Pod 的 VIP,現(xiàn)在已經(jīng)已經(jīng)訪問不到了。
我們在手動把 Endpoints 創(chuàng)建回來,創(chuàng)建腳本如下(endpoint-echoserver.yml):
apiVersion: v1 kind: Endpoints metadata: # Endpoints 實(shí)例的名稱 name: svc-echoserver subsets: - addresses: - ip: 172.17.0.5 - ip: 172.17.0.6 ports: - port: 80
創(chuàng)建命令:
kubectl create -f endpoint-echoserver.yml
注意:Endpoints 與 Service 的綁定關(guān)系通過名稱來關(guān)聯(lián)的,所以這兩者的名稱(name)一定要一致。
如果創(chuàng)建失敗,出現(xiàn)的錯(cuò)誤信息是“...endpoints "svc-echoserver" already exists”,說明 Service 已經(jīng)更新了 Endpoints。這里就說到了 Service 會定期去檢查 Pod 的狀態(tài),并且將結(jié)果更新到 Endpoints 上。
VIP 再次訪問時(shí)又能成功訪問到,如圖:
現(xiàn)在我們已經(jīng)能輕松的解決場景2的問題了,在創(chuàng)建 Service 時(shí),只要不設(shè)置 Selector 屬性,那么將不會自動創(chuàng)建 Endpoints,這是我們可以根據(jù)需求手動的創(chuàng)建指定地址(address)的 Endpoints,來解決標(biāo)簽無法實(shí)現(xiàn)的整合。
我們現(xiàn)在要做的呢,是將 VIP 請求給轉(zhuǎn)發(fā)到對應(yīng)的 Pod 上。而實(shí)現(xiàn)此的正是 iptables。
了解 iptables 的同學(xué)都知道四表五鏈的概念,而做端口地址轉(zhuǎn)發(fā)的呢,主要是在 nat 表中實(shí)現(xiàn)。我們下面看一下一個(gè) VIP 請求在 nat 表中是如何一步步被轉(zhuǎn)發(fā)到 Pod 上的。
根據(jù) iptables 的機(jī)制,請求是先到 nat 表的 PREROUTING 鏈(chain)上的,它的規(guī)則如下:
從圖中發(fā)現(xiàn),請求首先經(jīng)過 KUBE-SERVICE 鏈,其次再到 DOCKER 鏈上的。
我們看一下 KUBE-SERVICE 的情況:
我們發(fā)現(xiàn) KUBE-SERVICE 中包含了一系列 Service 的規(guī)則。根據(jù)我們請求的 VIP 的目的地址,對應(yīng)到了下一個(gè)名叫 KUBE-SVC-PRQ3AXYQLQGIVVIU 的 Service 鏈上。
KUBE-SVC-PRQ3AXYQLQGIVVIU 規(guī)則如下:
從規(guī)則的名字上可以看出,該條 Service 鏈上記錄的是2個(gè) Endpoints 鏈,具體的選擇是通過 50% 的隨機(jī)性的進(jìn)行決定(這也是它的一個(gè)負(fù)載規(guī)則)。
我們來看第一個(gè)名叫 KUBE-SEP-JSFY3ZFM2EVD64VQ 的 Endpoints 鏈的情況:
從圖中,我們已經(jīng)很清晰的看到了它轉(zhuǎn)發(fā)到 Pod 的具體規(guī)則。
下面以一張簡單的流程圖,看一下請求的轉(zhuǎn)發(fā)情況:
關(guān)于 DOCKER 鏈的跟蹤,方法是差不多的,請求 從 nat 表結(jié)束后,在到 filter 表中,這里就不加以說明了。
而這些規(guī)則的實(shí)現(xiàn)正是由 Service、Endpoints 來完成的。我們在創(chuàng)建、更新、以及其自身的檢測機(jī)制,都會對這些規(guī)則進(jìn)行更新。
對于服務(wù)與服務(wù)間的調(diào)用,實(shí)際上就是 Pod 對 Servie 的調(diào)用。而 Pod 是如何發(fā)現(xiàn) Service 的,這里可選擇的方式有2種。
我們通過啟動一個(gè)名為 busybox 的 Pod 來觀察這兩種方式:
kubectl run -i --tty busybox --image=busybox --restart=Never -- sh
環(huán)境變量:
在 Pod 中,集群中的 Service 會以環(huán)境變量的方式賦值在容器中,我們可以通過 {SERVICE_NAME}_SERVICE_HOST 和 {SERVICE_NAME}_SERVICE_PORT 進(jìn)行獲取(對于有多個(gè) Port 的,可以通過帶指定 PORT 名稱的變量獲得。)。
busybox 中 環(huán)境變量如下:
查看訪問情況:
dns 解析:
第二種方式是通過 kube-dns 對 Service 進(jìn)行域名解析,同樣能達(dá)到服務(wù)發(fā)現(xiàn)的目的。
查看 DNS 域名解析配置:
通過 nslookup 查詢 dns 記錄:
查看訪問結(jié)果:
在 Service 的配置文件中,屬性spec.type就是用來設(shè)置服務(wù)暴露的方式,它提供的三種方式如下:
ClusterIP: 提供一個(gè)集群內(nèi)部的虛擬IP以供Pod訪問(默認(rèn)類型,我們上述使用的正是這種方式)。
NodePort: 在每個(gè)Node上打開一個(gè)端口以供外部訪問。
LoadBalancer: 通過外部的負(fù)載均衡器來訪問(一般需要云提供商提供 LB 支持)。
我們這里簡單起見,還是通過 NodePort 方式進(jìn)行。
修改 Service 配置文件,并重新啟動:
apiVersion: v1 kind: Service metadata: # Service 實(shí)例名稱 name: svc-echoserver spec: ports: - protocol: TCP # Service 端口地址 port: 8080 # Pod 端口地址 targetPort: 80 selector: # 匹配符合標(biāo)簽條件的 Pod app: echoserver type: NodePort
注意:這里如果要以kubecrl replace -f service-echoserver.yml方式進(jìn)行平滑更新,配置中需添加spec.clusterIP屬性,值為當(dāng)前 Service 的 VIP,否則更新會失敗。這也符合了一開始說的 Service 在它終止之前,VIP 是不會改變的。
查看 Service 更新情況:
外部訪問(該 Node 地址是:192.168.64.6):
總結(jié)文本從 Service 的標(biāo)簽與選擇器開始,講了 Service 整合 Pod 的過程,引出了 Service, Endpoints, Pods 三者的關(guān)系情況。隨后又通過 iptables 詳細(xì)展開了 kube-proxy 的代理機(jī)制。最后,以 Service 的集群內(nèi)與集群外的訪問設(shè)置,講述了 Service 的服務(wù)發(fā)現(xiàn)與服務(wù)暴露機(jī)制。
關(guān)于 Service 的有遺漏重要的知識點(diǎn),或者有講的不對的地方,也歡迎提出和指正!最后,希望本篇對你學(xué)習(xí) K8S 有所幫助~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/26991.html
摘要:慶幸,引入了這個(gè)抽象的概念。會虛擬出一個(gè),并在它銷毀之前保持該地址保持不變。通過對它的訪問,以代理的方式負(fù)載到對應(yīng)的上,同時(shí)生命周期的變換,也會及時(shí)反應(yīng)在代理上。該與同名,它所暴露的地址信息正是對應(yīng)的地址。由此猜測是維護(hù)了與的映射關(guān)系。 帶著問題學(xué) Kubernetes 抽象對象 Service 摘要:本文屬于原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請保留出處:https://github.com/jas...
摘要:又因?yàn)槭枪雀璩銎返模蕾嚵撕芏喙雀枳约旱溺R像,所以對于國內(nèi)的同學(xué)環(huán)境搭建的難度又增加了一層。 帶著問題學(xué) Kubernetes 架構(gòu) 摘要:本文屬于原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請保留出處:https://github.com/jasonGeng88/blog 打開這篇文章的同學(xué),想必對 docker 都不會陌生。docker 是一種虛擬容器技術(shù),它上手比較簡單,只需在宿主機(jī)上起一個(gè) docke...
摘要:又因?yàn)槭枪雀璩銎返模蕾嚵撕芏喙雀枳约旱溺R像,所以對于國內(nèi)的同學(xué)環(huán)境搭建的難度又增加了一層。 帶著問題學(xué) Kubernetes 架構(gòu) 摘要:本文屬于原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請保留出處:https://github.com/jasonGeng88/blog 打開這篇文章的同學(xué),想必對 docker 都不會陌生。docker 是一種虛擬容器技術(shù),它上手比較簡單,只需在宿主機(jī)上起一個(gè) docke...
摘要:后面會涉及以配置文件進(jìn)行部署。的調(diào)度完成,被分配到指定上。這是的一種最終狀態(tài)。圖相較而言,除了提供的基本功能,還支持聲明式的更新和回滾。共享數(shù)據(jù)存儲的問題主要分為數(shù)據(jù)臨時(shí)存儲與持久性存儲。 帶著問題學(xué) Kubernetes 基本單元 Pod 摘要:本文屬于原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請保留出處:https://github.com/jasonGeng88/blog 文章一:帶著問題學(xué) Kube...
摘要:后面會涉及以配置文件進(jìn)行部署。的調(diào)度完成,被分配到指定上。這是的一種最終狀態(tài)。圖相較而言,除了提供的基本功能,還支持聲明式的更新和回滾。共享數(shù)據(jù)存儲的問題主要分為數(shù)據(jù)臨時(shí)存儲與持久性存儲。 帶著問題學(xué) Kubernetes 基本單元 Pod 摘要:本文屬于原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請保留出處:https://github.com/jasonGeng88/blog 文章一:帶著問題學(xué) Kube...
閱讀 1923·2021-10-11 10:59
閱讀 1032·2021-09-07 09:59
閱讀 2226·2021-08-27 16:17
閱讀 2783·2019-08-30 15:54
閱讀 2274·2019-08-30 12:58
閱讀 1773·2019-08-30 12:53
閱讀 1465·2019-08-28 18:13
閱讀 733·2019-08-26 13:35