Skip to content

Commit 61ecdba

Browse files
authored
Merge pull request kubernetes#82289 from robscott/endpointslice-fixes
Fixing bugs related to Endpoint Slices
2 parents c4c6467 + 8f9483d commit 61ecdba

File tree

22 files changed

+132
-78
lines changed

22 files changed

+132
-78
lines changed

cmd/kube-controller-manager/app/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ go_library(
112112
"//pkg/volume/util:go_default_library",
113113
"//pkg/volume/vsphere_volume:go_default_library",
114114
"//staging/src/k8s.io/api/core/v1:go_default_library",
115+
"//staging/src/k8s.io/api/discovery/v1alpha1:go_default_library",
115116
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
116117
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
117118
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",

cmd/kube-controller-manager/app/discovery.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@ package app
2323
import (
2424
"net/http"
2525

26-
"k8s.io/apimachinery/pkg/runtime/schema"
26+
discoveryv1alpha1 "k8s.io/api/discovery/v1alpha1"
27+
"k8s.io/klog"
2728
endpointslicecontroller "k8s.io/kubernetes/pkg/controller/endpointslice"
2829
)
2930

3031
func startEndpointSliceController(ctx ControllerContext) (http.Handler, bool, error) {
31-
if !ctx.AvailableResources[schema.GroupVersionResource{Group: "discovery", Version: "v1alpha1", Resource: "endpointslices"}] {
32+
if !ctx.AvailableResources[discoveryv1alpha1.SchemeGroupVersion.WithResource("endpointslices")] {
33+
klog.Warningf("Not starting endpointslice-controller, discovery.k8s.io/v1alpha1 resources are not available")
3234
return nil, false, nil
3335
}
3436

pkg/apis/discovery/validation/validation.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,14 @@ var (
3636
maxEndpoints = 1000
3737
)
3838

39+
// ValidateEndpointSliceName can be used to check whether the given endpoint
40+
// slice name is valid. Prefix indicates this name will be used as part of
41+
// generation, in which case trailing dashes are allowed.
42+
var ValidateEndpointSliceName = apimachineryvalidation.NameIsDNSSubdomain
43+
3944
// ValidateEndpointSlice validates an EndpointSlice.
4045
func ValidateEndpointSlice(endpointSlice *discovery.EndpointSlice) field.ErrorList {
41-
validateEndpointSliceName := apimachineryvalidation.NameIsDNSSubdomain
42-
allErrs := apivalidation.ValidateObjectMeta(&endpointSlice.ObjectMeta, true, validateEndpointSliceName, field.NewPath("metadata"))
46+
allErrs := apivalidation.ValidateObjectMeta(&endpointSlice.ObjectMeta, true, ValidateEndpointSliceName, field.NewPath("metadata"))
4347

4448
addrType := discovery.AddressType("")
4549
if endpointSlice.AddressType == nil {

pkg/controller/.import-restrictions

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@
188188
"k8s.io/kubernetes/pkg/apis/core/v1",
189189
"k8s.io/kubernetes/pkg/apis/core/v1/helper",
190190
"k8s.io/kubernetes/pkg/apis/core/validation",
191+
"k8s.io/kubernetes/pkg/apis/discovery",
192+
"k8s.io/kubernetes/pkg/apis/discovery/validation",
191193
"k8s.io/kubernetes/pkg/cloudprovider",
192194
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce",
193195
"k8s.io/kubernetes/pkg/controller",

pkg/controller/endpointslice/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ go_library(
1313
deps = [
1414
"//pkg/api/v1/pod:go_default_library",
1515
"//pkg/apis/core:go_default_library",
16+
"//pkg/apis/discovery/validation:go_default_library",
1617
"//pkg/controller:go_default_library",
1718
"//pkg/controller/util/endpoint:go_default_library",
1819
"//pkg/util/hash:go_default_library",

pkg/controller/endpointslice/endpointslice_controller.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"time"
2222

2323
v1 "k8s.io/api/core/v1"
24+
discovery "k8s.io/api/discovery/v1alpha1"
2425
apierrors "k8s.io/apimachinery/pkg/api/errors"
2526
"k8s.io/apimachinery/pkg/labels"
2627
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@@ -42,10 +43,6 @@ import (
4243
)
4344

4445
const (
45-
// serviceNameLabel is used to indicate the name of a Kubernetes service
46-
// associated with an EndpointSlice.
47-
serviceNameLabel = "kubernetes.io/service-name"
48-
4946
// maxRetries is the number of times a service will be retried before it is
5047
// dropped out of the queue. Any sync error, such as a failure to create or
5148
// update an EndpointSlice could trigger a retry. With the current
@@ -276,7 +273,7 @@ func (c *Controller) syncService(key string) error {
276273
return err
277274
}
278275

279-
esLabelSelector := labels.Set(map[string]string{serviceNameLabel: service.Name}).AsSelectorPreValidated()
276+
esLabelSelector := labels.Set(map[string]string{discovery.LabelServiceName: service.Name}).AsSelectorPreValidated()
280277
endpointSlices, err := c.endpointSliceLister.EndpointSlices(service.Namespace).List(esLabelSelector)
281278

282279
if err != nil {

pkg/controller/endpointslice/endpointslice_controller_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func TestSyncServiceWithSelector(t *testing.T) {
108108
assert.Len(t, sliceList.Items, 1, "Expected 1 endpoint slices")
109109
slice := sliceList.Items[0]
110110
assert.Regexp(t, "^"+serviceName, slice.Name)
111-
assert.Equal(t, serviceName, slice.Labels[serviceNameLabel])
111+
assert.Equal(t, serviceName, slice.Labels[discovery.LabelServiceName])
112112
assert.EqualValues(t, []discovery.EndpointPort{}, slice.Ports)
113113
assert.EqualValues(t, []discovery.Endpoint{}, slice.Endpoints)
114114
assert.NotEmpty(t, slice.Annotations["endpoints.kubernetes.io/last-change-trigger-time"])
@@ -189,11 +189,11 @@ func TestSyncServiceEndpointSliceSelection(t *testing.T) {
189189

190190
// 3 slices, 2 with matching labels for our service
191191
endpointSlices := []*discovery.EndpointSlice{{
192-
ObjectMeta: metav1.ObjectMeta{Name: "matching-1", Namespace: ns, Labels: map[string]string{serviceNameLabel: serviceName}},
192+
ObjectMeta: metav1.ObjectMeta{Name: "matching-1", Namespace: ns, Labels: map[string]string{discovery.LabelServiceName: serviceName}},
193193
}, {
194-
ObjectMeta: metav1.ObjectMeta{Name: "matching-2", Namespace: ns, Labels: map[string]string{serviceNameLabel: serviceName}},
194+
ObjectMeta: metav1.ObjectMeta{Name: "matching-2", Namespace: ns, Labels: map[string]string{discovery.LabelServiceName: serviceName}},
195195
}, {
196-
ObjectMeta: metav1.ObjectMeta{Name: "not-matching-1", Namespace: ns, Labels: map[string]string{serviceNameLabel: "something-else"}},
196+
ObjectMeta: metav1.ObjectMeta{Name: "not-matching-1", Namespace: ns, Labels: map[string]string{discovery.LabelServiceName: "something-else"}},
197197
}}
198198

199199
// need to add them to both store and fake clientset

pkg/controller/endpointslice/reconciler_test.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"github.com/stretchr/testify/assert"
2424

2525
corev1 "k8s.io/api/core/v1"
26-
v1 "k8s.io/api/core/v1"
2726
discovery "k8s.io/api/discovery/v1alpha1"
2827
apiequality "k8s.io/apimachinery/pkg/api/equality"
2928
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -52,7 +51,7 @@ func TestReconcileEmpty(t *testing.T) {
5251
assert.Len(t, slices, 1, "Expected 1 endpoint slices")
5352

5453
assert.Regexp(t, "^"+svc.Name, slices[0].Name)
55-
assert.Equal(t, svc.Name, slices[0].Labels[serviceNameLabel])
54+
assert.Equal(t, svc.Name, slices[0].Labels[discovery.LabelServiceName])
5655
assert.EqualValues(t, []discovery.EndpointPort{}, slices[0].Ports)
5756
assert.EqualValues(t, []discovery.Endpoint{}, slices[0].Endpoints)
5857
}
@@ -83,7 +82,7 @@ func TestReconcile1Pod(t *testing.T) {
8382
slices := fetchEndpointSlices(t, client, namespace)
8483
assert.Len(t, slices, 1, "Expected 1 endpoint slices")
8584
assert.Regexp(t, "^"+svc.Name, slices[0].Name)
86-
assert.Equal(t, svc.Name, slices[0].Labels[serviceNameLabel])
85+
assert.Equal(t, svc.Name, slices[0].Labels[discovery.LabelServiceName])
8786
assert.Equal(t, slices[0].Annotations, map[string]string{
8887
"endpoints.kubernetes.io/last-change-trigger-time": triggerTime.Format(time.RFC3339Nano),
8988
})
@@ -125,7 +124,7 @@ func TestReconcile1EndpointSlice(t *testing.T) {
125124
assert.Len(t, slices, 1, "Expected 1 endpoint slices")
126125

127126
assert.Regexp(t, "^"+svc.Name, slices[0].Name)
128-
assert.Equal(t, svc.Name, slices[0].Labels[serviceNameLabel])
127+
assert.Equal(t, svc.Name, slices[0].Labels[discovery.LabelServiceName])
129128
assert.EqualValues(t, []discovery.EndpointPort{}, slices[0].Ports)
130129
assert.EqualValues(t, []discovery.Endpoint{}, slices[0].Endpoints)
131130
}
@@ -362,9 +361,9 @@ func TestReconcileEndpointSlicesUpdatePacking(t *testing.T) {
362361
// ensure that endpoints in each slice will be marked for update.
363362
for i, pod := range pods {
364363
if i%10 == 0 {
365-
pod.Status.Conditions = []v1.PodCondition{{
366-
Type: v1.PodReady,
367-
Status: v1.ConditionFalse,
364+
pod.Status.Conditions = []corev1.PodCondition{{
365+
Type: corev1.PodReady,
366+
Status: corev1.ConditionFalse,
368367
}}
369368
}
370369
}
@@ -397,10 +396,10 @@ func TestReconcileEndpointSlicesNamedPorts(t *testing.T) {
397396

398397
svc := corev1.Service{
399398
ObjectMeta: metav1.ObjectMeta{Name: "named-port-example", Namespace: namespace},
400-
Spec: v1.ServiceSpec{
401-
Ports: []v1.ServicePort{{
399+
Spec: corev1.ServiceSpec{
400+
Ports: []corev1.ServicePort{{
402401
TargetPort: portNameIntStr,
403-
Protocol: v1.ProtocolTCP,
402+
Protocol: corev1.ProtocolTCP,
404403
}},
405404
Selector: map[string]string{"foo": "bar"},
406405
},
@@ -412,10 +411,10 @@ func TestReconcileEndpointSlicesNamedPorts(t *testing.T) {
412411
ready := !(i%3 == 0)
413412
portOffset := i % 5
414413
pod := newPod(i, namespace, ready, 1)
415-
pod.Spec.Containers[0].Ports = []v1.ContainerPort{{
414+
pod.Spec.Containers[0].Ports = []corev1.ContainerPort{{
416415
Name: portNameIntStr.StrVal,
417416
ContainerPort: int32(8080 + portOffset),
418-
Protocol: v1.ProtocolTCP,
417+
Protocol: corev1.ProtocolTCP,
419418
}}
420419
pods = append(pods, pod)
421420
}
@@ -433,7 +432,7 @@ func TestReconcileEndpointSlicesNamedPorts(t *testing.T) {
433432
expectUnorderedSlicesWithLengths(t, fetchedSlices, []int{60, 60, 60, 60, 60})
434433

435434
// generate data structures for expected slice ports and address types
436-
protoTCP := v1.ProtocolTCP
435+
protoTCP := corev1.ProtocolTCP
437436
ipAddressType := discovery.AddressTypeIP
438437
expectedSlices := []discovery.EndpointSlice{}
439438
for i := range fetchedSlices {

pkg/controller/endpointslice/utils.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"k8s.io/klog"
3333
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
3434
api "k8s.io/kubernetes/pkg/apis/core"
35+
"k8s.io/kubernetes/pkg/apis/discovery/validation"
3536
"k8s.io/kubernetes/pkg/util/hash"
3637
)
3738

@@ -158,8 +159,8 @@ func newEndpointSlice(service *corev1.Service, endpointMeta *endpointMeta) *disc
158159
ownerRef := metav1.NewControllerRef(service, gvk)
159160
return &discovery.EndpointSlice{
160161
ObjectMeta: metav1.ObjectMeta{
161-
Labels: map[string]string{serviceNameLabel: service.Name},
162-
GenerateName: fmt.Sprintf("%s.", service.Name),
162+
Labels: map[string]string{discovery.LabelServiceName: service.Name},
163+
GenerateName: getEndpointSlicePrefix(service.Name),
163164
OwnerReferences: []metav1.OwnerReference{*ownerRef},
164165
Namespace: service.Namespace,
165166
},
@@ -169,6 +170,16 @@ func newEndpointSlice(service *corev1.Service, endpointMeta *endpointMeta) *disc
169170
}
170171
}
171172

173+
// getEndpointSlicePrefix returns a suitable prefix for an EndpointSlice name.
174+
func getEndpointSlicePrefix(serviceName string) string {
175+
// use the dash (if the name isn't too long) to make the pod name a bit prettier
176+
prefix := fmt.Sprintf("%s-", serviceName)
177+
if len(validation.ValidateEndpointSliceName(prefix, true)) != 0 {
178+
prefix = serviceName
179+
}
180+
return prefix
181+
}
182+
172183
// boolPtrChanged returns true if a set of bool pointers have different values.
173184
func boolPtrChanged(ptr1, ptr2 *bool) bool {
174185
if (ptr1 == nil) != (ptr2 == nil) {

pkg/controller/endpointslice/utils_test.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"time"
2323

2424
"github.com/stretchr/testify/assert"
25-
corev1 "k8s.io/api/core/v1"
2625
v1 "k8s.io/api/core/v1"
2726
discovery "k8s.io/api/discovery/v1alpha1"
2827
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -58,8 +57,8 @@ func TestNewEndpointSlice(t *testing.T) {
5857

5958
expectedSlice := discovery.EndpointSlice{
6059
ObjectMeta: metav1.ObjectMeta{
61-
Labels: map[string]string{serviceNameLabel: service.Name},
62-
GenerateName: fmt.Sprintf("%s.", service.Name),
60+
Labels: map[string]string{discovery.LabelServiceName: service.Name},
61+
GenerateName: fmt.Sprintf("%s-", service.Name),
6362
OwnerReferences: []metav1.OwnerReference{*ownerRef},
6463
Namespace: service.Namespace,
6564
},
@@ -81,7 +80,7 @@ func TestPodToEndpoint(t *testing.T) {
8180

8281
multiIPPod.Status.PodIPs = []v1.PodIP{{IP: "1.2.3.4"}, {IP: "1234::5678:0000:0000:9abc:def0"}}
8382

84-
node1 := &corev1.Node{
83+
node1 := &v1.Node{
8584
ObjectMeta: metav1.ObjectMeta{
8685
Name: readyPod.Spec.NodeName,
8786
Labels: map[string]string{
@@ -288,14 +287,14 @@ func newClientset() *fake.Clientset {
288287
return client
289288
}
290289

291-
func newServiceAndendpointMeta(name, namespace string) (corev1.Service, endpointMeta) {
290+
func newServiceAndendpointMeta(name, namespace string) (v1.Service, endpointMeta) {
292291
portNum := int32(80)
293292
portNameIntStr := intstr.IntOrString{
294293
Type: intstr.Int,
295294
IntVal: portNum,
296295
}
297296

298-
svc := corev1.Service{
297+
svc := v1.Service{
299298
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace},
300299
Spec: v1.ServiceSpec{
301300
Ports: []v1.ServicePort{{
@@ -317,7 +316,7 @@ func newServiceAndendpointMeta(name, namespace string) (corev1.Service, endpoint
317316
return svc, endpointMeta
318317
}
319318

320-
func newEmptyEndpointSlice(n int, namespace string, endpointMeta endpointMeta, svc corev1.Service) *discovery.EndpointSlice {
319+
func newEmptyEndpointSlice(n int, namespace string, endpointMeta endpointMeta, svc v1.Service) *discovery.EndpointSlice {
321320
return &discovery.EndpointSlice{
322321
ObjectMeta: metav1.ObjectMeta{
323322
Name: fmt.Sprintf("%s.%d", svc.Name, n),

0 commit comments

Comments
 (0)