赞
踩
最近在学习kubernetes cni部分功能,学习 flannel源码发现数据转换处struct与配置文件中json无法对应,特此记录。【个人学习记录,如有错误,欢迎指出】
cat /etc/cni/net.d/10-flannel.conflist
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
cat flannel-release-v0.14.1\flannel.go
......
type NetConf struct {
types.NetConf
// IPAM field "replaces" that of types.NetConf which is incomplete
IPAM map[string]interface{} `json:"ipam,omitempty"`
SubnetFile string `json:"subnetFile"`
DataDir string `json:"dataDir"`
Delegate map[string]interface{} `json:"delegate"`
RuntimeConfig map[string]interface{} `json:"runtimeConfig,omitempty"`
}
......
func loadFlannelNetConf(bytes []byte) (*NetConf, error) {
n := &NetConf{
SubnetFile: defaultSubnetFile,
DataDir: defaultDataDir,
}
if err := json.Unmarshal(bytes, n); err != nil {
return nil, fmt.Errorf("failed to load netconf: %v", err)
}
return n, nil
}
......
此处delegate属于plugins数组内的子项,为何NetConf中定义却未体现层级关系?
cni/cnitool.go at release-0.8 · containernetworking/cni · GitHubContainer Network Interface - networking for Linux containers - cni/cnitool.go at release-0.8 · containernetworking/cnihttps://github.com/containernetworking/cni/blob/release-0.8/cnitool/cnitool.gohttps://github.com/containernetworking/cni/blob/release-0.8/cnitool/cnitool.go
func main() {
......
netconf, err := libcni.LoadConfList(netdir, os.Args[2])
if err != nil {
exit(err)
}
......
switch os.Args[1] {
case CmdAdd:
result, err := cninet.AddNetworkList(context.TODO(), netconf, rt)
if result != nil {
_ = result.Print()
}
exit(err)
重点关注这2个方法:
LoadConfList 重点关注调用流程如下:
func LoadConfList(dir, name string) (*NetworkConfigList, error)
func ConfListFromFile(filename string) (*NetworkConfigList, error)
func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
AddNetworkList 重点关注调用流程如下:
func (c *CNIConfig) AddNetworkList(ctx context.Context, list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) {
func (c *CNIConfig) addNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (types.Result, error) {
这里重点看一下LoadConfList 的func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) 方法。
func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
rawList := make(map[string]interface{})
//这里的bytes为1中完整配置文件的byte形式。
if err := json.Unmarshal(bytes, &rawList); err != nil {
return nil, fmt.Errorf("error parsing configuration list: %s", err)
}
list := &NetworkConfigList{
Name: name,
DisableCheck: disableCheck,
CNIVersion: cniVersion,
Bytes: bytes,
}
var plugins []interface{}
plug, ok := rawList["plugins"]
if !ok {
return nil, fmt.Errorf("error parsing configuration list: no 'plugins' key")
}
plugins, ok = plug.([]interface{})
......
for i, conf := range plugins {
//这里的newBytes为步骤1中完整配置文件单个plugin的byte形式。
newBytes, err := json.Marshal(conf)
if err != nil {
return nil, fmt.Errorf("failed to marshal plugin config %d: %v", i, err)
}
netConf, err := ConfFromBytes(newBytes)
if err != nil {
return nil, fmt.Errorf("failed to parse plugin config %d: %v", i, err)
}
list.Plugins = append(list.Plugins, netConf)
}
return list, nil
}
//ConfFromBytes 中也是类似的转换,最后NetworkConfig的Bytes字段值为如下json串对应byte格式。该Bytes将传递给cni插件cmdAdd使用。
{
"name": "cbr0",
"cniVersion": "0.3.1",
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
}
希望能够帮助您解决问题,欢迎您提出宝贵的建议。
end~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。