docker與k8s網絡模型學習

之前圍繞阿里雲的容器服務,內部做了一次阿里雲基於k8s服務治理的總結。這次系統地學習了docker與k8s的網絡模型,並從kubelet出發研究了kubelet -> dockershim -> cni -> flannel的調用鏈路,對cni項目的源碼做了些許分析。

  • Docker網絡模型
  • K8S網絡模型
    • 同POD網絡
    • 同NODE網絡
    • 不同NODE網絡
  • CNI分析

Docker網絡模型

根據docker官方對於network的介紹,網絡方案可以分爲以下幾種:

  1. bridge
    用於單個host上多個容器之間通信,bridge也是docker的默認網絡方案
  2. overlay
    基於docker swarm,用於不同容器在多個host上進行通信
  3. host
    移除容器的網絡隔離性,直接使用host上的網絡命名空間
  4. macvlan
    自定義容器的mac地址,將容器作爲硬件設備。最佳實踐是想將容器直接連接到物理網絡時,可以考慮使用macvlan的方案
  5. none
    容器沒有網絡聯通需求時,可以不配置

容器體系應用的網絡架構如下:
容器網絡

k8s網絡模型

k8s同pod

同一個pod內的容器共用一個網絡命名空間,直接訪問本地的端口就能通信

同pod網絡

k8s同node

同一個主機上的不同pod之間,通過docker0網絡進行通信,接入同一個網橋內的容器屬於相同的網段。

不同pod網絡

k8s不同node,分佈式網絡

多node網絡

分佈式的網絡模型,常見的解決方案有Coreos的flannel與calico。阿里雲的k8s容器服務就是使用flannel對接Ali VPC接口完成的。

參考:
flannel

calico

CNI分析

CNI是Container Network Interface的縮寫,簡單地說,就是一個標準的,通用的接口。已知我們現在有各種各樣的容器平臺:docker,kubernetes,mesos,我們也有各種各樣的容器網絡解決方案:flannel,calico,weave,並且還有各種新的解決方案在不斷涌現。

如果每出現一個新的解決方案,我們都需要對兩者進行適配,那麼由此帶來的工作量必然是巨大的,而且也是重複和不必要的。事實上,只要提供一個標準的接口,更準確的說是一種協議,就能完美地解決上述問題。一旦有新的網絡方案出現,只要它能滿足這個標準的協議,那麼它就能爲同樣滿足該協議的所有容器平臺提供網絡功能,而CNI正是這樣的一個標準接口協議。

源碼結構

倉庫:cni

repo主要組成

      |- cnitool (cni命令行工具)
      |- libcni (cni的interface申明與默認CNIConfig實現)
      |- pkg (調用插件的方法庫及網絡定義相關的結構)
      |- scripts(打包編譯腳本與執行腳本)

###源碼

type CNI interface {
    //network list
    AddNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
    CheckNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
    DelNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
 
    //network
    AddNetwork(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
    CheckNetwork(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
    DelNetwork(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error

    //Validation
    ValidateNetworkList(ctx context.Context, net *NetworkConfigList) ([]string, error)
    ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error)
}

核心配置主要有RuntimeConf與NetworkConfig

RuntimeConf

type RuntimeConf struct {
    ContainerID string //在cnitool裏containerID是根據net namespace做sha512得到
    NetNS string //network namespace
    IfName string //網卡名
    Args [][2]string //執行命令行參數,底層是轉換爲環境變量
    CapabilityArgs map[string]interface{} //用於網絡插件執行的輸入參數
    CacheDir string
}

NetworkConf

type NetworkConfig struct {
    Network *types.Netconf
    Bytes []byte
}

type NetworkConfigList struct {
    Name string
    CNIVersion string
    DisableCheck bool
    Plugins []*NetworkConfig
    Bytes []byte
}

type NetConf struct {
    CNIVersion string
    Name string
    Type string
    Capabilities map[string]bool
    IPAM IPAM
    DNS DNS
    RawPrevResult map[string]interface{}
    PrevResult Result
}

默認沒有自定義plugin執行器時,cni默認的exec爲CNIConfig{},Exec是interface類型,默認有ExecPlugin、FindInPath與Decode三個函數。

執行邏輯

以AddNetwork爲例

CNI.AddNetwork -> 
addNetwork -> 
exec.FindInPath -> 
buildOneConfig(network config) -> 
ExecPluginWithResult -> 
setCachedResult

CNI執行邏輯

參考:

  • CNI源碼:https://github.com/containernetworking/cni
  • k8s網絡原理:http://www.youruncloud.com/blog/131.html
    …(img-3U65HuYc-1586319883545)]

參考:

  • CNI源碼:https://github.com/containernetworking/cni
  • k8s網絡原理:http://www.youruncloud.com/blog/131.html
  • K8S-CNI https://feisky.gitbooks.io/kubernetes/network/cni/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章