Skip to content

Commit d5a0709

Browse files
committed
UVIP: fix incorrect handling of a routable request
1 parent 55f9657 commit d5a0709

File tree

2 files changed

+48
-23
lines changed

2 files changed

+48
-23
lines changed

staging/src/k8s.io/apiserver/pkg/util/peerproxy/peerproxy_handler.go

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,20 +162,24 @@ func (h *peerProxyHandler) WrapHandler(handler http.Handler) http.Handler {
162162
return
163163
}
164164

165-
gv := schema.GroupVersion{Group: gvr.Group, Version: gvr.Version}
166-
167-
if serviceableByResp.errorFetchingAddressFromLease {
168-
klog.ErrorS(err, "error fetching ip and port of remote server while proxying")
169-
responsewriters.ErrorNegotiated(apierrors.NewServiceUnavailable("Error getting ip and port info of the remote server while proxying"), h.serializer, gv, w, r)
170-
return
171-
}
172-
173-
// no apiservers were found that could serve the request, pass request to
174-
// next handler, that should eventually serve 404
165+
// no peer endpoints found could mean one of the following things:
166+
// 1. apiservers were found in storage version informer but either they had no endpoint
167+
// lease or their endpoint lease had invalid hostport information. Serve 503 in this case.
168+
// 2. no apiservers were found in storage version informer cache meaning
169+
// this resource is not served by anything in this cluster. Pass request to
170+
// next handler, that should eventually serve 404.
175171

176172
// TODO: maintain locally serviceable GVRs somewhere so that we dont have to
177173
// consult the storageversion-informed map for those
178174
if len(serviceableByResp.peerEndpoints) == 0 {
175+
gv := schema.GroupVersion{Group: gvr.Group, Version: gvr.Version}
176+
177+
if serviceableByResp.errorFetchingAddressFromLease {
178+
klog.ErrorS(err, "error fetching ip and port of remote server while proxying")
179+
responsewriters.ErrorNegotiated(apierrors.NewServiceUnavailable("Error getting ip and port info of the remote server while proxying"), h.serializer, gv, w, r)
180+
return
181+
}
182+
179183
klog.Errorf(fmt.Sprintf("GVR %v is not served by anything in this cluster", gvr))
180184
handler.ServeHTTP(w, r)
181185
return
@@ -203,7 +207,6 @@ func (h *peerProxyHandler) findServiceableByServers(gvr schema.GroupVersionResou
203207
apiservers.Range(func(key, value interface{}) bool {
204208
apiserverKey := key.(string)
205209
if apiserverKey == localAPIServerId {
206-
response.errorFetchingAddressFromLease = true
207210
response.locallyServiceable = true
208211
// stop iteration
209212
return false
@@ -229,7 +232,10 @@ func (h *peerProxyHandler) findServiceableByServers(gvr schema.GroupVersionResou
229232
return true
230233
})
231234

232-
response.peerEndpoints = peerServerEndpoints
235+
if len(peerServerEndpoints) > 0 {
236+
response.errorFetchingAddressFromLease = false
237+
response.peerEndpoints = peerServerEndpoints
238+
}
233239
return response, nil
234240
}
235241

staging/src/k8s.io/apiserver/pkg/util/peerproxy/peerproxy_handler_test.go

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ const (
5959
)
6060

6161
type FakeSVMapData struct {
62-
gvr schema.GroupVersionResource
63-
serverId string
62+
gvr schema.GroupVersionResource
63+
serverIds []string
6464
}
6565

6666
type reconciler struct {
@@ -116,7 +116,7 @@ func TestPeerProxy(t *testing.T) {
116116
Group: "core",
117117
Version: "bar",
118118
Resource: "baz"},
119-
serverId: ""},
119+
serverIds: []string{}},
120120
},
121121
{
122122
desc: "503 if no endpoint fetched from lease",
@@ -128,7 +128,7 @@ func TestPeerProxy(t *testing.T) {
128128
Group: "core",
129129
Version: "foo",
130130
Resource: "bar"},
131-
serverId: remoteServerId},
131+
serverIds: []string{remoteServerId}},
132132
},
133133
{
134134
desc: "200 if locally serviceable",
@@ -140,7 +140,7 @@ func TestPeerProxy(t *testing.T) {
140140
Group: "core",
141141
Version: "foo",
142142
Resource: "bar"},
143-
serverId: localServerId},
143+
serverIds: []string{localServerId}},
144144
},
145145
{
146146
desc: "503 unreachable peer bind address",
@@ -152,7 +152,7 @@ func TestPeerProxy(t *testing.T) {
152152
Group: "core",
153153
Version: "foo",
154154
Resource: "bar"},
155-
serverId: remoteServerId},
155+
serverIds: []string{remoteServerId}},
156156
reconcilerConfig: reconciler{
157157
do: true,
158158
publicIP: "1.2.3.4",
@@ -177,7 +177,7 @@ func TestPeerProxy(t *testing.T) {
177177
Group: "core",
178178
Version: "foo",
179179
Resource: "bar"},
180-
serverId: remoteServerId},
180+
serverIds: []string{remoteServerId}},
181181
reconcilerConfig: reconciler{
182182
do: true,
183183
publicIP: "1.2.3.4",
@@ -192,6 +192,23 @@ func TestPeerProxy(t *testing.T) {
192192
apiserver_rerouted_request_total{code="503"} 2
193193
`,
194194
},
195+
{
196+
desc: "503 if one apiserver's endpoint lease wasnt found but another valid (unreachable) apiserver was found",
197+
requestPath: "/api/foo/bar",
198+
expectedStatus: http.StatusServiceUnavailable,
199+
informerFinishedSync: true,
200+
svdata: FakeSVMapData{
201+
gvr: schema.GroupVersionResource{
202+
Group: "core",
203+
Version: "foo",
204+
Resource: "bar"},
205+
serverIds: []string{"aggregated-apiserver", remoteServerId}},
206+
reconcilerConfig: reconciler{
207+
do: true,
208+
publicIP: "1.2.3.4",
209+
serverId: remoteServerId,
210+
},
211+
},
195212
}
196213

197214
metrics.Register()
@@ -290,16 +307,18 @@ func newFakePeerProxyHandler(informerFinishedSync bool, reconciler reconcilers.P
290307
}
291308
ppI := NewPeerProxyHandler(informerFactory, storageversion.NewDefaultManager(), proxyRoundTripper, id, reconciler, s)
292309
if testDataExists(svdata.gvr) {
293-
ppI.addToStorageVersionMap(svdata.gvr, svdata.serverId)
310+
ppI.addToStorageVersionMap(svdata.gvr, svdata.serverIds)
294311
}
295312
return ppI, nil
296313
}
297314

298-
func (h *peerProxyHandler) addToStorageVersionMap(gvr schema.GroupVersionResource, serverId string) {
315+
func (h *peerProxyHandler) addToStorageVersionMap(gvr schema.GroupVersionResource, serverIds []string) {
299316
apiserversi, _ := h.svMap.LoadOrStore(gvr, &sync.Map{})
300317
apiservers := apiserversi.(*sync.Map)
301-
if serverId != "" {
302-
apiservers.Store(serverId, true)
318+
for _, serverID := range serverIds {
319+
if serverID != "" {
320+
apiservers.Store(serverID, true)
321+
}
303322
}
304323
}
305324

0 commit comments

Comments
 (0)