赞
踩
一个基本的SDN系统一般包含管理面、控制面和数据(转发)面三部分,通俗来说,管理面的对外表现就是北向接口,拿Openshift中的SDN来说,它的北向接口就是CNI了,kubelet收到用户创建POD的请求后,会调用CRI接口去实现POD创建相关的工作,另一块就是调用CNI去完成网络相关的工作,当然这里的CNI主要分成两块:
一部分是二进制文件,也就是kubelet直接执行该二进制文件并向其传递pod id、namespace等参数;
另一部分就是CNI Server,接收CNI Client的请求,并调用SDN Controller去完成OVS Bridge端口、流表相关的配置,为POD打通网络。
控制面一个主要载体就是南向接口了,当然管理面的一些具体实现也有可能通过南向接口实现(这里不做重点分析),对于一个DC领域SDN控制器而言,其南向协议占了很大一部分的,说道南向协议很多人可能想到是Openflow、netconf、XMPP、P4 runtime……,不过可能要让大家失望了,这里并没采用上面说的那些高大上的协议,有的只是CLI、ovs-vsctl、ovs-ofctl、iptables等我们以前常用的命令而已,通过对这些常用命令的函数化封装、调用就组成了今天要用到的SDN南向协议。
可能很多人要在心里面犯嘀咕了,仅仅通过几条命令的调用能不能胜任这份重任呢?答案当然是肯定的,没有一点问题,大名鼎鼎的OpenStack中的Neutron也是这么干的,Neutron中的默认方式也是直接调用的命令来实现对OVS的控制,所以放心用吧。
我们这里重点介绍一下该SDN方案的数据面实现模型,当SDN Controller收到北向CNI Server的网络请求后,是如何控制OVS进行流表的增删改查、以及iptables相关的操作。
数据面就是指各种转发设备了,包括传统的硬件厂家个各种路由器、交换机、防火墙、负载均衡等,也包括各种纯软件实现的是Vswitch、Vrouter,其中OVS作为其中的典型代表,借着OpenStack等云计算技术的发展着实火了一把,在Openshift的SDN方案中OVS作为数据面的转发载体,起着至关重要的作用。
在一个基本的SDN系统中北向接口作为直接面向用户或者应用部分,一个主要的功能就是先理解用户的“语言”,这里的语言就是是CNI了,CNI也是容器平台一个重要的网络接口,基本动作包含:添加网络、删除网络、添加网络列表、删除网络列表。
在Openshift的SDN中,首先实现了一个CNI的client,编译后会产生一个二进制可执行文件,安装过程中一般会将该文件放置在/opt/cni/bin目录下,供kubelet调用。
在pkg/network/sdn-cni-plugin/openshift-sdn.go#line57文件中
// Send a CNI request to the CNI server via JSON + HTTP over a root-owned unix socket, // and return the result func (p *cniPlugin) doCNI(url string, req *cniserver.CNIRequest) ([]byte, error) { data, err := json.Marshal(req) if err != nil { returnnil, fmt.Errorf("failed to marshal CNI request %v: %v", req, err) }
client := &http.Client{ Transport: &http.Transport{ Dial: func(proto, addr string) (net.Conn, error) { return net.Dial("unix", p.socketPath) }, }, }
varresp *http.Response err = p.hostNS.Do(func(ns.NetNS) error { resp, err = client.Post(url, "application/json", bytes.NewReader(data)) return err }) if err != nil { returnnil, fmt.Errorf("failed to send CNI request: %v", err) } defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) if err != nil { returnnil, fmt.Errorf("failed to read CNI result: %v", err) }
if resp.StatusCode != 200 { returnnil, fmt.Errorf("CNI request failed with status %v: '%s'", resp.StatusCode, string(body)) }
return body, nil }
// Send the ADD command environment and config to the CNI server, returning // the IPAM result to the caller func (p *cniPlugin) doCNIServerAdd(req *cniserver.CNIRequest, hostVeth string) (types.Result, error) { req.HostVeth = hostVeth body, err := p.doCNI("http://dummy/", req) if err != nil { returnnil, err }
// We currently expect CNI version 0.2.0 results, because that's the // CNIVersion we pass in our config JSON result, err := types020.NewResult(body) if err != nil { returnnil, fmt.Errorf("failed to unmarshal response '%s': %v", string(body), err) }
return result, nil } ....
func (p *cniPlugin) CmdDel(args *skel.CmdArgs) error { _, err := p.doCNI("http://dummy/", newCNIRequest(args)) return err } |
主要实现了CmdAdd、CmdDel两种类型的方法供kubelet调用,以完成POD创建或者删除时相关网络配置的变更。
其次就是实现了一个CNI的Server用来响应处理CNI客户端的请求,Server 跟Client之间通过一个unix类型的Socket以HTTP + JSON 的方式进行通信。
在Openshift中每个NODE启动时都会顺带启动一个CNI Server,在文件origin/pkg/network/node/pod.go#line170中
// Start the CNI server and start processing requests from it func (m *podManager) Start(rundir string, localSubnetCIDR string, clusterNetworks []common.ClusterNetwork, serviceNetworkCIDR string) error { if m.enableHostports { iptInterface := utiliptables.New(utilexec.New(), utildbus.New(), utiliptables.ProtocolIpv4) m.hostportSyncer = kubehostport.NewHostportSyncer(iptInterface) }
varerrerror ifm.ipamConfig, err = getIPAMConfig(clusterNetworks, localSubnetCIDR); err != nil { return err }
go m.processCNIRequests()
m.cniServer = cniserver.NewCNIServer(rundir, &cniserver.Config{MTU: m.mtu, ServiceNetworkCIDR: serviceNetworkCIDR}) return m.cniServer.Start(m.handleCNIRequest) } |
其中的line184的cniserver.NewCNIServer具体实现在文件origin/pkg/network/node/cniserver/cniserver.go#line120中
// Create and return a new CNIServer object which will listen on a socket in the given path funcNewCNIServer(rundir string, config *Config) *CNIServer { router := mux.NewRouter()
s := &CNIServer{ Server: http.Server{ Handler: router, }, rundir: rundir, config: config, |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。