基於Neutron的Kubernetes SDN實踐經驗之談

來源:互聯網
上載者:User

標籤:開發   abc   資源   loading   多個   route   rgs   bin   基本   

首先,向大家科普下Kubernetes所選擇的CNI網路介面,簡單介紹下網路實現的背景。

 

CNI即Container Network Interface,是一套容器網路的定義規範,包括方法規範、參數規範、響應規範等等。CNI只要求在容器建立時為容器分配網路資源、刪除容器時釋放網路資源。CNI與調用者之間的整個互動過程如所示:

 

 

CNI實現與外界的互動都通過進程參數和環境變數傳遞,也只要求輸出結果符合CNI規範即可,與實現語言也沒什麼特殊要求。比如Calico早期版本就使用Python實現了CNI規範,為Kubernetes提供了網路實現。常見的環境變數設定如下:

 

  • CNI_COMMAND:調用指定CNI動作,ADD表示增加網卡,DEL表示釋放網卡

     

  • CNI_CONTAINERID:容器ID

     

  • CNI_NETNS:容器網路命名空間檔案位置

     

  • CNI_ARGS:額外傳遞的參數

     

  • CNI_IFNAME:設定的容器網卡名稱,如eth0

 

正因如此,CNI規範實現起來非常容易擴充,除了CNI內建的Bridge、Macvlan等基本實現以外,還有大量的第三方實現可供選擇,包括Calico、Romana、Flannel等常用實現。同時CNI支援多種容器運行時,包括Docker、rkt、Mesos、Hyper等容器引擎都可以使用。這也是Kubernetes選擇使用CNI的一大重要原因。

 

相對的,Docker提出的CNM(Cotainer Network Model)模型實現就比較複雜,但更為完善,比較接近傳統的網路概念。如所示:

 

 

Sandbox就是容器的網路命名空間,Endpoint為容器串連到網路中的一張網卡,而網路則是一組相互連信的Endpoint的集合,比較接近Neutron中的網路定義。

 

在CNM中,docker engine通過HTTP REST API調用網路實現,為容器配置網路。這些API介面涵蓋網路管理、容器管理、建立endpoint等十幾個介面。同時CNM模型還隱含在docker自身附帶的service機制、dns機制等附加約束,因此可以在一定程度上說,CNM模型只是專為docker容器實現的,對別的容器運行時並不友好。

 

由於上面這些技術上的原因以及一些商業上的原因,Kubernetes最終選擇了CNI作為自己的網路介面。

 

當然,Kubernetes也提供一些取巧的方法,將CNI介面轉化為對CNM模型的調用,從而實現兩種模型的通用。例如to_docker,這個指令碼就將Kubernetes對CNI的調用轉換為Docker CNM網路的對應操作,從而實現CNI到CNM的轉換。

 

接下來,給大家介紹下Kubernetes中網路概念和通訊原理。

 

在Kubernetes的網路模型中,約定了三個基本約束:

 

  1. 所有容器之間都可以無須SNAT即可相互直接以IP通訊。

     

  2. 所有主機與容器之間都可以無須SNAT即可相互直接以IP通訊。

     

  3. 容器看到的自身IP與其他容器看到的容器IP相同。

 

在滿足約束的基礎上,Kubernetes不關心具體的網路通訊原理,只以三個約束為既定事實,在此基礎上,根據Kubernetes自身邏輯處理網路通訊,從而避免Kubernetes功能糾結在紛繁複雜的網路實現中。

 

而在網路概念上,Kubernetes中有兩種核心IP:

 

  • POD IP:有CNI實現提供,Kubernetes不管這個IP是否可達,只負責使用這個IP實現配置iptables、做健全狀態檢查等功能。預設情況下,這個IP在Kubernetes叢集範圍內都是可達的,並且可以進行ping等操作。

     

  • cluster IP:即服務IP,這個IP在Kubernetes中只是用於實現服務互動通訊,本質上只是iptables上的幾條DNAT規則。預設情況下,這個IP上只能提供服務連接埠的訪問,且不可ping。

 

以叢集的DNS服務為例,相關的核心iptables如所示:

 

 

這些iptables都是由kube-proxy產生的,而且kube-proxy並不實際負責進行轉寄,因此即使kube-proxy服務異常,已經產生的iptables依然可以使流量能夠正確的在服務IP和POD IP之間流轉。其網路流量路徑可以參考:

 

 

當訪問DNS服務的連接埠10.254.0.3時,kube-proxy產生的iptables DNAT規則,將流量轉寄到後端POD IP及對應連接埠上,將流量按後端POD的IP個數實行隨機均等分配。

 

而kube-proxy可以從kube-apiserver擷取服務和POD的狀態更新,隨時根據其狀態更新iptables,從而實現服務的高可用與動態擴充。

 

在基礎的IP通訊機制上,Kubernetes還通過Network Policy和Ingress提高網路安全性和響應效能。

 

Network Policy提供了網路隔離能力,它基於SIG-Network group演化而來,Kubernetes只提供內建的labelSelector和label以及Network Policy API定義,本身並不負責實現如何隔離。在Kubernetes使用的CNI網路實現中,目前只有Calico、Romana、Contiv等少少幾個實現了Network Policy整合。一個典型的Network Policy定義如下所示:

 

apiVersion: extensions/v1beta1

kind: NetworkPolicy

metadata:

name: test-network-policy

namespace: default

spec:

podSelector:

matchLabels:

role: db

ingress:

- from:

- podSelector:

   matchLabels:

    role: frontend

ports:

- protocol: tcp

  port: 6379

 

它指定約束,具有role:db標籤的POD只能被具有role:frontend標籤的POD訪問,除此之外拒絕所有流量。從功能上來講,Network Policy可以等價於Neutron的安全性群組。

 

Ingress是負責對外提供服務的,通過Nginx對外提供一個單獨介面,實現叢集中的所有服務的對外提供,從而取代使用NodePort暴露每個服務的現有實現。目前,Kubernetes的Ingress提供了Nginx和GCE兩種實現,感興趣的同學可以直接參考官文檔,https://github.com/kubernetes/ingress/tree/master/controllers。

 

Kubernetes社區中,比較常見的幾種網路實現主要是以下兩種:

 

  1. 基於Overlay網路:以Flannel、Weave為代表。Flannel是CoreOS為Kubernetes專門定製實現的Overlay網路方案,也是Kubernetes預設的網路實現。它基於VXLAN或者UDP整個叢集的Overlay網路,從而實現容器在叢集上的通訊,滿足Kubernetes網路模型的三大基本約束。由於在通訊過程中存在資料包的封包解包等額外損耗,效能較差,但已經基本滿足使用。

     

  2. 以L3路由為基礎實現網路:以Calico、Romana為代表。其中,Calico是廣泛流傳的效能最好的Kubernetes網路實現,基於純三層的路由實現網路通訊,結合iptables實現的安全控制,可以滿足大多數雲的效能需求。但是由於它要求主機上必須開啟BGP形成路由拓撲,在一些資料中心上可能不會被允許。同時,Calico還比較早地支援了Network Policy,並且可以將Calico自身的資料直接託管在Kubernetes中,從而實現與Kubernetes的深度整合。

 

從上面這些網路實現來看,目前Kubernetes的網路實現都還談不上是比較成熟的SDN,因此我們公司在考察Kubernetes後,決定基於Neutron,為Kubernetes提供一個可用的SDN實現,這就是Skynet項目的由來。

 

下面我來跟大家分享下,Skynet在實踐過程中的一些經驗。

 

在實踐中,首先要解決的就是Kubernetes中的網路概念,怎麼翻譯到Neutron中,才能比較合適地實現功能。

 

在第一個版本中,Kubernetes網路中概念翻譯對應如下表所示:

 

  • POD ----> 虛擬機器

     

  • Service -------> loadbalancer

     

  • Endpoints -------> pool

     

  • Service後端POD ----> member

 

但是,由於Kubernetes中支援同一服務上設定多個服務連接埠,而Neutron的每個Load Balancer僅支援一個對外連接埠。好在,去年OpenStack的Mitaka版本後,Neutron LBaaS V2正式發布,因此有了第二個版本的概念翻譯。

 

  • POD ----> 虛擬機器

     

  • Service -----> lbaasv2 loadbalancer

     

  • Service port ----->lbaasv2 listener

     

  • Endpoints -----> lbaasv2 pool

     

  • Service後端POD ------>lbaasv2 member

     

  • POD livenessProbe ----->health monitor

 

LBaaS V2的基本術語圖解如下所示:

 

 

  • Load Balancer:負載平衡器,對應一個HAProxy進程,佔據一個子網IP。可以邏輯上映射為Kubernetes中的Service。

     

  • Listener:監聽器,表示負載平衡器本身提供的一個前端監聽連接埠。對應service定義中的ports中port。

     

  • pool:監聽器後端的成員集合記錄。

     

  • member:監聽器後端的成員。對應service使用的Endpoints的addresses列表,每個地址可以對應service聲明中的targetPort的映射。

     

  • health monitor:pool中的成員健全狀態檢查器,類似Kubernetes中的livenessProbe,目前不映射。

 

就資源數量的映射來說:Kubernetes的一個service,對應一個Load Balancer。service中的每個port對應監聽這個Load Balancer的一個Listener。每個Listener後端都對接一個pool包含其後端資源。而Kubernetes中的每個Service都有一個對應的Endpoints來包含其後端POD。Endpoints中的每個IP+Service聲明port的targetPort就對應pool中的一個member。

 

初步完成了概念的映射後,我們簡單介紹下開發中的思路。

 

在整體結構上,Skynet居於Kubernetes和Neutron之間,實現了CNI規範,基於Neutron為容器配置網路。service-watcher負責監聽Kubernetes的資源,對服務等概念翻譯為Neutron實現,從而實現完整的網路功能。如下所示:

 

 

kubelet是建立POD的直接操作者,在為POD設定網路時,通過CNI介面規範,調用Skynet實現。Skynet通過調用Neutron為容器分配IP,並通過在POD容器網路命令空間中操作,實現IP、路由等通訊規則的設定。

 

而Neutron原生的DHCP、LBaaS v2等機制可以基本保持不變。從而實現完整的整合,可以使Kubernetes叢集獲得完整的Neutron SDN功能。而當容器內需要進行DNS時,則可以通過Neutron內建的DHCP Agent負責實現解析,在叢集網路中正常工作。

 

如前文所述,Skynet實現了CNI規範,kubelet與Skynet之間的互動過程如下所示:

 

 

簡要介紹下每個步驟:

 

kubelet通過CNI機制調用skynet,主要傳遞的參數如下:

 

  • CNI_COMMAND:調用指定CNI動作,ADD表示增加網卡,DEL表示釋放網卡

     

  • CNI_CONTAINERID:容器ID

     

  • CNI_NETNS:容器網路命名空間檔案位置

     

  • CNI_ARGS:額外傳遞的參數

     

  • CNI_IFNAME:設定的容器網卡名稱,如eth0

 

執行ADD操作時,Skynet根據傳入的參數和POD的配置,通過neutron-server為POD建立port。

 

執行ADD操作時,Skynet根據port和網路設定,為容器建立網路裝置,並掛載到容器命名空間中。

 

neutron-linuxbridge-agent,根據容器的網路和安全性群組規則產生iptables。從而利用Neutron原生的安全性群組功能,同時也可以直接利用Neutron的一整套SDN實現,包括vRouter、FWaaS、VPNaaS等服務。

 

service-watcher將Kubernetes服務對應為Neutron LBaaS v2實現後,以VLAN網路為例,POD與服務之間的流量通訊過程如:

 

 

當叢集內容器訪問服務時,Kubernetes預設都是通過服務名稱訪問,服務名通過Neutron的DHCP機制,可以由每個網路的Dnsmasq進程負責解析,獲得service對應負載平衡的IP地址後,即可用於網路通訊,由物理交換器負責流量的中轉。

 

在實際實現中,以Kubernetes中一個服務的定義映射到Neutron的loadbalancer為例示範下。

 

例如對下面的service實現:

 

kind: Service

apiVersion: v1

metadata:

name: neutron-service

namespace: default

labels:

app: neutron-service

annotations:

skynet/subnet_id: a980172e-638d-474a-89a2-52b967803d6c

spec:

ports:

- name: port1

protocol: TCP

port: 8888

targetPort: 8000

- name: port2

protocol: TCP

port: 9999

targetPort: 9000

selector:

app: neutron-service

type: NodePort

 

kind: Endpoints

apiVersion: v1

metadata:

name: neutron-service

namespace: default

labels:

app: neutron-service

subsets:

- addresses:

- ip: 192.168.119.187

targetRef:

 kind: Pod

 namespace: default

 name: neutron-service-puds0

 uid: eede8e24-85f5-11e6-ab34-000c29fad731

 resourceVersion: ‘2381789‘

- ip: 192.168.119.188

targetRef:

 kind: Pod

 namespace: default

 name: neutron-service-u9nnw

 uid: eede9b70-85f5-11e6-ab34-000c29fad731

 resourceVersion: ‘2381787‘

ports:

- name: port1

port: 8000

protocol: TCP

- name: port2

port: 9000

protocol: TCP

 

POD和Service通過特定註解來指定使用的Neutron網路、IP等配置,與Kubernetes盡量解耦。

 

上面的Service映射成Load Balancer後,其定義如下所示:

 

{

"statuses": {

"loadbalancer": {

 "name": "neutron-service",

 "provisioning_status": "ACTIVE",

 "listeners": [

   {

     "name": "neutron-service-8888",

     "provisioning_status": "ACTIVE",

     "pools": [

       {

         "name": "neutron-service-8888",

         "provisioning_status": "ACTIVE",

         "healthmonitor": {},

         "members": [

           {

             "name": "",

             "provisioning_status": "ACTIVE",

             "address": "192.168.119.188",

             "protocol_port": 8000,

             "id": "461a0856-5c97-417e-94b4-c3486d8e2160",

             "operating_status": "ONLINE"

           },

           {

             "name": "",

             "provisioning_status": "ACTIVE",

             "address": "192.168.119.187",

             "protocol_port": 8000,

             "id": "1d1b3da6-b1a1-485b-a25a-243e904fcedb",

             "operating_status": "ONLINE"

           }

         ],

         "id": "95f42465-0cab-477e-a7de-008621235d52",

         "operating_status": "ONLINE"

       }

     ],

     "l7policies": [],

     "id": "6cf0c3dd-3aec-4b35-b2a5-3c0a314834e8",

     "operating_status": "ONLINE"

   },

   {

     "name": "neutron-service-9999",

     "provisioning_status": "ACTIVE",

     "pools": [

       {

         "name": "neutron-service-9999",

         "provisioning_status": "ACTIVE",

         "healthmonitor": {},

         "members": [

           {

             "name": "",

             "provisioning_status": "ACTIVE",

             "address": "192.168.119.188",

             "protocol_port": 9000,

             "id": "2faa9f42-2734-416a-a6b2-ed922d01ca50",

             "operating_status": "ONLINE"

           },

           {

             "name": "",

             "provisioning_status": "ACTIVE",

             "address": "192.168.119.187",

             "protocol_port": 9000,

             "id": "81f777b1-d999-48b0-be79-6dbdedca5e97",

             "operating_status": "ONLINE"

           }

         ],

         "id": "476952ac-64a8-4594-8972-699e87ae5b9b",

         "operating_status": "ONLINE"

       }

     ],

     "l7policies": [],

     "id": "c6506b43-2453-4f04-ba87-f5ba4ee19b17",

     "operating_status": "ONLINE"

   }

 ],

 "pools": [

   {

     "name": "neutron-service-8888",

     "provisioning_status": "ACTIVE",

     "healthmonitor": {},

     "members": [

       {

         "name": "",

         "provisioning_status": "ACTIVE",

         "address": "192.168.119.188",

         "protocol_port": 8000,

         "id": "461a0856-5c97-417e-94b4-c3486d8e2160",

         "operating_status": "ONLINE"

       },

       {

         "name": "",

         "provisioning_status": "ACTIVE",

         "address": "192.168.119.187",

         "protocol_port": 8000,

         "id": "1d1b3da6-b1a1-485b-a25a-243e904fcedb",

         "operating_status": "ONLINE"

       }

     ],

     "id": "95f42465-0cab-477e-a7de-008621235d52",

     "operating_status": "ONLINE"

   },

   {

     "name": "neutron-service-9999",

     "provisioning_status": "ACTIVE",

     "healthmonitor": {},

     "members": [

       {

         "name": "",

         "provisioning_status": "ACTIVE",

         "address": "192.168.119.188",

         "protocol_port": 9000,

         "id": "2faa9f42-2734-416a-a6b2-ed922d01ca50",

         "operating_status": "ONLINE"

       },

       {

         "name": "",

         "provisioning_status": "ACTIVE",

         "address": "192.168.119.187",

         "protocol_port": 9000,

         "id": "81f777b1-d999-48b0-be79-6dbdedca5e97",

         "operating_status": "ONLINE"

       }

     ],

     "id": "476952ac-64a8-4594-8972-699e87ae5b9b",

     "operating_status": "ONLINE"

   }

 ],

 "id": "31b61658-4708-4a48-a3c4-0d61a127cd09",

 "operating_status": "ONLINE"

}

}

}

 

其對應的HAProxy進程配置如下所示:

 

# Configuration for neutron-service

global

daemon

user nobody

group nogroup

log /dev/log local0

log /dev/log local1 notice

stats socket /var/lib/neutron/lbaas/v2/31b61658-4708-4a48-a3c4-0d61a127cd09/haproxy_stats.sock mode 0666 level user

 

defaults

log global

retries 3

option redispatch

timeout connect 5000

timeout client 50000

timeout server 50000

 

frontend 6cf0c3dd-3aec-4b35-b2a5-3c0a314834e8

option tcplog

bind 192.168.119.178:8888

mode tcp

default_backend 95f42465-0cab-477e-a7de-008621235d52

 

frontend c6506b43-2453-4f04-ba87-f5ba4ee19b17

option tcplog

bind 192.168.119.178:9999

mode tcp

default_backend 476952ac-64a8-4594-8972-699e87ae5b9b

 

backend 476952ac-64a8-4594-8972-699e87ae5b9b

mode tcp

balance roundrobin

server 81f777b1-d999-48b0-be79-6dbdedca5e97 192.168.119.187:9000 weight 1

server 2faa9f42-2734-416a-a6b2-ed922d01ca50 192.168.119.188:9000 weight 1

 

backend 95f42465-0cab-477e-a7de-008621235d52

mode tcp

balance roundrobin

server 1d1b3da6-b1a1-485b-a25a-243e904fcedb 192.168.119.187:8000 weight 1

server 461a0856-5c97-417e-94b4-c3486d8e2160 192.168.119.188:8000 weight 1

 

綜上所述,通過基於Neutron的Skynet,我們為Kubernetes初步實現了SDN的功能,同時提供了如下網路功能增強:

 

  1. POD的IP、Mac、主機名稱等網路設定的保持;

     

  2. 基於Neutron安全性群組,實現了POD之間的網路隔離功能,更加通用;

     

  3. 支援通過HAProxy直接對外提供服務,效能上會比原生的iptables好很多。

 

當然,目前有一些Kubernetes特性在Skynet網路方案中還不支援,需要在後面進行增強或實現:

 

  1. Headless services這一類沒有叢集IP的Service無法處理。

     

  2. 由於neutron-server與neutron-plugin之間的訊息都是通過RabbitMQ進行,不是特別適合容器環境下網路快速變更的現狀,會是整個方案的一大瓶頸。

基於Neutron的Kubernetes SDN實踐經驗之談

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.