溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何理解Kubernets網(wǎng)絡(luò)

發(fā)布時(shí)間:2021-10-12 11:01:42 來(lái)源:億速云 閱讀:126 作者:柒染 欄目:云計(jì)算

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)如何理解Kubernets網(wǎng)絡(luò),文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

不同宿主機(jī)上運(yùn)行的容器并不能通過(guò) IP 相互訪問(wèn),那么 Kubernetes 是如何實(shí)現(xiàn)不同節(jié)點(diǎn)上 Pod 的互通?Pod 有生命周期,它的 IP 會(huì)隨著動(dòng)態(tài)的創(chuàng)建和銷毀而動(dòng)態(tài)變化,Kubernetes 又是怎樣對(duì)外提供穩(wěn)定的服務(wù)?今天就為大家一一解答這些疑問(wèn)。

Docker 網(wǎng)絡(luò)

先來(lái)看一下 Docker 中的網(wǎng)絡(luò)。在啟動(dòng) Docker 服務(wù)后,默認(rèn)會(huì)創(chuàng)建一個(gè) docker0 網(wǎng)橋(其上有一個(gè) docker0 內(nèi)部接口),它在內(nèi)核層連通了其他的物理或虛擬網(wǎng)卡,這就將所有容器和本地主機(jī)都放到同一個(gè)物理網(wǎng)絡(luò)。

Docker 默認(rèn)指定了 docker0 接口 的 IP 地址和子網(wǎng)掩碼,讓主機(jī)和容器之間可以通過(guò)網(wǎng)橋相互通信,它還給出了 MTU(接口允許接收的最大傳輸單元),通常是 1500 Bytes,或宿主主機(jī)網(wǎng)絡(luò)路由上支持的默認(rèn)值,這些值都可以在服務(wù)啟動(dòng)的時(shí)候進(jìn)行配置。

root@ubuntu:/root# ifconfig
...
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
        ether 02:42:d2:00:10:6c  txqueuelen 0  (Ethernet)
...
root@ubuntu:/root# docker inspect busybox
···
"IPAddress": "172.17.0.2",
···

為了實(shí)現(xiàn)上述功能,Docker 主要用到了 linux 的 Bridge 、Network Namespace 、VETH

  • Bridge相當(dāng)于是一個(gè)虛擬網(wǎng)橋,工作在第二層網(wǎng)絡(luò)。也可以為它配置IP,工作在三層網(wǎng)絡(luò)。docker0網(wǎng)關(guān)就是通過(guò)Bridge實(shí)現(xiàn)的。

  • Network Namespace是網(wǎng)絡(luò)命名空間,通過(guò)Network Namespace可以建立一些完全隔離的網(wǎng)絡(luò)棧。比如通過(guò)docker network create xxx就是在建立一個(gè)Network Namespace

  • VETH是虛擬網(wǎng)卡的接口對(duì),可以把兩端分別接在兩個(gè)不同的Network Namespace中,實(shí)現(xiàn)兩個(gè)原本隔離的Network Namespace的通信。

所以總結(jié)起來(lái)就是:Network Namespace做了容器和宿主機(jī)的網(wǎng)絡(luò)隔離,Bridge分別在容器和宿主機(jī)建立一個(gè)網(wǎng)關(guān),然后再用VETH將容器和宿主機(jī)兩個(gè)網(wǎng)絡(luò)空間連接起來(lái)。但這都是在同一個(gè)主機(jī)上的網(wǎng)絡(luò)實(shí)現(xiàn),如果想要在多臺(tái)主機(jī)上進(jìn)行網(wǎng)絡(luò)就得看看下面介紹的 Kubernetes 網(wǎng)絡(luò)。

Kubernetes 網(wǎng)絡(luò)

Kubernetes 為了解決容器的“跨主通信”問(wèn)題,提出了很多解決方案。常見(jiàn)思路有兩種:

  • 直接在宿主機(jī)上建立不同宿主機(jī)上子網(wǎng)的路由規(guī)則;

  • 通過(guò)特殊的網(wǎng)絡(luò)設(shè)備封裝二層數(shù)據(jù)幀,根據(jù)目標(biāo) IP 地址匹配到對(duì)應(yīng)的子網(wǎng)找到對(duì)應(yīng)的宿主機(jī) IP 地址,最后將轉(zhuǎn)發(fā) IP 包,目的宿主機(jī)上同樣的特殊網(wǎng)絡(luò)設(shè)備完成解封并根據(jù)本機(jī)路由表轉(zhuǎn)發(fā)。

Flannel

大家所熟知的 Flannel 項(xiàng)目是 CoreOS 公司推出的容器網(wǎng)絡(luò)解決方案。它本身只是一個(gè)框架,為開(kāi)發(fā)者提供容器網(wǎng)絡(luò)功能的是 Flannel 的后端實(shí)現(xiàn)。目前有如下三種具體實(shí)現(xiàn):

  • UDP

  • VXLAN

  • host-gw

下面的三層網(wǎng)絡(luò)指的是七層網(wǎng)絡(luò)模型中的底部的三層:網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層和物理層。

UDP 模式是最早支持,性能最差,但最容易理解和實(shí)現(xiàn)的容器跨主網(wǎng)絡(luò)方案。Flannel UDP 模式提供的是一個(gè)三層的覆蓋網(wǎng)絡(luò):首先對(duì)發(fā)出端的IP包進(jìn)行 UDP 封裝,然后在接受端進(jìn)行解封拿到原始的IP包,進(jìn)而把這個(gè)包轉(zhuǎn)發(fā)給目標(biāo)容器。它相當(dāng)于在兩個(gè)容器之間打通一條“隧道”,使得兩個(gè)容器可以直接使用 IP 通信,而不關(guān)心容器和宿主機(jī)的分布情況。

如何理解Kubernets網(wǎng)絡(luò)

因?yàn)?Flannel 進(jìn)行 UDP 封裝和解封都是在用戶態(tài)完成,而在 Linux 系統(tǒng)中上下文切換和用戶態(tài)操作的代價(jià)非常大,這就是它性能不好的主要原因。

VXLAN 即 Virtual Extensible LAN(虛擬可擴(kuò)展局域網(wǎng)),是 Linux 內(nèi)核本身就支持的一種網(wǎng)絡(luò)虛擬化技術(shù)。VXLAN 在內(nèi)核態(tài)就完成了上面的封裝和解封工作,通過(guò)與 UDP 模式類似的“隧道”機(jī)制,構(gòu)建出覆蓋網(wǎng)絡(luò)(Overlay Network),使得連接在這個(gè) VXLAN 二層網(wǎng)絡(luò)的“主機(jī)”可以像在局域網(wǎng)自由通信。

如何理解Kubernets網(wǎng)絡(luò)

host-gw 模式的工作原理是將每一個(gè) Flannel 子網(wǎng)的下一跳設(shè)置為該子網(wǎng)對(duì)應(yīng)的宿主機(jī) IP 地址。

也就是說(shuō),這臺(tái)“主機(jī)”(host)會(huì)充當(dāng)這條容器通信路徑里的“網(wǎng)關(guān)”(Getway)。Flannel host-gw 模式必須要求集群宿主機(jī)之間是二層連通的。

如何理解Kubernets網(wǎng)絡(luò)

Calico

Calico 項(xiàng)目提供的網(wǎng)絡(luò)解決方案與 Flannel Host-gw 模式同理。但是不同于 Flannel 通過(guò) Etcd 和宿主機(jī)的 flanneld 來(lái)維護(hù)路由信息得做法,Calio 項(xiàng)目使用BGP(邊界網(wǎng)關(guān)協(xié)議) 來(lái)自動(dòng)的在整個(gè)集群中分發(fā)路由消息。它由三部分組成:

Calico 的 CNI 插件:這是 Calico 與 Kubernetes 對(duì)接的部分。 Felix:它是一個(gè) DaemonSet,負(fù)責(zé)在宿主機(jī)插入路由規(guī)則,以及維護(hù)Calico所需的網(wǎng)絡(luò)設(shè)備等。 BIRD:它是 BGP 的客戶端,負(fù)責(zé)在集群里分發(fā)路由規(guī)則信息。

除了對(duì)路由信息的維護(hù)方式之外,Calico 項(xiàng)目和 Flannel 的 host-gw 另一個(gè)不同是它不會(huì)在宿主機(jī)上創(chuàng)建任何網(wǎng)橋設(shè)備。

如何理解Kubernets網(wǎng)絡(luò)

CNI(容器網(wǎng)絡(luò)接口)

CNI)是CNCF旗下的一個(gè)項(xiàng)目,由一組用于配置Linux容器的網(wǎng)絡(luò)接口的規(guī)范和庫(kù)組成,同時(shí)還包含了一些插件。CNI僅關(guān)心容器創(chuàng)建時(shí)的網(wǎng)絡(luò)分配,和當(dāng)容器被刪除時(shí)釋放網(wǎng)絡(luò)資源。其基本思想為: Kubernetes 在啟動(dòng) Infra 容器之后,就可以直接調(diào)用 CNI 網(wǎng)絡(luò)插件,為這個(gè) Infra 容器的 Network Namespace 配置符合預(yù)期的網(wǎng)絡(luò)棧。

Kubernetes 使用 CNI 接口,維護(hù)一個(gè)單獨(dú)的網(wǎng)橋來(lái)代替 docker0。這個(gè)網(wǎng)橋就叫做 CNI 網(wǎng)橋,它在宿主機(jī)上的默認(rèn)名稱是:cni0。以 Flannel 的 VXLAN 模式為例,在 Kubernetes 環(huán)境里,它的工作方式?jīng)]有變化,只是 docker0 網(wǎng)橋替換成了 CNI 網(wǎng)橋。CNI 網(wǎng)橋只是接管所有 CNI 插件負(fù)責(zé)的,即 Kuberntes 創(chuàng)建的容器(Pod)。

如何理解Kubernets網(wǎng)絡(luò)

Service

Kubernetes 中 Pod 有生命周期,它的 IP 會(huì)隨著動(dòng)態(tài)的創(chuàng)建和銷毀而動(dòng)態(tài)變化,不能穩(wěn)定的提供服務(wù)。Kubernetes Service 定義這樣一種抽象:一個(gè) Pod 的邏輯分組,一種可以訪問(wèn)它們的策略。開(kāi)發(fā)者可以通過(guò)一個(gè) Service 的入口地址訪問(wèn)其背后的一組 Pod。一旦 Service 被創(chuàng)建,Kubernetes 就會(huì)自動(dòng)為它分配一個(gè)可用的 Cluster IP,在 Service 的整個(gè)生命周期中它的 Cluster IP 都不會(huì)發(fā)生改變。這樣就解決了分布式集群的服務(wù)發(fā)現(xiàn)。

一個(gè)典型的 Service 定義如下:

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  ports:
  - nmae: dafault
    protocol: TCP
    port: 8000
    targetPort: 80

在這個(gè) Service 例子中,筆者使用 selector 字段聲明這個(gè) Service 只代理 app=nginx 標(biāo)簽的 pod。這個(gè) Service 的 8000 端口代理 Pod 的 80 端口。

然后定義應(yīng)用 Delpoyment 如下:

apiVersion: v1
kind: Delpoyment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    meatdata:
    lalels:
      app: nginx
    spec:
    containers:
    - name: nginx
      image: nginx
      ports:
      - containers: 80
        protocol: TCP

被 selector 選中的 Pod,就被稱為 Serivce 的 Endpoints,你可以使用 kubectl get ep 查看它們,如下所示:

$ kubectl get endpoints nginx
NAME    ENDPOINTS                                      AGE
nginx   172.20.1.16:80,172.20.2.22:80,172.20.2.23:80   1m

通過(guò)該 Service 的 VIP 10.68.57.93 地址,就可以訪問(wèn)到它所代理的 Pod:

$ kubectl get svc nginx
NAME    TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   10.68.57.93   <none>        80/TCP    1m

$ curl 10.68.57.93
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
......
<h2>Welcome to nginx!</h2>
......
</html>

這個(gè) VIP 地址是 Kubernetes 自動(dòng)為 Service 分配的。訪問(wèn) Service 的 VIP 地址和代理的 80 端口,它就為我們返回了默認(rèn)的 nginx 頁(yè)面,這種方式稱為:Cluster IP 模式的 Service。

集群外訪問(wèn) Service

Servcie 的訪問(wèn)信息在 kubernates 集群外無(wú)效,因?yàn)樗^的 Service 的訪問(wèn)接口,實(shí)際上是每臺(tái)宿主機(jī)上由 kube-proxy 生成的 iptables 規(guī)則,以及 kube-dns 生成的 DNS 記錄。

解決外部訪問(wèn) Kubernetes 集群里創(chuàng)建的 servcie有以下幾種方法:

  • NodePort

  • LoadBalancer

NodePort 方法

下面是 NodePort 的例子:

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  type: NodePort
  ports:
  - name: http
    nodePort: 30080
    port: 8080
    targetPort: 80
    protocol: TCP

在這個(gè) Service 定義中,聲明它的類型為 type=NodePort。此時(shí)在 ports 字段中聲明了 Service 的 8080 端口代理 Pod的80端口。

如果你不顯示聲明 nodePort 字段,Kubernetes 會(huì)為你隨機(jī)分配可用端口來(lái)設(shè)置代理,這個(gè)端口的范圍默認(rèn)為:30000-32767。這里設(shè)置為 30080。

這里就可以如此訪問(wèn)這個(gè) service:

<任何一臺(tái)宿主機(jī) IP 地址>:30080

LoadBalancer

這種方法適用于公有云上的 Kubernetes 服務(wù),通過(guò)指定一個(gè) LoadBalancer 類型的 Service 實(shí)現(xiàn)。

apiVersion: v1
kind: Service
metadata:
  name: example-service
spec:
  ports:
  - port: 8765
    targetPort: 9379
  selector:
    app: example
  type: LoadBalancer

創(chuàng)建 Service 時(shí),你可以選擇自動(dòng)創(chuàng)建云網(wǎng)絡(luò)負(fù)載均衡器。這提供了一個(gè)外部可訪問(wèn)的IP地址,只要您的群集在受支持的云環(huán)境中運(yùn)行,就可以將流量發(fā)送到群集節(jié)點(diǎn)上的正確端口。

Ingress

為代理不同后端 Service 而設(shè)置的路由規(guī)則集合就是 Kubernetes 里的 Ingress。

舉一個(gè)例子,這里有一個(gè)訂閱系統(tǒng),它的域名是:https://wwww.example.com 。其中 http://www.example.com/book 是訂書(shū)系統(tǒng),https://www.example.com/food 是訂餐系統(tǒng)。這兩個(gè)系統(tǒng)分別由 book 和 food 兩個(gè) Deployment 來(lái)提供服務(wù)。

apiVersion: v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  tls:
  - hosts:
    - www.example.com
    secretName: example-secret
  rules:
  - host: www.example.com
    http:
      paths:
      - path: book
        backend:
          serviceName: book-svc
          servicePort: 80
      - path: /food
        backend:
          serviceName: food-svc
          servicePort: 80

這個(gè) yaml 文件值得關(guān)注的 rules 字段,它叫作:IngressRules。

IngressRule 的 Key 就是 host,它必須是一個(gè)標(biāo)準(zhǔn)域名格式的字符串,不能是 IP 地址。

host 字段定義的值就是 Ingress 的入口,也就是說(shuō)當(dāng)用戶訪問(wèn) www.example.com 的時(shí)候,實(shí)際上訪問(wèn)到的是這個(gè) Ingress 對(duì)象。Kubernetes就能根據(jù) IngressRule 進(jìn)行下一步轉(zhuǎn)發(fā),這里定義兩個(gè) path,它們分別對(duì)應(yīng) book 和 food 這個(gè)兩個(gè) Deployment 的 Service。

由此不難看出,Ingress 對(duì)象其實(shí)就是 Kubernetes 項(xiàng)目對(duì)“反向代理”的一種抽象。

上述就是小編為大家分享的如何理解Kubernets網(wǎng)絡(luò)了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI