@@ -2,9 +2,7 @@ package controller
22
33import (
44 "context"
5- "crypto/tls"
65 "fmt"
7- "io"
86 "net/http"
97 "sync"
108 "time"
@@ -14,6 +12,7 @@ import (
1412 utilfeature "k8s.io/apiserver/pkg/util/feature"
1513 "k8s.io/client-go/informers"
1614 "k8s.io/client-go/kubernetes"
15+ "k8s.io/client-go/rest"
1716 "k8s.io/client-go/tools/clientcmd"
1817 cloudprovider "k8s.io/cloud-provider"
1918 nodecontroller "k8s.io/cloud-provider/controllers/node"
@@ -109,80 +108,76 @@ func (c *Controller) Run(ctx context.Context) {
109108 }
110109}
111110
111+ func (c * Controller ) getKubeConfig (cluster string , internal bool ) (* rest.Config , error ) {
112+ kconfig , err := c .kind .KubeConfig (cluster , internal )
113+ if err != nil {
114+ klog .Errorf ("Failed to get kubeconfig for cluster %s: %v" , cluster , err )
115+ return nil , err
116+ }
117+
118+ config , err := clientcmd .RESTConfigFromKubeConfig ([]byte (kconfig ))
119+ if err != nil {
120+ klog .Errorf ("Failed to convert kubeconfig for cluster %s: %v" , cluster , err )
121+ return nil , err
122+ }
123+ return config , nil
124+ }
125+
112126// getKubeClient returns a kubeclient for the cluster passed as argument
113127// It tries first to connect to the internal endpoint.
114128func (c * Controller ) getKubeClient (ctx context.Context , cluster string ) (kubernetes.Interface , error ) {
115- httpClient := & http.Client {
116- Timeout : 5 * time .Second ,
117- Transport : & http.Transport {
118- TLSClientConfig : & tls.Config {InsecureSkipVerify : true },
119- },
129+ addresses := []string {}
130+ internalConfig , err := c .getKubeConfig (cluster , true )
131+ if err != nil {
132+ klog .Errorf ("Failed to get internal kubeconfig for cluster %s: %v" , cluster , err )
133+ } else {
134+ addresses = append (addresses , internalConfig .Host )
135+ }
136+ externalConfig , err := c .getKubeConfig (cluster , false )
137+ if err != nil {
138+ klog .Errorf ("Failed to get external kubeconfig for cluster %s: %v" , cluster , err )
139+ } else {
140+ addresses = append (addresses , externalConfig .Host )
120141 }
121- // prefer internal (direct connectivity) over no-internal (commonly portmap)
122- for _ , internal := range []bool {true , false } {
123- kconfig , err := c .kind .KubeConfig (cluster , internal )
124- if err != nil {
125- klog .Errorf ("Failed to get kubeconfig for cluster %s: %v" , cluster , err )
126- continue
127- }
128142
129- config , err := clientcmd .RESTConfigFromKubeConfig ([]byte (kconfig ))
130- if err != nil {
131- klog .Errorf ("Failed to convert kubeconfig for cluster %s: %v" , cluster , err )
132- continue
133- }
143+ if len (addresses ) == 0 {
144+ return nil , fmt .Errorf ("could not find kubeconfig for cluster %s" , cluster )
145+ }
134146
135- // check that the apiserver is reachable before continue
136- // to fail fast and avoid waiting until the client operations timeout
137- var ok bool
138- for i := 0 ; i < 5 ; i ++ {
139- select {
140- case <- ctx .Done ():
141- return nil , ctx .Err ()
142- default :
143- }
144- if probeHTTP (httpClient , config .Host ) {
145- ok = true
146- break
147- }
147+ var host string
148+ for i := 0 ; i < 5 ; i ++ {
149+ host , err = firstSuccessfulProbe (ctx , addresses )
150+ if err != nil {
151+ klog .Errorf ("Failed to connect to any address in %v: %v" , addresses , err )
148152 time .Sleep (time .Second * time .Duration (i ))
153+ } else {
154+ klog .Infof ("Connected succesfully to %s" , host )
155+ break
149156 }
150- if ! ok {
151- klog .Errorf ("Failed to connect to apiserver %s: %v" , cluster , err )
152- continue
153- }
157+ }
154158
155- kubeClient , err := kubernetes .NewForConfig (config )
156- if err != nil {
157- klog .Errorf ("Failed to create kubeClient for cluster %s: %v" , cluster , err )
158- continue
159- }
159+ var config * rest.Config
160+ switch host {
161+ case internalConfig .Host :
162+ config = internalConfig
160163 // the first cluster will give us the type of connectivity between
161164 // cloud-provider-kind and the clusters and load balancer containers.
162165 // In Linux or containerized cloud-provider-kind this will be direct.
163166 once .Do (func () {
164- if internal {
165- cpkconfig .DefaultConfig .ControlPlaneConnectivity = cpkconfig .Direct
166- }
167+ cpkconfig .DefaultConfig .ControlPlaneConnectivity = cpkconfig .Direct
167168 })
168- return kubeClient , err
169+ case externalConfig .Host :
170+ config = externalConfig
171+ default :
172+ return nil , fmt .Errorf ("restConfig for host %s not avaliable" , host )
169173 }
170- return nil , fmt .Errorf ("can not find a working kubernetes clientset" )
171- }
172174
173- func probeHTTP (client * http.Client , address string ) bool {
174- klog .Infof ("probe HTTP address %s" , address )
175- resp , err := client .Get (address )
175+ kubeClient , err := kubernetes .NewForConfig (config )
176176 if err != nil {
177- klog .Infof ("Failed to connect to HTTP address %s: %v" , address , err )
178- return false
177+ klog .Errorf ("Failed to create kubeClient for cluster %s: %v" , cluster , err )
178+ return kubeClient , err
179179 }
180- defer resp .Body .Close ()
181- // drain the body
182- io .ReadAll (resp .Body ) // nolint:errcheck
183- // we only want to verify connectivity so don't need to check the http status code
184- // as the apiserver may not be ready
185- return true
180+ return kubeClient , nil
186181}
187182
188183// TODO: implement leader election to not have problems with multiple providers
0 commit comments