Change:
<!-- Thanks for filing an issue! Before hitting the button, please answer these questions.--Is this a request for help? (If yes, you should use our troubleshooting guide and community support channels, see ): What keywords did you search in Kubernetes issues before filing this one? (If you have found any duplicates, you should instead reply there.): Is this a BUG REPORT or FEATURE REQUEST? (choose one): FEATURE REQUEST <!-- If this is a BUG REPORT, please: Fill in as much of the template below as you can. If you leave out information, we can't help you as well. If this is a FEATURE REQUEST, please: Describe in detail the feature/behavior/change you'd like to see. In both cases, be ready for followup questions, and please respond in a timely manner. If we can't reproduce a bug or think a feature already exists, we might close your issue. If we're wrong, PLEASE feel free to reopen it and explain why. --Kubernetes version (use ): 1.6.2 Environment: Cloud provider or hardware configuration: AWS using Juju OS (e.g. from /etc/os-release): Ubuntu Xenial Kernel (e.g. ): 4.4.0-59-generic Install tools: Juju Others: What happened: kubefed init entered a infinite loop health checking the federation api service What you expected to happen: kubefed to exit with a success code How to reproduce it (as minimally and precisely as possible): Anything else we need to know: When doing a kubefed init on a cluster setup using VMs on aws (using Juju in my case) the worker nodes have two IPs: one that is visible to the internet and one internal visible only to VMs within aws. In my case for example the VM on aws hosting the kubernetes-worker node had external IP in the 54.174.73.1/24 subnet and it also had an internal IP in the 172.31.60.1/24 subnet. Using a client machine outside aws to bootstrap federation: I got the kubefed client stuck on doing a health check against the clouds internal subnet https://172.31.60.XXX:/healthz . To address this I can use the flag and pass the external IP of any kubernetes-worker node. With this flag kubeconfig file gets updated with the right endpoint for the federation-apiserver. However, apart from the I should also be able to specify the desired port the service will be listening on. I have to make sure that port is opened on the aws routing/firewall prior to issuing . In the example above, kubefed init will try to reach https://54.174.73.XXX:/healthz, port is randomly assigned and is not reachable. I should be able to first open the port on aws and then do a with and port pinned to .
/cc
/assign
is there a reason why you are not using the default load balanced service on AWS?
I am using Juju to stay cloud agnostic. AWS just happened to be where I deployed this time. Juju just grabs machines (virtual or physical) from wherever you have resources from. In effect your cluster is more like an on-prem than anything else. How would the default load balanced service work?
got it.

Discussion:
apiserverServiceTypeFlag      = "api-server-service-type" apiserverAdvertiseAddressFlag = "api-server-advertise-address" <ins> apiserverPortFlag             = "api-server-port" </ins> dnsProviderSecretName = "federation-dns-provider.conf"

apiServerServiceTypeString       string apiServerServiceType             v1.ServiceType apiServerAdvertiseAddress        string <ins> apiServerNodePortPort            int32 apiServerNodePortPortPtr         *int32 </ins> apiServerEnableHTTPBasicAuth     bool apiServerEnableTokenAuth         bool }

flags.StringVar(&o.controllerManagerOverridesString, "controllermanager-arg-overrides", "", "comma separated list of federation-controller-manager arguments to override: Example "--arg1=value1,--arg2=value2..."") flags.StringVar(&o.apiServerServiceTypeString, apiserverServiceTypeFlag, string(v1.ServiceTypeLoadBalancer), "The type of service to create for federation API server. Options: 'LoadBalancer' (default), 'NodePort'.") flags.StringVar(&o.apiServerAdvertiseAddress, apiserverAdvertiseAddressFlag, "", "Preferred address to advertise api server nodeport service. Valid only if '"+apiserverServiceTypeFlag+"=NodePort'.") <ins> flags.Int32Var(&o.apiServerNodePortPort, apiserverPortFlag, 0, "Preferred port to use for api server nodeport service (0 for random port assignment). Valid only if '"+apiserverServiceTypeFlag+"=NodePort'.") </ins> flags.BoolVar(&o.apiServerEnableHTTPBasicAuth, "apiserver-enable-basic-auth", false, "Enables HTTP Basic authentication for the federation-apiserver. Defaults to false.") flags.BoolVar(&o.apiServerEnableTokenAuth, "apiserver-enable-token-auth", false, "Enables token authentication for the federation-apiserver. Defaults to false.") }

} } <ins> if i.options.apiServerNodePortPort != 0 { if i.options.apiServerServiceType != v1.ServiceTypeNodePort { return fmt.Errorf("%s should be passed only with '%s=NodePort'", apiserverPortFlag, apiserverServiceTypeFlag) } i.options.apiServerNodePortPortPtr = &i.options.apiServerNodePortPort } else { i.options.apiServerNodePortPortPtr = nil } if i.options.apiServerNodePortPort < 0 || i.options.apiServerNodePortPort > 65535 { return fmt.Errorf("Please provide a valid port number for %s", apiserverPortFlag) } </ins> i.options.apiServerOverrides, err = marshallOverrides(i.options.apiServerOverridesString) if err != nil { return fmt.Errorf("error marshalling --apiserver-arg-overrides: %v", err)

fmt.Fprint(cmdOut, "Creating federation control plane service...") glog.V(4).Info("Creating federation control plane service") <del> svc, ips, hostnames, err := createService(cmdOut, hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.commonOptions.Name, i.options.apiServerAdvertiseAddress, i.options.apiServerServiceType, i.options.dryRun) </del> <ins> svc, ips, hostnames, err := createService(cmdOut, hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.commonOptions.Name, i.options.apiServerAdvertiseAddress, i.options.apiServerNodePortPortPtr, i.options.apiServerServiceType, i.options.dryRun) </ins> if err != nil { return err }

return clientset.Core().Namespaces().Create(ns) } <del> func createService(cmdOut io.Writer, clientset client.Interface, namespace, svcName, federationName, apiserverAdvertiseAddress string, apiserverServiceType v1.ServiceType, dryRun bool) (*api.Service, []string, []string, error) { </del> <ins> func createService(cmdOut io.Writer, clientset client.Interface, namespace, svcName, federationName, apiserverAdvertiseAddress string, apiserverPort *int32, apiserverServiceType v1.ServiceType, dryRun bool) (*api.Service, []string, []string, error) { port := api.ServicePort{ Name:       "https", Protocol:   "TCP", Port:       443, TargetPort: intstr.FromString(apiServerSecurePortName), } if apiserverServiceType == v1.ServiceTypeNodePort && apiserverPort != nil { port.NodePort = *apiserverPort } </ins> svc := &api.Service{ ObjectMeta: metav1.ObjectMeta{ Name:        svcName,

Spec: api.ServiceSpec{ Type:     api.ServiceType(apiserverServiceType), Selector: apiserverSvcSelector, <del> Ports: []api.ServicePort{ { Name:       "https", Protocol:   "TCP", Port:       443, TargetPort: intstr.FromString(apiServerSecurePortName), }, }, </del> <ins> Ports:    []api.ServicePort{port}, </ins> }, }

var err error svc, err = clientset.Core().Services(namespace).Create(svc) <ins> if err != nil { return nil, nil, nil, err } </ins> ips := []string{} hostnames := []string{}