首頁>技術>

一、原理簡介

名詞解釋

1、網路的名稱空間:Linux在網路棧中引入網路名稱空間,將獨立的網路協議棧隔離到不同的命令空間中,彼此間無法通訊;docker利用這一特性,實現不容器間的網路隔離。

2、Veth裝置對:也叫虛擬網路介面對。Veth裝置對的引入是為了實現在不同網路名稱空間的通訊。

3、Iptables/Netfilter:Netfilter負責在核心中執行各種掛接的規則(過濾、修改、丟棄等),執行在核心 模式中;Iptables模式是在使用者模式下執行的程序,負責協助維護核心中Netfilter的各種規則表;通過二者的配合來實現整個Linux網路協議棧中靈活的資料包處理機制。

4、網橋:網橋是一個二層網路裝置,通過網橋可以將linux支援的不同的埠連線起來,並實現類似交換機那樣的多對多的通訊。

令人頭大的網路模型

Kubernetes對叢集內部的網路進行了重新抽象,以實現整個叢集網路扁平化。我們可以理解網路模型時,可以完全抽離物理節點去理解,我們用圖說話,先有基本印象。

其中,重點講解以下幾個關鍵抽象概念。

Service

Service是Kubernetes為為遮蔽這些後端例項(Pod)的動態變化和對多例項的負載均衡而引入的資源物件。

Service通常與deployment繫結,定義了服務的訪問入口地址,應用(Pod)可以通過這個入口地址訪問其背後的一組由Pod副本組成的叢集例項。

Service與其後端Pod副本叢集之間則是通過Label Selector來實現對映。

Service的型別(Type)決定了Service如何對外提供服務,根據型別不同,服務可以只在Kubernetes cluster中可見,也可以暴露到叢集外部。

Service有三種類型,ClusterIP,NodePort和LoadBalancer。

在測試環境檢視:

$ kubectl get svc --selector app=nginx

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

nginx ClusterIP 172.19.0.166 <none> 80/TCP 1m

$ kubectl describe svc nginx

Name: nginx

Namespace: default

Labels: app=nginx

Annotations: <none>

Selector: app=nginx

Type: ClusterIP

IP: 172.19.0.166

Port: <unset> 80/TCP

TargetPort: 80/TCP

Endpoints: 172.16.2.125:80,172.16.2.229:80

Session Affinity: None

Events: <none>

上述資訊中該svc後端代理了2個Pod例項:172.16.2.125:80,172.16.2.229:80 二個IP

Kubernetes為描述其網路模型的IP物件,抽象出Cluster IP和Pod IP的概念。

PodIP是Kubernetes叢集中每個Pod的IP地址。

它是Docker Engine 根據docker0網橋的IP地址段進行分配的,是一個虛擬的二層網路。

Kubernetes中Pod間能夠彼此直接通訊,Pod裡的容器訪問另外一個Pod裡的容器,是通過Pod IP所在進行通訊。

Cluster IP僅作用於Service,其沒有實體物件所對應,因此Cluster IP無法被ping通。

它的作用是為Service後端的例項提供統一的訪問入口。

Cluster IP和Service一樣由kube-proxy元件維護,其實現方式主要有兩種,iptables和IPVS。

在1.8版本後kubeproxy開始支援IPVS方式。在上例中,SVC的資訊中包含了Cluster IP。

這裡未列出nodeip概念,由於其本身是物理機的網絡卡IP。因此可理解為nodeip就是物理機IP。

三個Port

在Kubernetes中,涉及容器,Pod,Service,叢集各等多個層級的物件間的通訊,為在網路模型中區分各層級的通訊埠,這裡對Port進行了抽象。

Port

該Port非一般意義上的TCP/IP中的Port概念,它是特指Kubernetes中Service的port,是Service間的訪問埠,例如Mysql的Service預設3306埠。它僅對進群內容器提供訪問許可權,而無法從叢集外部通過該埠訪問服務。

nodePort

nodePort為外部機器提供了訪問叢集內服務的方式。比如一個Web應用需要被其他使用者訪問,那麼需要配置type=NodePort,而且配置nodePort=30001,那麼其他機器就可以通過瀏覽器訪問scheme://node:30001訪問到該服務,例如http://node:30001。

targetPort

targetPort是容器的埠(最根本的埠入口),與製作容器時暴露的埠一致(DockerFile中EXPOSE),例如http://docker.io官方的nginx暴露的是80埠。

舉一個例子來看如何配置Service的port:

這裡舉出了一個service的yaml,其部署在abcdocker的namespace中。

這裡配置了nodePort,因此其型別Type就是NodePort,注意大小寫。

若沒有配置nodePort,那這裡需要填寫ClusterIP,即表示只支援叢集內部服務訪問。

叢集內部通訊

單節點通訊

叢集單節點內的通訊,主要包括兩種情況,同一個pod內的多容器間通訊以及同一節點不同pod間的通訊。

通過檢視路由表,也能窺見一二:

1、 Pod內通訊

如下圖所示:

這種情況下,同一個pod內共享網路名稱空間,容器之間通過訪問127.0.0.1:(埠)即可。

圖中的veth*即指veth對的一端(另一端未標註,但實際上是成對出現),該veth對是由Docker Daemon掛載在docker0網橋上,另一端新增到容器所屬的網路名稱空間,圖上顯示是容器中的eth0。

圖中演示了bridge模式下的容器間通訊。docker1向docker2傳送請求,docker1,docker2均與docker0建立了veth對進行通訊。

當請求經過docker0時,由於容器和docker0同屬於一個子網,因此請求經過docker2與docker0的veth*對,轉發到docker2,該過程並未跨節點,因此不經過eth0。

2、Pod間通訊

同節點pod間通訊

由於Pod內共享網路名稱空間(由pause容器建立),所以本質上也是同節點容器間的通訊。

同時,同一Node中Pod的預設路由都是docker0的地址,由於它們關聯在同一個docker0網橋上,地址網段相同,所有它們之間應當是能直接通訊的。

來看看實際上這一過程如何實現。如上圖,Pod1中容器1和容器2共享網路名稱空間,因此對pod外的請求通過pod1和Docker0網橋的veth對(圖中掛在eth0和ethx上)實現。

跨節點通訊

CNI:容器網路介面

CNI 是一種標準,它旨在為容器平臺提供網路的標準化。不同的容器平臺(比如目前的 kubernetes、mesos 和 rkt)能夠通過相同的介面呼叫不同的網路元件。

目前kubernetes支援的CNI元件種類很多,例如:bridge calico calico-ipam dhcp flannel host-local ipvlan loopback macvlan portmap ptp sample tuning vlan。在docker中,主流的跨主機通訊方案主要有一下幾種:

1)基於隧道的overlay網路:按隧道型別來說,不同的公司或者組織有不同的實現方案。docker原生的overlay網路就是基於vxlan隧道實現的。ovn則需要通過geneve或者stt隧道來實現的。flannel最新版本也開始預設基於vxlan實現overlay網路。

2)基於包封裝的overlay網路:基於UDP封裝等資料包包裝方式,在docker叢集上實現跨主機網路。典型實現方案有weave、flannel的早期版本。

3)基於三層實現SDN網路:基於三層協議和路由,直接在三層上實現跨主機網路,並且通過iptables實現網路的安全隔離。典型的方案為Project Calico。同時對不支援三層路由的環境,Project Calico還提供了基於IPIP封裝的跨主機網路實現

通訊方式

叢集內跨節點通訊涉及到不同的子網間通訊,僅靠docker0無法實現,這裡需要藉助CNI網路外掛來實現。圖中展示了使用flannel實現跨節點通訊的方式。

簡單說來,flannel的使用者態程序flanneld會為每個node節點建立一個flannel.1的網橋,根據etcd或apiserver的全域性統一的叢集資訊為每個node分配全域性唯一的網段,避免地址衝突。同時會為docker0和flannel.1建立veth對,docker0將報文丟給flannel.1,。

Flanneld維護了一份全域性node的網路表,通過flannel.1接收到請求後,根據node表,將請求二次封裝為UDP包,扔給eth0,由eth0出口進入物理網路傳送給目的node。

在另一端以相反的流程。Flanneld解包併發往docker0,進而發往目的Pod中的容器。

外部訪問叢集

從叢集外訪問叢集有多種方式,比如loadbalancer,Ingress,nodeport,nodeport和loadbalancer是service的兩個基本型別,是將service直接對外暴露的方式,ingress則是提供了七層負載均衡,其基本原理將外部流量轉發到內部的service,再轉發到後端endpoints,在平時的使用中,我們可以依據具體的業務需求選用不同的方式。這裡主要介紹nodeport和ingress方式。

Nodeport

通過將Service的型別設定為NodePort,就可以在Cluster中的主機上通過一個指定埠暴露服務。注意通過Cluster中每臺主機上的該指定埠都可以訪問到該服務,傳送到該主機埠的請求會被kubernetes路由到提供服務的Pod上。採用這種服務型別,可以在kubernetes cluster網路外通過主機IP:埠的方式訪問到服務。

這裡給出一個influxdb的例子,我們也可以針對這個模板去修改成其他的型別:

Ingress

Ingress是推薦在生產環境使用的方式,它起到了七層負載均衡器和Http方向代理的作用,可以根據不同的url把入口流量分發到不同的後端Service。外部客戶端只看到http://foo.bar.com這個伺服器,遮蔽了內部多個Service的實現方式。採用這種方式,簡化了客戶端的訪問,並增加了後端實現和部署的靈活性,可以在不影響客戶端的情況下對後端的服務部署進行調整。

其部署的yaml可以參考如下模板:

這裡我們定義了一個ingress模板,定義通過http://test.name.com來訪問服務,在虛擬主機http://test.name.com下面定義了兩個Path,其中/test被分發到後端服務s1,/name被分發到後端服務s2。

叢集中可以定義多個ingress,來完成不同服務的轉發,這裡需要一個ingress controller來管理叢集中的Ingress規則。Ingress Contronler 通過與 Kubernetes API 互動,動態的去感知叢集中 Ingress 規則變化,然後讀取它,按照自定義的規則,規則就是寫明了哪個域名對應哪個service,生成一段 Nginx 配置,再寫到 Nginx-ingress-control的 Pod 裡,這個 Ingress Contronler 的pod裡面執行著一個nginx服務,控制器會把生成的nginx配置寫入/etc/nginx.conf檔案中,然後 reload使用配置生效。

Kubernetes提供的Ingress Controller模板如下:

二、環境搭建及簡單使用

1、先安裝docker

配置阿里雲映象地址

如何獲取該地址?

訪問

https://cr.console.aliyun.com/undefined/instances/mirrors?accounttraceid=0de4534ad7f14efa9280e1a74f290c96xkqu

2、開啟k8s服務

第一次開啟需要下載k8s相關庫 非常慢 這裡通過手動下載相關庫的方式完成

a、下載k8s-for-docker-desktop.git

git clone https://gitee.com/poineer/k8s-for-docker-desktop.git -b v1.14.7

注意這裡有一個版本號v1.14.7

為什麼是v1.14.7?

是因為

下載的k8s-for-docker-desktop一定要和dokcer支援的k8s版本一致

b、執行./load_images.sh

等待下載完依賴

c、下載完了之後

k8s服務即可啟動成功

3、簡單使用

a、查詢所有的空間下的Pod

kubectl get pod --all-namespaces

b、查詢指定命令空間下的Pods

kubectl get pods --namespace kube-system

c、查詢某一個Pod的日誌

kubectl --namespace kube-system logs kubernetes-dashboard-855f8c968f-g7c67

檢視pob

kubectl describe pods kubernetes-dashboard-855f8c968f-gjwjp -n kube-system

檢視service

kubectl describe svc/kubernetes-dashboard -n kube-system

d、檢視叢集

kubectl config get-contexts

切換叢集

kubectl config use-context docker-for-desktop

e、驗證叢集狀態

kubectl cluster-infokubectl get nodeskubectl describe node

4、安裝 Kubernetes Dashboard

a、下載git程式碼 為了獲取 kubernetes-dashboard.yaml

https://gitee.com/kfzly/kbdashboard.git

b、將image後面修改成阿里源

registry.cn-shanghai.aliyuncs.com/kubeimage/kubernetes-dashboard-amd64:v1.8.3

c、通過檔名或標準輸入流(stdin)對資源進行配置

kubectl apply -f kubernetes-dashboard.yaml

根據配置檔案建立資源

kubectl create -f kubernetes-dashboard.yaml

kubectl delete -f kubernetes-dashboard.yaml啟動dashboardkubectl proxy

or

kubectl proxy --address='0.0.0.0' --accept-hosts='^*$' --port=8009

檢視啟動狀態

kubectl -n kube-system get svc

kubectl -n kube-system get service kubernetes-dashboard

獲取token

kubectl -n kube-system describe $(kubectl -n kube-system get secret -n kube-system -o name | grep namespace) | grep token

訪問 http://127.0.0.1:32666/

後續將推出:

1、搭建本地的dokcer 資源庫

2、dokcer映象備份

參考文章: https://zhuanlan.zhihu.com/p/81667781

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Python學習第二天