之前圍繞阿里雲的容器服務,內部做了一次阿里雲基於k8s服務治理的總結。這次系統地學習了docker與k8s的網絡模型,並從kubelet出發研究了kubelet -> dockershim -> cni -> flannel的調用鏈路,對cni項目的源碼做了些許分析。
- Docker網絡模型
- K8S網絡模型
- 同POD網絡
- 同NODE網絡
- 不同NODE網絡
- CNI分析
Docker網絡模型
根據docker官方對於network的介紹,網絡方案可以分爲以下幾種:
- bridge
用於單個host上多個容器之間通信,bridge也是docker的默認網絡方案 - overlay
基於docker swarm,用於不同容器在多個host上進行通信 - host
移除容器的網絡隔離性,直接使用host上的網絡命名空間 - macvlan
自定義容器的mac地址,將容器作爲硬件設備。最佳實踐是想將容器直接連接到物理網絡時,可以考慮使用macvlan的方案 - none
容器沒有網絡聯通需求時,可以不配置
容器體系應用的網絡架構如下:
k8s網絡模型
k8s同pod
同一個pod內的容器共用一個網絡命名空間,直接訪問本地的端口就能通信
k8s同node
同一個主機上的不同pod之間,通過docker0網絡進行通信,接入同一個網橋內的容器屬於相同的網段。
k8s不同node,分佈式網絡
分佈式的網絡模型,常見的解決方案有Coreos的flannel與calico。阿里雲的k8s容器服務就是使用flannel對接Ali VPC接口完成的。
參考:
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源碼: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/