Skip to content

Commit 2a9a9fa

Browse files
committed
kube-apiserver: first remove endpoints, then add when ready
1 parent 14f2a33 commit 2a9a9fa

File tree

5 files changed

+35
-12
lines changed

5 files changed

+35
-12
lines changed

pkg/master/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ go_library(
115115
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
116116
"//staging/src/k8s.io/client-go/informers:go_default_library",
117117
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
118+
"//staging/src/k8s.io/client-go/rest:go_default_library",
118119
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
119120
"//vendor/k8s.io/klog:go_default_library",
120121
],

pkg/master/controller.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package master
1919
import (
2020
"fmt"
2121
"net"
22+
"net/http"
2223
"time"
2324

2425
corev1 "k8s.io/api/core/v1"
@@ -31,6 +32,7 @@ import (
3132
genericapiserver "k8s.io/apiserver/pkg/server"
3233
utilfeature "k8s.io/apiserver/pkg/util/feature"
3334
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
35+
"k8s.io/client-go/rest"
3436
"k8s.io/klog"
3537
"k8s.io/kubernetes/pkg/features"
3638
"k8s.io/kubernetes/pkg/master/reconcilers"
@@ -51,6 +53,7 @@ type Controller struct {
5153
ServiceClient corev1client.ServicesGetter
5254
NamespaceClient corev1client.NamespacesGetter
5355
EventClient corev1client.EventsGetter
56+
healthClient rest.Interface
5457

5558
ServiceClusterIPRegistry rangeallocation.RangeRegistry
5659
ServiceClusterIPInterval time.Duration
@@ -80,7 +83,7 @@ type Controller struct {
8083
}
8184

8285
// NewBootstrapController returns a controller for watching the core capabilities of the master
83-
func (c *completedConfig) NewBootstrapController(legacyRESTStorage corerest.LegacyRESTStorage, serviceClient corev1client.ServicesGetter, nsClient corev1client.NamespacesGetter, eventClient corev1client.EventsGetter) *Controller {
86+
func (c *completedConfig) NewBootstrapController(legacyRESTStorage corerest.LegacyRESTStorage, serviceClient corev1client.ServicesGetter, nsClient corev1client.NamespacesGetter, eventClient corev1client.EventsGetter, healthClient rest.Interface) *Controller {
8487
_, publicServicePort, err := c.GenericConfig.SecureServing.HostPort()
8588
if err != nil {
8689
klog.Fatalf("failed to get listener address: %v", err)
@@ -95,6 +98,7 @@ func (c *completedConfig) NewBootstrapController(legacyRESTStorage corerest.Lega
9598
ServiceClient: serviceClient,
9699
NamespaceClient: nsClient,
97100
EventClient: eventClient,
101+
healthClient: healthClient,
98102

99103
EndpointReconciler: c.ExtraConfig.EndpointReconcilerConfig.Reconciler,
100104
EndpointInterval: c.ExtraConfig.EndpointReconcilerConfig.Interval,
@@ -138,6 +142,12 @@ func (c *Controller) Start() {
138142
return
139143
}
140144

145+
// Reconcile during first run removing itself until server is ready.
146+
endpointPorts := createEndpointPortSpec(c.PublicServicePort, "https", c.ExtraEndpointPorts)
147+
if err := c.EndpointReconciler.RemoveEndpoints(kubernetesServiceName, c.PublicIP, endpointPorts); err != nil {
148+
klog.Errorf("Unable to remove old endpoints from kubernetes service: %v", err)
149+
}
150+
141151
repairClusterIPs := servicecontroller.NewRepair(c.ServiceClusterIPInterval, c.ServiceClient, c.EventClient, &c.ServiceClusterIPRange, c.ServiceClusterIPRegistry)
142152
repairNodePorts := portallocatorcontroller.NewRepair(c.ServiceNodePortInterval, c.ServiceClient, c.EventClient, c.ServiceNodePortRange, c.ServiceNodePortRegistry)
143153

@@ -150,10 +160,6 @@ func (c *Controller) Start() {
150160
// If we fail to repair node ports apiserver is useless. We should restart and retry.
151161
klog.Fatalf("Unable to perform initial service nodePort check: %v", err)
152162
}
153-
// Service definition is reconciled during first run to correct port and type per expectations.
154-
if err := c.UpdateKubernetesService(true); err != nil {
155-
klog.Errorf("Unable to perform initial Kubernetes service initialization: %v", err)
156-
}
157163

158164
c.runner = async.NewRunner(c.RunKubernetesNamespaces, c.RunKubernetesService, repairClusterIPs.RunUntil, repairNodePorts.RunUntil)
159165
c.runner.Start()
@@ -168,7 +174,8 @@ func (c *Controller) Stop() {
168174
go func() {
169175
defer close(finishedReconciling)
170176
klog.Infof("Shutting down kubernetes service endpoint reconciler")
171-
if err := c.EndpointReconciler.StopReconciling(kubernetesServiceName, c.PublicIP, endpointPorts); err != nil {
177+
c.EndpointReconciler.StopReconciling()
178+
if err := c.EndpointReconciler.RemoveEndpoints(kubernetesServiceName, c.PublicIP, endpointPorts); err != nil {
172179
klog.Error(err)
173180
}
174181
}()
@@ -178,7 +185,7 @@ func (c *Controller) Stop() {
178185
// done
179186
case <-time.After(2 * c.EndpointInterval):
180187
// don't block server shutdown forever if we can't reach etcd to remove ourselves
181-
klog.Warning("StopReconciling() timed out")
188+
klog.Warning("RemoveEndpoints() timed out")
182189
}
183190
}
184191

@@ -196,7 +203,14 @@ func (c *Controller) RunKubernetesNamespaces(ch chan struct{}) {
196203

197204
// RunKubernetesService periodically updates the kubernetes service
198205
func (c *Controller) RunKubernetesService(ch chan struct{}) {
199-
wait.Until(func() {
206+
// wait until process is ready
207+
wait.PollImmediateUntil(100*time.Millisecond, func() (bool, error) {
208+
var code int
209+
c.healthClient.Get().AbsPath("/healthz").Do().StatusCode(&code)
210+
return code == http.StatusOK, nil
211+
}, ch)
212+
213+
wait.NonSlidingUntil(func() {
200214
// Service definition is not reconciled after first
201215
// run, ports and type will be corrected only during
202216
// start.

pkg/master/master.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ func (m *Master) InstallLegacyAPI(c *completedConfig, restOptionsGetter generic.
375375

376376
controllerName := "bootstrap-controller"
377377
coreClient := corev1client.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig)
378-
bootstrapController := c.NewBootstrapController(legacyRESTStorage, coreClient, coreClient, coreClient)
378+
bootstrapController := c.NewBootstrapController(legacyRESTStorage, coreClient, coreClient, coreClient, coreClient.RESTClient())
379379
m.GenericAPIServer.AddPostStartHookOrDie(controllerName, bootstrapController.PostStartHook)
380380
m.GenericAPIServer.AddPreShutdownHookOrDie(controllerName, bootstrapController.PreShutdownHook)
381381

pkg/master/reconcilers/reconcilers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type EndpointReconciler interface {
3838
ReconcileEndpoints(serviceName string, ip net.IP, endpointPorts []corev1.EndpointPort, reconcilePorts bool) error
3939
// RemoveEndpoints removes this apiserver's lease.
4040
RemoveEndpoints(serviceName string, ip net.IP, endpointPorts []corev1.EndpointPort) error
41-
// StopReonciling turns any later ReconcileEndpoints call into a noop.
41+
// StopReconciling turns any later ReconcileEndpoints call into a noop.
4242
StopReconciling()
4343
}
4444

test/integration/master/synthetic_master_test.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,16 @@ func TestKubernetesService(t *testing.T) {
103103
_, _, closeFn := framework.RunAMaster(config)
104104
defer closeFn()
105105
coreClient := clientset.NewForConfigOrDie(config.GenericConfig.LoopbackClientConfig)
106-
if _, err := coreClient.Core().Services(metav1.NamespaceDefault).Get("kubernetes", metav1.GetOptions{}); err != nil {
107-
t.Fatalf("Expected kubernetes service to exists, got: %v", err)
106+
err := wait.PollImmediate(time.Millisecond*100, wait.ForeverTestTimeout, func() (bool, error) {
107+
if _, err := coreClient.Core().Services(metav1.NamespaceDefault).Get("kubernetes", metav1.GetOptions{}); err != nil && errors.IsNotFound(err) {
108+
return false, nil
109+
} else if err != nil {
110+
return false, err
111+
}
112+
return true, nil
113+
})
114+
if err != nil {
115+
t.Fatalf("Expected kubernetes service to exist, got: %v", err)
108116
}
109117
}
110118

0 commit comments

Comments
 (0)