// RunIngressIPController starts the ingress ip controller if IngressIPNetworkCIDR is configured. func (c *MasterConfig) RunIngressIPController(client *kclient.Client) { // TODO need to disallow if a cloud provider is configured if len(c.Options.NetworkConfig.IngressIPNetworkCIDR) == 0 { return } _, ipNet, err := net.ParseCIDR(c.Options.NetworkConfig.IngressIPNetworkCIDR) if err != nil { // should have been caught with validation glog.Fatalf("Unable to start ingress ip controller: %v", err) } ingressIPController := ingressip.NewIngressIPController(client, ipNet, defaultIngressIPSyncPeriod) go ingressIPController.Run(utilwait.NeverStop) }
// RunIngressIPController starts the ingress ip controller if IngressIPNetworkCIDR is configured. func (c *MasterConfig) RunIngressIPController(client *kclient.Client) { if len(c.Options.NetworkConfig.IngressIPNetworkCIDR) == 0 { return } _, ipNet, err := net.ParseCIDR(c.Options.NetworkConfig.IngressIPNetworkCIDR) if err != nil { // should have been caught with validation glog.Fatalf("Unable to start ingress ip controller: %v", err) } if ipNet.IP.IsUnspecified() { return } ingressIPController := ingressip.NewIngressIPController(client, ipNet, defaultIngressIPSyncPeriod) go ingressIPController.Run(utilwait.NeverStop) }
// TestIngressIPAllocation validates that ingress ip allocation is // performed correctly even when multiple controllers are running. func TestIngressIPAllocation(t *testing.T) { testutil.RequireEtcd(t) masterConfig, err := testserver.DefaultMasterOptions() if err != nil { t.Fatalf("Unexpected error: %v", err) } masterConfig.NetworkConfig.ExternalIPNetworkCIDRs = []string{"172.16.0.0/24"} masterConfig.NetworkConfig.IngressIPNetworkCIDR = "172.16.1.0/24" clusterAdminKubeConfig, err := testserver.StartConfiguredMasterWithOptions(masterConfig, testserver.TestOptions{}) if err != nil { t.Fatalf("Unexpected error: %v", err) } kc, _, err := configapi.GetKubeClient(clusterAdminKubeConfig, &configapi.ClientConnectionOverrides{ QPS: 20, Burst: 50, }) if err != nil { t.Fatalf("Unexpected error: %v", err) } stopChannel := make(chan struct{}) defer close(stopChannel) received := make(chan bool) rand.Seed(time.Now().UTC().UnixNano()) t.Log("start informer to watch for sentinel") _, informerController := framework.NewInformer( &cache.ListWatch{ ListFunc: func(options kapi.ListOptions) (runtime.Object, error) { return kc.Services(kapi.NamespaceAll).List(options) }, WatchFunc: func(options kapi.ListOptions) (watch.Interface, error) { return kc.Services(kapi.NamespaceAll).Watch(options) }, }, &kapi.Service{}, time.Minute*10, framework.ResourceEventHandlerFuncs{ UpdateFunc: func(old, cur interface{}) { service := cur.(*kapi.Service) if service.Name == sentinelName && len(service.Spec.ExternalIPs) > 0 { received <- true } }, }, ) go informerController.Run(stopChannel) t.Log("start generating service events") go generateServiceEvents(t, kc) // Start a second controller that will be out of sync with the first _, ipNet, err := net.ParseCIDR(masterConfig.NetworkConfig.IngressIPNetworkCIDR) c := ingressip.NewIngressIPController(kc, ipNet, 10*time.Minute) go c.Run(stopChannel) t.Log("waiting for sentinel to be updated with external ip") select { case <-received: case <-time.After(time.Duration(90 * time.Second)): t.Fatal("took too long") } // Validate that all services of type load balancer have a unique // ingress ip and corresponding external ip. services, err := kc.Services(kapi.NamespaceDefault).List(kapi.ListOptions{}) if err != nil { t.Fatalf("Unexpected error: %v", err) } ips := sets.NewString() for _, s := range services.Items { typeLoadBalancer := s.Spec.Type == kapi.ServiceTypeLoadBalancer hasAllocation := len(s.Status.LoadBalancer.Ingress) > 0 switch { case !typeLoadBalancer && !hasAllocation: continue case !typeLoadBalancer && hasAllocation: t.Errorf("A service not of type load balancer has an ingress ip allocation") continue case typeLoadBalancer && !hasAllocation: t.Errorf("A service of type load balancer has not been allocated an ingress ip") continue } ingressIP := s.Status.LoadBalancer.Ingress[0].IP if ips.Has(ingressIP) { t.Errorf("One or more services have the same ingress ip") continue } ips.Insert(ingressIP) if len(s.Spec.ExternalIPs) == 0 || s.Spec.ExternalIPs[0] != ingressIP { t.Errorf("Service does not have the ingress ip as an external ip") continue } } }