Merge pull request #50739 from FengyunPan/auto-get-subnet-id

Automatic merge from submit-queue (batch tested with PRs 50769, 50739)

Support autoprobing subnet-id for openstack cloud provider

Currently if user doesn't specify subnet-id or specify a unsafe
subnet-id, openstack cloud provider can't create a correct LoadBalancer
service.
Actually we can get it automatically. This patch do a improvement.
This is a part of #50726

**Special notes for your reviewer**:
/assign @dims 
/assign @anguslees 

**Release note**:
```release-note
NONE
```
This commit is contained in:
Kubernetes Submit Queue 2017-08-16 09:24:54 -07:00 committed by GitHub
commit e76ecd634a
2 changed files with 56 additions and 10 deletions

View File

@ -77,7 +77,7 @@ type LoadBalancer struct {
type LoadBalancerOpts struct {
LBVersion string `gcfg:"lb-version"` // overrides autodetection. v1 or v2
SubnetId string `gcfg:"subnet-id"` // required
SubnetId string `gcfg:"subnet-id"` // overrides autodetection.
FloatingNetworkId string `gcfg:"floating-network-id"` // If specified, will create floating ip for loadbalancer, or do not create floating ip.
LBMethod string `gcfg:"lb-method"` // default to ROUND_ROBIN.
CreateMonitor bool `gcfg:"create-monitor"`
@ -221,12 +221,6 @@ func readInstanceID() (string, error) {
func checkOpenStackOpts(openstackOpts *OpenStack) error {
lbOpts := openstackOpts.lbOpts
// subnet-id is required
if len(lbOpts.SubnetId) == 0 {
glog.Warningf("subnet-id not set in cloud provider config. " +
"OpenStack Load balancer will not work.")
}
// if need to create health monitor for Neutron LB,
// monitor-delay, monitor-timeout and monitor-max-retries should be set.
emptyDuration := MyDuration{}

View File

@ -570,6 +570,34 @@ func getStringFromServiceAnnotation(service *v1.Service, annotationKey string, d
return defaultSetting
}
// getSubnetIDForLB returns subnet-id for a specific node
func getSubnetIDForLB(compute *gophercloud.ServiceClient, node v1.Node) (string, error) {
ipAddress, err := nodeAddressForLB(&node)
if err != nil {
return "", err
}
instanceID := node.Spec.ProviderID
if ind := strings.LastIndex(instanceID, "/"); ind >= 0 {
instanceID = instanceID[(ind + 1):]
}
interfaces, err := getAttachedInterfacesByID(compute, instanceID)
if err != nil {
return "", err
}
for _, intf := range interfaces {
for _, fixedIP := range intf.FixedIPs {
if fixedIP.IPAddress == ipAddress {
return intf.NetID, nil
}
}
}
return "", ErrNotFound
}
// TODO: This code currently ignores 'region' and always creates a
// loadbalancer in only the current OpenStack region. We should take
// a list of regions (from config) and query/create loadbalancers in
@ -579,7 +607,15 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv
glog.V(4).Infof("EnsureLoadBalancer(%v, %v, %v, %v, %v, %v, %v)", clusterName, apiService.Namespace, apiService.Name, apiService.Spec.LoadBalancerIP, apiService.Spec.Ports, nodes, apiService.Annotations)
if len(lbaas.opts.SubnetId) == 0 {
return nil, fmt.Errorf("subnet-id not set in cloud provider config")
// Get SubnetId automatically.
// The LB needs to be configured with instance addresses on the same subnet, so get SubnetId by one node.
subnetID, err := getSubnetIDForLB(lbaas.compute, *nodes[0])
if err != nil {
glog.Warningf("Failed to find subnet-id for loadbalancer service %s/%s: %v", apiService.Namespace, apiService.Name, err)
return nil, fmt.Errorf("No subnet-id for service %s/%s : subnet-id not set in cloud provider config, "+
"and failed to find subnet-id from OpenStack: %v", apiService.Namespace, apiService.Name, err)
}
lbaas.opts.SubnetId = subnetID
}
ports := apiService.Spec.Ports
@ -947,7 +983,15 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(clusterName string, service *v1.Service
glog.V(4).Infof("UpdateLoadBalancer(%v, %v, %v)", clusterName, loadBalancerName, nodes)
if len(lbaas.opts.SubnetId) == 0 {
return fmt.Errorf("subnet-id not set in cloud provider config")
// Get SubnetId automatically.
// The LB needs to be configured with instance addresses on the same subnet, so get SubnetId by one node.
subnetID, err := getSubnetIDForLB(lbaas.compute, *nodes[0])
if err != nil {
glog.Warningf("Failed to find subnet-id for loadbalancer service %s/%s: %v", service.Namespace, service.Name, err)
return fmt.Errorf("No subnet-id for service %s/%s : subnet-id not set in cloud provider config, "+
"and failed to find subnet-id from OpenStack: %v", service.Namespace, service.Name, err)
}
lbaas.opts.SubnetId = subnetID
}
ports := service.Spec.Ports
@ -1226,7 +1270,15 @@ func (lb *LbaasV1) EnsureLoadBalancer(clusterName string, apiService *v1.Service
glog.V(4).Infof("EnsureLoadBalancer(%v, %v, %v, %v, %v, %v, %v)", clusterName, apiService.Namespace, apiService.Name, apiService.Spec.LoadBalancerIP, apiService.Spec.Ports, nodes, apiService.Annotations)
if len(lb.opts.SubnetId) == 0 {
return nil, fmt.Errorf("subnet-id not set in cloud provider config")
// Get SubnetId automatically.
// The LB needs to be configured with instance addresses on the same subnet, so get SubnetId by one node.
subnetID, err := getSubnetIDForLB(lb.compute, *nodes[0])
if err != nil {
glog.Warningf("Failed to find subnet-id for loadbalancer service %s/%s: %v", apiService.Namespace, apiService.Name, err)
return nil, fmt.Errorf("No subnet-id for service %s/%s : subnet-id not set in cloud provider config, "+
"and failed to find subnet-id from OpenStack: %v", apiService.Namespace, apiService.Name, err)
}
lb.opts.SubnetId = subnetID
}
ports := apiService.Spec.Ports