简介:KubeStack is an OpenStack network provider for
kubernetes.KubeStack is devided into two functions:

  • kubestack running on the same host with kube-controller-manager,
    which provides network management for openstack
  • kubestack running on each minion host, which setups container’s
    network interfaces

 

kubestack.conf的默认配置文件如下所示:

[Global]
auth-url = http://${IF_IP}:5000/v2.0
username = admin
password = admin
tenant-name = admin
region = RegionOne
ext-net-id = ${EXT_NET_ID}

[LoadBalancer]
create-monitor = yes
monitor-delay = 1m
monitor-timeout = 30s
monitor-max-retries = 3

[Plugin]
plugin-name = ovs

  

// kubestack.go

1、func main()

1、调用config, err :=
os.Open(configFile)打开配置文件,configFile默看/etc/kubestack.conf

2、调用openstack, err := common.NewOpenStack(config)

3、调用server := kubestack.NewKubeHandler(openstack)

4、最后,调用server.Serve(port)举行监听,端口号默认为4237

 

OpenStack数据结构如下所示:

// OpenStack is an implementation of network provider Interface for OpenStack

type OpenStack struct {

  network    *gophercloud.ServiceClient
  identity   *gophercloud.ServiceClient
  provider   *gophercloud.ProviderClient
  region     string
  lbOpts     LoadBalancerOpts
  pluginOpts  PluginOpts

  ExtNetID    string

  Plugin      plugins.PluginInterface 
}

// pkg/common/openstack.go

2、func NewOpenStack(config io.Reader) (*OpenStack, error)

  • 调用err := gcfg.ReadInto(&cfg, config)读取配置信息
  • 调用provider, err :=
    openstack.AuthenticatedClient(cfg.toAuthOptions()) 用于auth
    openstack
  • 调用identity, err := openstack.NewIdentityV2(provider,
    gophercloud.EndpointOpts{Availability:
    gophercloud.AvailabilityAdmin})用于find identity endpoint
  • 调用network, err := openstack.NewNetworkV2(provider,
    gophercloud.EndpointOpts{Region: cfg.Global.Region})
  • 创建 os := OpenStack{

    identity:    identity,

    network:    network,

    provider:    provider,

    region:     cfg.Global.Region,

    lbOpts:     cfg.LoadBalancer,

    pluginOpts:   cfg.Plugin,

    ExtNetID:    cfg.Global.ExtNetID,

  }

  • 当cfg.Plugin.PluginName 不为nil时:
    • integrationBriage :=
      “br-int”,若cfg.Plugin.IntegrationBridge不为””,则设置integrationBriage
      = cfg.Plugin.IntegrationBridge
    • 调用plugin, _ :=
      plugins.GetNetworkPlugin(cfg.Plugin.PluginName)
    • 若plugin不为nil,则调用plugin.Init(integrationBriage),并且os.Plugin
      = plugin
  • 最后,返回return &os, nil

 

// pkg/plugins/plugins.go

// GetNetworkPlugin creates an instance of the named network plugin, or
nil if

// the name is unkown. The error return is only used if the named plugin

// was known but failed to initialize

3、func GetNetworkPlugin(name string) (PluginInterface, error)

该函数仅仅调用f, found :=
plugins[name]得plugin的Factory函数f(),调用该f()函数生成对应的PluginInterface

(要是相应的Plugin被协助,则对应的担保在伊始化的时光便曾以init()函数中进行了登记,因而一定能于那时候找到)

 

PluginInterface数据结构如下所示:

type PluginInterface interface {

  SetupInterface(podName, podInfraContainerID string, port *ports.Port, ipcidr, gateway string, dnsServers []string, containerRuntime string) error

  DestroyInterface(podName, podInfraContainerID string, port *ports.Port, containerRuntime string) error

  Init(integrationBridge string) error

}

  

 

// pkg/kubestack/kubestack.go

4、func NewKubeHandler(driver *common.OpenStack) *kubeHandler

该函数仅仅只是开首化并报grpc server,生成h := &KubeHandler{driver:
driver, server: grpc.NewServer()}

 

kubeHandler的布局如下所示:

// KubeHandler forwards requests and responses between 
// the docker daemon and the plugin.
type KubeHandler struct {
  driver  *common.OpenStack
  server  *grpc.Server
}

  

————-到是截至,kubestack
初叶化完成,接下为网络的成立过程————-

// pkg/kubestack/kubestack.go

1、func (h *KubeHandler) CreateNetwork(c context.Context, req
*provider.CreateNetworkRequest) (*provider.CommonResponse, error)

1、首先调用req.Network.TenantID =
h.driver.ToTenantID(req.Network.TenantID),将tenantName转换为tenantID

2、再调用err := h.driver.CreateNetwork(req.Network)创立网络

 

Network数据结构如下所示:

type Network struct {
  Name     string
  Uid      string
  TenantID   string
  SegmentID   int32
  Subnets   []*Subnet
  // Status of network
  // Valid value: Initializing, Active, Pending, Failed, Terminating
  Status    string
}

  

Subnet数据结构如下所示:

type Subnet struct {

  Name      string
  Uid       string
  Cidr      string
  Gateway    string
  Tenantid    string
  Dnsservers   []string
  Routes     []*Route
}

  

// pkg/common/openstack.go

2、func (os *OpenStack) CreateNetwork(network *provider.Network)
error

1、首先创造opts := networks.CreateOpts{

  Name:      network.Name,

  AdminStateUp:  &adminStateUp,

  TenantID:     network.TenantID,

}

重复调用osNet, err := networks.Create(os.network, opts).Extract()成立网络

2、同样调用routerOpts := routers.CreateOpts{

  Name:      network.Name,

  TenantID:     network.TenantID,

  GatewayInfo:   &routers.GatewayInfo{NetworkID: os.ExtNetID},

}

再调用osRouter, err := routers.Create(os.network,
routerOpts).Extract()创建router

3、最终,遍历network.Subnets创制子网

  1. 第一创建 subnetOpts := subnets.CreateOpts{

    NetworkID:      networkID,   //其实就是osNet.ID

    CIDR:         sub.Cidr,

    Name:         sub.Name,

    IPVersion:       gophercloud.IPv4,

    TenantID:       network.TenantID,

    GatewaryIP:      &sub.Gateway,

    DNSNameserver:    sub.Dnsservers,

  }

  再调用s, err := subnets.Create(os.network,
subnetOpts).Extract()创制子网

  // 将子网插手router中

  2. 创建opts := routers.AddInterfaceOpts{SubnetID: s.ID},

    再调用routers.AddInterface(os.network, osRouter.ID,
opts).Extract()

 

—————————————创建pod—————————————–

// pkg/kubestack/kubestack.go

1、func (h *KubeHandler) SetupPod(c context.Context, req
*provider.SetupPodRequest) (*provider.CommonResponse, error)

该函数仅仅是调用h.driver.SetupPod(req.PodName, req.Namespace,
req.PodInfraContainerID, req.Network, req.ContainerRuntime)

 

SetupPodRequest数据结构如下所示:

type SetupPodRequest struct {
  PodName      string
  Namespace     string
  ContainerRuntime  string
  PodInfraContainerID string
  Network       *Network
}

 

// pkg/common/openstack.go

2、func (os *OpenStack) SetupPod(podName, namespace,
podInfraContainerID string, network *provider.Network, containerRuntime
string)

1、调用portName := os.BuildPortName(podName, namespace,
network.Uid),该函数的图就是用podNamePrefix和上述两只参数连成一个字符串而一度

2、获取dns server的ip,调用networkPorts, err :=
os.ListPorts(network.Uid,
“network:dhcp”),再遍历networkPorts,调用dnsServers = append(dnsServers,
p.FixedIPs[0].IPAddress)

3、调用port, err :=
os.GetPort(portName),从openstack中拿走port,即便port不在,则调用portWithBinding,
err := os.CreatePort(network.Uid, network.TenantID, portName,
podHostname)成立一个

4、如若port.DeviceOwner和骨子里的deviceOwner不符,则更新hostname

5、调用subnet, err :=
os.getProviderSubnet(port.FixedIPs[0].SubnetID)获取子网和网关

6、最后,调用os.Plugin.SetupInterface(podName+”_”+namespace,
podInfraContainerID, port, fmt.Sprintf(“%s/%d”,
port.FixedIPs[0].IPAddress, prefixSize), subnet.Gateway, dnsServers,
containerRuntime)为pod设置网卡

 

———————————–OVS
plugin实现—————————————

OVSPlugin的数据结构很简单,如下所示:

type OVSPlugin struct {

  IntegrationBridage string

}

  

// pkg/plugins/openvswitch/openvswitch.go

1、func (p *OVSPlugin) Init(integrationBridge string) error

拖欠函数仅仅以p.IntegrationBridage赋值为integrationBridge

 

// pkg/plugins/openvswitch/openvswitch.go

2、func (p *OVSPlugin) SetupInterface(podName, podInfraContainerID
string, port *ports.Port, ipcidr, gatewary string, dnsServers
[]string, containerRuntime string) error

1、先调用err := p.SetupOVSInterface(podName, podInfraContainerID, port,
ipcidr, gatewary, containerRuntime)创建OVS interface

2、再遵照containerRuntime的不同,分别调用p.SetupDockerInterface(podName,
podInfraContainerID, port, ipcidr,
gateway)或者p.SetupHyperInterface(podName, podInfraContainerID, port,
ipcidr, gateway, dnsServers)

 

// pkg/plugins/openvswitch/openvswitch.go

3、func (p *OVSPlugin)  SetupOVSInterface(podName,
podInfraContainerID string, port *ports.Port, ipcidr, gateway string,
containerRuntime string)

1、该函数调用exec.RunCommand函数创设一个veth
pair以及一个bridge,并将中一个veth参与bridge中

2、调用ovs-vsctl,对其它一个veth举办操作

 

// pkg/plugins/openvswitch/openvswitch.go

4、func (p *OVSPlugin) SetupDockerInterface(podName,
podInfraContainerID string, port *ports.Port, ipcidr, gateway string)
error

1、先创设一个veth对,tapName和vifName,并且将tapName参加在此以前成立的bridge中

2、将vifName的MAC地址设置为port.MACAddress

3、遵照podInfraContainerID容器的pid找到相应的net
ns,并把它软链接到/var/run/netns目录,从而能用ip命令对其直接举办操作。

4、将vifName插手net ns中,再去其中的eth0网卡,再以vifName重命名吧eth0

5、调用`ip addr add dev eth0 ipcidr`添加ip,以及`ip route add default
via gateway`创建默认路出于

 

// pkg/plugins/openvswitch/openvswitch.go

5、func (p *OVSPlugin) SetupHyperInterface(podName,
podInfraContainerID string, port *ports.Port, ipcidr, gateway string,
dnsServers []string)

1、首先拿到bridge和tapName

2、创建interfaceSpec := map[string]string{

  ”bridge”:    bridge,

  ”ifname”:    tapName,

  ”mac”:     port.MACAddress,

  ”ip”:       ipcidr,

  ”gateway”:   gateway,

} 生成network interface的配置

3、调用podSpec, err :=
p.getHyperPodSpec(podName)获取旧的hyper配置,并解码至specData中

4、调用specData[“interfaces”] =
[]map[string]string{interfaceSpec}将network interface的安排在其中

5、在specData[“dns”]的基础之上添加dnsServers

6、最终调用newPodSpec, err :=
json.马尔斯hal(specData)和p.saveHyperPodSpec(string(newPodSpec),
podName)将新的hyper配置写副文件中

 

注:Neutron
Port代表的是一个逻辑沟通机中之一个虚构交流机端口。虚拟机实例将协调之网卡和这多少个端口不断,这么些逻辑端口还要定义了连接到其被之接口的MAC地址与IP地址。当一个IP地址及一个端口关联起来的早晚,这代表这一个端口与一个子网相连,因为此IP地址便是于一个一定子网的allocation
pool中获取之。

 

相关文章

网站地图xml地图