From ef248bba4839c8c37e23018a1231fab898df6361 Mon Sep 17 00:00:00 2001 From: Mike Beaumont Date: Tue, 21 May 2024 15:03:03 +0200 Subject: [PATCH 01/10] feat(MeshService): handle headless Services Signed-off-by: Mike Beaumont --- .../kuma/crds/kuma.io_meshservices.yaml | 5 + .../raw/crds/kuma.io_meshservices.yaml | 5 + .../meshservice/api/v1alpha1/meshservice.go | 13 + .../apis/meshservice/api/v1alpha1/schema.yaml | 5 + .../api/v1alpha1/zz_generated.deepcopy.go | 20 ++ .../k8s/crd/kuma.io_meshservices.yaml | 5 + .../policies/core/xds/meshroute/listeners.go | 3 + .../k8s/controllers/meshservice_controller.go | 249 +++++++++++++++--- pkg/util/k8s/name_converter.go | 11 + pkg/xds/topology/outbound.go | 3 + 10 files changed, 282 insertions(+), 37 deletions(-) diff --git a/deployments/charts/kuma/crds/kuma.io_meshservices.yaml b/deployments/charts/kuma/crds/kuma.io_meshservices.yaml index 535af7054889..3e1f5f86c68e 100644 --- a/deployments/charts/kuma/crds/kuma.io_meshservices.yaml +++ b/deployments/charts/kuma/crds/kuma.io_meshservices.yaml @@ -65,6 +65,11 @@ spec: x-kubernetes-list-type: map selector: properties: + dataplaneRef: + properties: + name: + type: string + type: object dataplaneTags: additionalProperties: type: string diff --git a/docs/generated/raw/crds/kuma.io_meshservices.yaml b/docs/generated/raw/crds/kuma.io_meshservices.yaml index 535af7054889..3e1f5f86c68e 100644 --- a/docs/generated/raw/crds/kuma.io_meshservices.yaml +++ b/docs/generated/raw/crds/kuma.io_meshservices.yaml @@ -65,6 +65,11 @@ spec: x-kubernetes-list-type: map selector: properties: + dataplaneRef: + properties: + name: + type: string + type: object dataplaneTags: additionalProperties: type: string diff --git a/pkg/core/resources/apis/meshservice/api/v1alpha1/meshservice.go b/pkg/core/resources/apis/meshservice/api/v1alpha1/meshservice.go index 5973062a593e..990b5cfffa13 100644 --- a/pkg/core/resources/apis/meshservice/api/v1alpha1/meshservice.go +++ b/pkg/core/resources/apis/meshservice/api/v1alpha1/meshservice.go @@ -11,6 +11,19 @@ type DataplaneTags map[string]string type Selector struct { DataplaneTags DataplaneTags `json:"dataplaneTags,omitempty"` + DataplaneRef *DataplaneRef `json:"dataplaneRef,omitempty"` +} + +type DataplaneRef struct { + Name string `json:"name,omitempty"` +} + +func (r *DataplaneRef) Matches() bool { + if r == nil { + return false + } + + return false } type Port struct { diff --git a/pkg/core/resources/apis/meshservice/api/v1alpha1/schema.yaml b/pkg/core/resources/apis/meshservice/api/v1alpha1/schema.yaml index 315decb779a0..4df6fe4e83d3 100644 --- a/pkg/core/resources/apis/meshservice/api/v1alpha1/schema.yaml +++ b/pkg/core/resources/apis/meshservice/api/v1alpha1/schema.yaml @@ -40,6 +40,11 @@ properties: x-kubernetes-list-type: map selector: properties: + dataplaneRef: + properties: + name: + type: string + type: object dataplaneTags: additionalProperties: type: string diff --git a/pkg/core/resources/apis/meshservice/api/v1alpha1/zz_generated.deepcopy.go b/pkg/core/resources/apis/meshservice/api/v1alpha1/zz_generated.deepcopy.go index 5d3ba1654cb3..30a373975e4a 100644 --- a/pkg/core/resources/apis/meshservice/api/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/core/resources/apis/meshservice/api/v1alpha1/zz_generated.deepcopy.go @@ -21,6 +21,21 @@ func (in *Address) DeepCopy() *Address { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataplaneRef) DeepCopyInto(out *DataplaneRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataplaneRef. +func (in *DataplaneRef) DeepCopy() *DataplaneRef { + if in == nil { + return nil + } + out := new(DataplaneRef) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in DataplaneTags) DeepCopyInto(out *DataplaneTags) { { @@ -115,6 +130,11 @@ func (in *Selector) DeepCopyInto(out *Selector) { (*out)[key] = val } } + if in.DataplaneRef != nil { + in, out := &in.DataplaneRef, &out.DataplaneRef + *out = new(DataplaneRef) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Selector. diff --git a/pkg/core/resources/apis/meshservice/k8s/crd/kuma.io_meshservices.yaml b/pkg/core/resources/apis/meshservice/k8s/crd/kuma.io_meshservices.yaml index 535af7054889..3e1f5f86c68e 100644 --- a/pkg/core/resources/apis/meshservice/k8s/crd/kuma.io_meshservices.yaml +++ b/pkg/core/resources/apis/meshservice/k8s/crd/kuma.io_meshservices.yaml @@ -65,6 +65,11 @@ spec: x-kubernetes-list-type: map selector: properties: + dataplaneRef: + properties: + name: + type: string + type: object dataplaneTags: additionalProperties: type: string diff --git a/pkg/plugins/policies/core/xds/meshroute/listeners.go b/pkg/plugins/policies/core/xds/meshroute/listeners.go index ef90803b5323..1dffbfc7a918 100644 --- a/pkg/plugins/policies/core/xds/meshroute/listeners.go +++ b/pkg/plugins/policies/core/xds/meshroute/listeners.go @@ -71,6 +71,9 @@ func CollectServices( for _, outbound := range proxy.Dataplane.Spec.GetNetworking().GetOutbounds() { oface := proxy.Dataplane.Spec.Networking.ToOutboundInterface(outbound) if outbound.BackendRef != nil { + if outbound.GetAddress() == proxy.Dataplane.Spec.GetNetworking().GetAddress() { + continue + } ms, ok := meshCtx.MeshServiceByName[outbound.BackendRef.Name] if !ok { // we want to ignore service which is not found. Logging might be excessive here. diff --git a/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go b/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go index c85da58a7538..281be8da5aed 100644 --- a/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go +++ b/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go @@ -2,11 +2,13 @@ package controllers import ( "context" + "fmt" "maps" "github.com/go-logr/logr" "github.com/pkg/errors" kube_core "k8s.io/api/core/v1" + kube_discovery "k8s.io/api/discovery/v1" kube_apierrs "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" kube_runtime "k8s.io/apimachinery/pkg/runtime" @@ -28,6 +30,7 @@ import ( "github.com/kumahq/kuma/pkg/plugins/resources/k8s/native/api/v1alpha1" "github.com/kumahq/kuma/pkg/plugins/runtime/k8s/metadata" "github.com/kumahq/kuma/pkg/plugins/runtime/k8s/util" + "github.com/kumahq/kuma/pkg/util/k8s" "github.com/kumahq/kuma/pkg/util/pointer" ) @@ -109,22 +112,203 @@ func (r *MeshServiceReconciler) Reconcile(ctx context.Context, req kube_ctrl.Req return kube_ctrl.Result{}, err } - ms := &meshservice_k8s.MeshService{ - ObjectMeta: v1.ObjectMeta{ - Name: svc.GetName(), - Namespace: svc.GetNamespace(), + if svc.Spec.ClusterIP != kube_core.ClusterIPNone { + name := kube_client.ObjectKeyFromObject(svc) + op, err := r.manageMeshService( + ctx, + svc, + mesh, + r.setFromClusterIPSvc, + name, + ) + if err != nil { + return kube_ctrl.Result{}, err + } + switch op { + case kube_controllerutil.OperationResultCreated: + r.EventRecorder.Eventf(svc, kube_core.EventTypeNormal, CreatedMeshServiceReason, "Created Kuma MeshService: %s", name.Name) + case kube_controllerutil.OperationResultUpdated: + r.EventRecorder.Eventf(svc, kube_core.EventTypeNormal, UpdatedMeshServiceReason, "Updated Kuma MeshService: %s", name.Name) + } + + return kube_ctrl.Result{}, nil + } + + trackedPodEndpoints := map[kube_types.NamespacedName]struct{}{} + meshServices := &meshservice_k8s.MeshServiceList{} + if err := r.List( + ctx, + meshServices, + kube_client.MatchingLabels(map[string]string{ + metadata.KumaSerivceName: svc.Name, + }), + ); err != nil { + return kube_ctrl.Result{}, errors.Wrap(err, "unable to list MeshServices for headless Service") + } + for _, svc := range meshServices.Items { + if len(svc.GetOwnerReferences()) == 0 { + continue + } + owner := svc.GetOwnerReferences()[0] + // TODO check kinds of owner + trackedPodEndpoints[kube_types.NamespacedName{Namespace: svc.Namespace, Name: owner.Name}] = struct{}{} + } + + endpointSlices := &kube_discovery.EndpointSliceList{} + if err := r.List( + ctx, + endpointSlices, + kube_client.InNamespace(svc.Namespace), + kube_client.MatchingLabels(map[string]string{ + kube_discovery.LabelServiceName: svc.Name, + }), + ); err != nil { + return kube_ctrl.Result{}, errors.Wrap(err, "unable to list EndpointSlices for headless Service") + } + + servicePodEndpoints := map[kube_types.NamespacedName]kube_discovery.Endpoint{} + // We need to look at our EndpointSlice to see which Pods this headless + // service points to + var created, updated int + for _, slice := range endpointSlices.Items { + for _, endpoint := range slice.Endpoints { + if endpoint.TargetRef == nil || + endpoint.TargetRef.Kind != "Pod" || + (endpoint.TargetRef.APIVersion != kube_core.SchemeGroupVersion.String() && + endpoint.TargetRef.APIVersion != "") { + continue + } + servicePodEndpoints[kube_types.NamespacedName{Name: endpoint.TargetRef.Name, Namespace: endpoint.TargetRef.Namespace}] = endpoint + } + } + + log.V(1).Info("", "MeshServiceEndpoints", trackedPodEndpoints, "EndpointSliceEndpoints", servicePodEndpoints) + + // Delete trackedPodEndpoints - servicePodEndpoints + for tracked := range trackedPodEndpoints { + if _, ok := servicePodEndpoints[tracked]; ok { + continue + } + delete(trackedPodEndpoints, tracked) + ms := meshservice_k8s.MeshService{ + ObjectMeta: v1.ObjectMeta{ + Namespace: tracked.Namespace, + Name: tracked.Name, + }, + } + if err := r.Delete(ctx, &ms); err != nil && !kube_apierrs.IsNotFound(err) { + return kube_ctrl.Result{}, errors.Wrap(err, "unable to delete MeshService tracking headless Service endpoint") + } + } + + for current, endpoint := range servicePodEndpoints { + // Our name is unique depending on the service identity and pod name + canonicalNameHash := k8s.NewHasher() + canonicalNameHash.Write([]byte(svc.Name)) + canonicalNameHash.Write([]byte(svc.Namespace)) + canonicalName := fmt.Sprintf("%s-%s", current.Name, k8s.HashToString(canonicalNameHash)) + op, err := r.manageMeshService( + ctx, + svc, + mesh, + r.setFromPodAndHeadlessSvc(endpoint), + kube_types.NamespacedName{Namespace: current.Namespace, Name: canonicalName}, + ) + if err != nil { + return kube_ctrl.Result{}, errors.Wrap(err, "unable to create/update MeshService for headless Service") + } + switch op { + case kube_controllerutil.OperationResultCreated: + created++ + case kube_controllerutil.OperationResultUpdated: + updated++ + } + } + if created > 0 { + r.EventRecorder.Eventf(svc, kube_core.EventTypeNormal, CreatedMeshServiceReason, "Created %d MeshServices", created) + } + if updated > 0 { + r.EventRecorder.Eventf(svc, kube_core.EventTypeNormal, UpdatedMeshServiceReason, "Updated %d MeshServices", updated) + } + + return kube_ctrl.Result{}, nil +} + +func (r *MeshServiceReconciler) setFromClusterIPSvc(ms *meshservice_k8s.MeshService, svc *kube_core.Service) error { + if ms.ObjectMeta.GetGeneration() != 0 { + if owners := ms.GetOwnerReferences(); len(owners) == 0 || owners[0].UID != svc.GetUID() { + r.EventRecorder.Eventf( + svc, kube_core.EventTypeWarning, FailedToGenerateMeshServiceReason, "MeshService already exists and isn't owned by Service", + ) + return errors.Errorf("MeshService already exists and isn't owned by Service") + } + } + ms.Spec.Selector = meshservice_api.Selector{ + DataplaneTags: svc.Spec.Selector, + } + + ms.Status.VIPs = []meshservice_api.VIP{ + { + IP: svc.Spec.ClusterIP, }, } - operationResult, err := kube_controllerutil.CreateOrUpdate(ctx, r.Client, ms, func() error { + if err := kube_controllerutil.SetOwnerReference(svc, ms, r.Scheme); err != nil { + return errors.Wrap(err, "could not set owner reference") + } + return nil +} + +func (r *MeshServiceReconciler) setFromPodAndHeadlessSvc(endpoint kube_discovery.Endpoint) func(*meshservice_k8s.MeshService, *kube_core.Service) error { + return func(ms *meshservice_k8s.MeshService, svc *kube_core.Service) error { if ms.ObjectMeta.GetGeneration() != 0 { - if owners := ms.GetOwnerReferences(); len(owners) == 0 || owners[0].UID != svc.GetUID() { + if owners := ms.GetOwnerReferences(); len(owners) == 0 || owners[0].UID != endpoint.TargetRef.UID { r.EventRecorder.Eventf( - svc, kube_core.EventTypeWarning, FailedToGenerateMeshServiceReason, "MeshService already exists and isn't owned by Service", + svc, kube_core.EventTypeWarning, FailedToGenerateMeshServiceReason, "MeshService already exists and isn't owned by Pod", ) - return errors.Errorf("MeshService already exists and isn't owned by Service") + return errors.Errorf("MeshService already exists and isn't owned by Pod") } } + ms.Spec.Selector = meshservice_api.Selector{ + DataplaneRef: &meshservice_api.DataplaneRef{ + Name: endpoint.TargetRef.Name, + }, + } + for _, address := range endpoint.Addresses { + ms.Status.VIPs = append(ms.Status.VIPs, + meshservice_api.VIP{ + IP: address, + }) + } + owner := kube_core.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: endpoint.TargetRef.Name, + Namespace: endpoint.TargetRef.Namespace, + UID: endpoint.TargetRef.UID, + }, + } + if err := kube_controllerutil.SetOwnerReference(&owner, ms, r.Scheme); err != nil { + return errors.Wrap(err, "could not set owner reference") + } + return nil + } +} + +func (r *MeshServiceReconciler) manageMeshService( + ctx context.Context, + svc *kube_core.Service, + mesh string, + setSpec func(*meshservice_k8s.MeshService, *kube_core.Service) error, + meshServiceName kube_types.NamespacedName, +) (kube_controllerutil.OperationResult, error) { + ms := &meshservice_k8s.MeshService{ + ObjectMeta: v1.ObjectMeta{ + Name: meshServiceName.Name, + Namespace: meshServiceName.Namespace, + }, + } + + return kube_controllerutil.CreateOrUpdate(ctx, r.Client, ms, func() error { ms.ObjectMeta.Labels = maps.Clone(svc.GetLabels()) if ms.ObjectMeta.Labels == nil { ms.ObjectMeta.Labels = map[string]string{} @@ -135,10 +319,6 @@ func (r *MeshServiceReconciler) Reconcile(ctx context.Context, req kube_ctrl.Req ms.Spec = &meshservice_api.MeshService{} } - ms.Spec.Selector = meshservice_api.Selector{ - DataplaneTags: svc.Spec.Selector, - } - ms.Spec.Ports = []meshservice_api.Port{} for _, port := range svc.Spec.Ports { if port.Protocol != kube_core.ProtocolTCP { @@ -154,27 +334,8 @@ func (r *MeshServiceReconciler) Reconcile(ctx context.Context, req kube_ctrl.Req if ms.Status == nil { ms.Status = &meshservice_api.MeshServiceStatus{} } - ms.Status.VIPs = []meshservice_api.VIP{ - { - IP: svc.Spec.ClusterIP, - }, - } - if err := kube_controllerutil.SetOwnerReference(svc, ms, r.Scheme); err != nil { - return errors.Wrap(err, "could not set owner reference") - } - return nil + return setSpec(ms, svc) }) - if err != nil { - return kube_ctrl.Result{}, err - } - switch operationResult { - case kube_controllerutil.OperationResultCreated: - r.EventRecorder.Eventf(svc, kube_core.EventTypeNormal, CreatedMeshServiceReason, "Created Kuma MeshService: %s", ms.Name) - case kube_controllerutil.OperationResultUpdated: - r.EventRecorder.Eventf(svc, kube_core.EventTypeNormal, UpdatedMeshServiceReason, "Updated Kuma MeshService: %s", ms.Name) - } - log.V(1).Info("mesh service reconciled", "result", operationResult) - return kube_ctrl.Result{}, nil } func (r *MeshServiceReconciler) deleteIfExist(ctx context.Context, key kube_types.NamespacedName) error { @@ -185,7 +346,7 @@ func (r *MeshServiceReconciler) deleteIfExist(ctx context.Context, key kube_type }, } if err := r.Client.Delete(ctx, ms); err != nil && !kube_apierrs.IsNotFound(err) { - return errors.Wrap(err, "could not delete mesh service") + return errors.Wrap(err, "could not delete MeshService") } return nil } @@ -193,13 +354,27 @@ func (r *MeshServiceReconciler) deleteIfExist(ctx context.Context, key kube_type func (r *MeshServiceReconciler) SetupWithManager(mgr kube_ctrl.Manager) error { return kube_ctrl.NewControllerManagedBy(mgr). For(&kube_core.Service{}). - // on Namespace update we reconcile Services in this namespace Watches(&kube_core.Namespace{}, kube_handler.EnqueueRequestsFromMapFunc(NamespaceToServiceMapper(r.Log, mgr.GetClient())), builder.WithPredicates(predicate.LabelChangedPredicate{})). - // on Mesh create or delete reconcile all Services - Watches(&v1alpha1.Mesh{}, kube_handler.EnqueueRequestsFromMapFunc(MeshToMeshService(r.Log, mgr.GetClient())), builder.WithPredicates(CreateOrDeletePredicate{})). + Watches(&v1alpha1.Mesh{}, kube_handler.EnqueueRequestsFromMapFunc(MeshToAllMeshServices(r.Log, mgr.GetClient())), builder.WithPredicates(CreateOrDeletePredicate{})). + Watches(&kube_discovery.EndpointSlice{}, kube_handler.EnqueueRequestsFromMapFunc(EndpointSliceToServicesMapper(r.Log, mgr.GetClient()))). Complete(r) } +func EndpointSliceToServicesMapper(l logr.Logger, client kube_client.Client) kube_handler.MapFunc { + return func(ctx context.Context, obj kube_client.Object) []kube_reconcile.Request { + slice := obj.(*kube_discovery.EndpointSlice) + + svcName, ok := slice.Labels[kube_discovery.LabelServiceName] + if !ok { + return nil + } + req := []kube_reconcile.Request{ + {NamespacedName: kube_types.NamespacedName{Namespace: slice.Namespace, Name: svcName}}, + } + return req + } +} + func NamespaceToServiceMapper(l logr.Logger, client kube_client.Client) kube_handler.MapFunc { l = l.WithName("namespace-to-service-mapper") return func(ctx context.Context, obj kube_client.Object) []kube_reconcile.Request { @@ -218,7 +393,7 @@ func NamespaceToServiceMapper(l logr.Logger, client kube_client.Client) kube_han } } -func MeshToMeshService(l logr.Logger, client kube_client.Client) kube_handler.MapFunc { +func MeshToAllMeshServices(l logr.Logger, client kube_client.Client) kube_handler.MapFunc { l = l.WithName("mesh-to-service-mapper") return func(ctx context.Context, obj kube_client.Object) []kube_reconcile.Request { services := &kube_core.ServiceList{} diff --git a/pkg/util/k8s/name_converter.go b/pkg/util/k8s/name_converter.go index 787f2247a8b8..87d94c3fa3f6 100644 --- a/pkg/util/k8s/name_converter.go +++ b/pkg/util/k8s/name_converter.go @@ -2,9 +2,12 @@ package k8s import ( "fmt" + "hash" + "hash/fnv" "strings" "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/util/rand" ) func CoreNameToK8sName(coreName string) (string, string, error) { @@ -23,3 +26,11 @@ func CoreNameToK8sName(coreName string) (string, string, error) { func K8sNamespacedNameToCoreName(name, namespace string) string { return fmt.Sprintf("%s.%s", name, namespace) } + +func NewHasher() hash.Hash32 { + return fnv.New32a() +} + +func HashToString(h hash.Hash32) string { + return rand.SafeEncodeString(fmt.Sprint(h.Sum32())) +} diff --git a/pkg/xds/topology/outbound.go b/pkg/xds/topology/outbound.go index e7c701287263..bac05197507c 100644 --- a/pkg/xds/topology/outbound.go +++ b/pkg/xds/topology/outbound.go @@ -157,6 +157,9 @@ func fillLocalMeshServices( for _, meshSvc := range meshServices { tagSelector := mesh_proto.TagSelector(meshSvc.Spec.Selector.DataplaneTags) + if meshSvc.Spec.Selector.DataplaneRef != nil { + continue + } for _, inbound := range dpNetworking.GetHealthyInbounds() { if !tagSelector.Matches(inbound.GetTags()) { From f76d011010e6f6aed34d47ee9a0e8827d30ab4b8 Mon Sep 17 00:00:00 2001 From: Mike Beaumont Date: Tue, 21 May 2024 18:07:25 +0200 Subject: [PATCH 02/10] chore: fix variable typo Signed-off-by: Mike Beaumont --- pkg/plugins/runtime/k8s/controllers/meshservice_controller.go | 4 ++-- pkg/plugins/runtime/k8s/metadata/annotations.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go b/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go index 281be8da5aed..e1d971dd44a8 100644 --- a/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go +++ b/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go @@ -140,7 +140,7 @@ func (r *MeshServiceReconciler) Reconcile(ctx context.Context, req kube_ctrl.Req ctx, meshServices, kube_client.MatchingLabels(map[string]string{ - metadata.KumaSerivceName: svc.Name, + metadata.KumaServiceName: svc.Name, }), ); err != nil { return kube_ctrl.Result{}, errors.Wrap(err, "unable to list MeshServices for headless Service") @@ -314,7 +314,7 @@ func (r *MeshServiceReconciler) manageMeshService( ms.ObjectMeta.Labels = map[string]string{} } ms.ObjectMeta.Labels[mesh_proto.MeshTag] = mesh - ms.ObjectMeta.Labels[metadata.KumaSerivceName] = svc.GetName() + ms.ObjectMeta.Labels[metadata.KumaServiceName] = svc.GetName() if ms.Spec == nil { ms.Spec = &meshservice_api.MeshService{} } diff --git a/pkg/plugins/runtime/k8s/metadata/annotations.go b/pkg/plugins/runtime/k8s/metadata/annotations.go index fb457269ec2c..ee3bf2f03846 100644 --- a/pkg/plugins/runtime/k8s/metadata/annotations.go +++ b/pkg/plugins/runtime/k8s/metadata/annotations.go @@ -117,7 +117,7 @@ const ( KumaWaitForDataplaneReady = "kuma.io/wait-for-dataplane-ready" // KumaServiceName points to the Service that a MeshService is derived from - KumaSerivceName = "k8s.kuma.io/service-name" + KumaServiceName = "k8s.kuma.io/service-name" ) var PodAnnotationDeprecations = []Deprecation{ From 3f98a99ce5db53ab09c0a8998a820ff1f0531d3b Mon Sep 17 00:00:00 2001 From: Mike Beaumont Date: Tue, 21 May 2024 18:30:54 +0200 Subject: [PATCH 03/10] chore: fix RBAC Signed-off-by: Mike Beaumont --- deployments/charts/kuma/templates/cp-rbac.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/deployments/charts/kuma/templates/cp-rbac.yaml b/deployments/charts/kuma/templates/cp-rbac.yaml index 60da7d01bae5..2c0145f0c164 100644 --- a/deployments/charts/kuma/templates/cp-rbac.yaml +++ b/deployments/charts/kuma/templates/cp-rbac.yaml @@ -43,6 +43,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: From 946156ca338858c494f380f5d09615c796e0549a Mon Sep 17 00:00:00 2001 From: Mike Beaumont Date: Mon, 27 May 2024 15:36:46 +0200 Subject: [PATCH 04/10] test(MeshService): add headless Service test Signed-off-by: Mike Beaumont --- .../meshservice_controller_test.go | 8 +++- .../meshservice/headless.meshservice.yaml | 30 +++++++++++++ .../meshservice/headless.resources.yaml | 45 +++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml create mode 100644 pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml diff --git a/pkg/plugins/runtime/k8s/controllers/meshservice_controller_test.go b/pkg/plugins/runtime/k8s/controllers/meshservice_controller_test.go index 80d51398a841..d7774ab2ce1d 100644 --- a/pkg/plugins/runtime/k8s/controllers/meshservice_controller_test.go +++ b/pkg/plugins/runtime/k8s/controllers/meshservice_controller_test.go @@ -10,7 +10,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" kube_core "k8s.io/api/core/v1" - kube_errors "k8s.io/apimachinery/pkg/api/errors" + kube_discovery "k8s.io/api/discovery/v1" kube_types "k8s.io/apimachinery/pkg/types" kube_record "k8s.io/client-go/tools/record" kube_ctrl "sigs.k8s.io/controller-runtime" @@ -48,6 +48,8 @@ var _ = Describe("MeshServiceController", func() { obj = &meshservice_k8s.MeshService{} case strings.Contains(yamlObj, "kind: Service"): obj = &kube_core.Service{} + case strings.Contains(yamlObj, "kind: EndpointSlice"): + obj = &kube_discovery.EndpointSlice{} case strings.Contains(yamlObj, "kind: Namespace"): obj = &kube_core.Namespace{} case strings.Contains(yamlObj, "kind: Mesh"): @@ -109,5 +111,9 @@ var _ = Describe("MeshServiceController", func() { inputFile: "05.resources.yaml", outputFile: "05.meshservice.yaml", }), + Entry("service for headless Service", testCase{ + inputFile: "headless.resources.yaml", + outputFile: "headless.meshservice.yaml", + }), ) }) diff --git a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml new file mode 100644 index 000000000000..dae86ab67ee9 --- /dev/null +++ b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml @@ -0,0 +1,30 @@ +items: +- metadata: + creationTimestamp: null + labels: + k8s.kuma.io/service-name: example + kuma.io/mesh: default + name: example-1-87ff74c98 + namespace: demo + ownerReferences: + - apiVersion: v1 + kind: Pod + name: example-1 + uid: 12350sd0fds0f + resourceVersion: "1" + spec: + ports: + - port: 80 + protocol: http + targetPort: 8080 + - port: 443 + protocol: tcp + targetPort: 8443 + selector: + dataplaneRef: + name: example-1 + status: + tls: {} + vips: + - ip: 192.168.0.5 +metadata: {} diff --git a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml new file mode 100644 index 000000000000..95b9935c04df --- /dev/null +++ b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml @@ -0,0 +1,45 @@ +--- +apiVersion: discovery.k8s.io/v1 +kind: EndpointSlice +metadata: + name: example-ip4 + namespace: demo + labels: + kubernetes.io/service-name: example +addressType: IPv4 +endpoints: + - addresses: + - 192.168.0.5 + targetRef: + kind: Pod + name: example-1 + namespace: demo + uid: 12350sd0fds0f +--- +apiVersion: v1 +kind: Service +metadata: + namespace: demo + name: example +spec: + clusterIP: None + ports: + - appProtocol: http + port: 80 + targetPort: 8080 + protocol: TCP + - port: 443 + targetPort: 8443 + protocol: TCP +--- +apiVersion: v1 +kind: Namespace +metadata: + name: demo + labels: + kuma.io/sidecar-injection: enabled +--- +apiVersion: kuma.io/v1alpha1 +kind: Mesh +metadata: + name: default From 5f832bc6cefed171f77cd74e689e2799c5ab2a8b Mon Sep 17 00:00:00 2001 From: Mike Beaumont Date: Tue, 28 May 2024 14:03:11 +0200 Subject: [PATCH 05/10] chore: remove unused code Signed-off-by: Mike Beaumont --- .../apis/meshservice/api/v1alpha1/meshservice.go | 8 -------- .../runtime/k8s/controllers/meshservice_controller.go | 2 -- 2 files changed, 10 deletions(-) diff --git a/pkg/core/resources/apis/meshservice/api/v1alpha1/meshservice.go b/pkg/core/resources/apis/meshservice/api/v1alpha1/meshservice.go index 990b5cfffa13..4054ce275aa8 100644 --- a/pkg/core/resources/apis/meshservice/api/v1alpha1/meshservice.go +++ b/pkg/core/resources/apis/meshservice/api/v1alpha1/meshservice.go @@ -18,14 +18,6 @@ type DataplaneRef struct { Name string `json:"name,omitempty"` } -func (r *DataplaneRef) Matches() bool { - if r == nil { - return false - } - - return false -} - type Port struct { Port uint32 `json:"port"` TargetPort intstr.IntOrString `json:"targetPort,omitempty"` diff --git a/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go b/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go index e1d971dd44a8..f99e2eb16c20 100644 --- a/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go +++ b/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go @@ -182,8 +182,6 @@ func (r *MeshServiceReconciler) Reconcile(ctx context.Context, req kube_ctrl.Req } } - log.V(1).Info("", "MeshServiceEndpoints", trackedPodEndpoints, "EndpointSliceEndpoints", servicePodEndpoints) - // Delete trackedPodEndpoints - servicePodEndpoints for tracked := range trackedPodEndpoints { if _, ok := servicePodEndpoints[tracked]; ok { From 2627cbc4cef4fd39f57c695e6e60ef45d1afdbfe Mon Sep 17 00:00:00 2001 From: Mike Beaumont Date: Tue, 28 May 2024 14:05:33 +0200 Subject: [PATCH 06/10] test(MeshService): add endpoint to headless service case Signed-off-by: Mike Beaumont --- .../meshservice/headless.meshservice.yaml | 30 ++++++++++++++++++- .../meshservice/headless.resources.yaml | 9 +++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml index dae86ab67ee9..adfe30814d5f 100644 --- a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml +++ b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml @@ -10,7 +10,7 @@ items: - apiVersion: v1 kind: Pod name: example-1 - uid: 12350sd0fds0f + uid: example-1-1 resourceVersion: "1" spec: ports: @@ -27,4 +27,32 @@ items: tls: {} vips: - ip: 192.168.0.5 +- metadata: + creationTimestamp: null + labels: + k8s.kuma.io/service-name: example + kuma.io/mesh: default + name: example-2-87ff74c98 + namespace: demo + ownerReferences: + - apiVersion: v1 + kind: Pod + name: example-2 + uid: example-2-1 + resourceVersion: "1" + spec: + ports: + - port: 80 + protocol: http + targetPort: 8080 + - port: 443 + protocol: tcp + targetPort: 8443 + selector: + dataplaneRef: + name: example-2 + status: + tls: {} + vips: + - ip: 192.168.0.6 metadata: {} diff --git a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml index 95b9935c04df..3979cbe250ab 100644 --- a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml +++ b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml @@ -14,7 +14,14 @@ endpoints: kind: Pod name: example-1 namespace: demo - uid: 12350sd0fds0f + uid: example-1-1 + - addresses: + - 192.168.0.6 + targetRef: + kind: Pod + name: example-2 + namespace: demo + uid: example-2-1 --- apiVersion: v1 kind: Service From b41cee76f83799b2226980304e2e866bd2cc7cb9 Mon Sep 17 00:00:00 2001 From: Mike Beaumont Date: Tue, 28 May 2024 14:36:00 +0200 Subject: [PATCH 07/10] fix(MeshService): ensure that we don't try to create a MeshService with too long a name Signed-off-by: Mike Beaumont --- .../k8s/controllers/meshservice_controller.go | 14 +++++++--- .../meshservice/headless.meshservice.yaml | 28 +++++++++++++++++++ .../meshservice/headless.resources.yaml | 7 +++++ pkg/util/k8s/name_converter.go | 11 ++++++++ 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go b/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go index f99e2eb16c20..460c9c2beb76 100644 --- a/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go +++ b/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go @@ -201,10 +201,16 @@ func (r *MeshServiceReconciler) Reconcile(ctx context.Context, req kube_ctrl.Req for current, endpoint := range servicePodEndpoints { // Our name is unique depending on the service identity and pod name - canonicalNameHash := k8s.NewHasher() - canonicalNameHash.Write([]byte(svc.Name)) - canonicalNameHash.Write([]byte(svc.Namespace)) - canonicalName := fmt.Sprintf("%s-%s", current.Name, k8s.HashToString(canonicalNameHash)) + // but we also might hash the pod name because it might need to be truncated + namePrefix := current.Name + canonicalNameHasher := k8s.NewHasher() + canonicalNameHasher.Write([]byte(svc.Name)) + canonicalNameHasher.Write([]byte(svc.Namespace)) + if len(current.Name)+k8s.MaxHashStringLength+1 > 253 { + canonicalNameHasher.Write([]byte(current.Name)) + namePrefix = k8s.EnsureMaxLength(namePrefix, 253-k8s.MaxHashStringLength-1) + } + canonicalName := fmt.Sprintf("%s-%s", namePrefix, k8s.HashToString(canonicalNameHasher)) op, err := r.manageMeshService( ctx, svc, diff --git a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml index adfe30814d5f..6fb6d0cccb06 100644 --- a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml +++ b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml @@ -55,4 +55,32 @@ items: tls: {} vips: - ip: 192.168.0.6 +- metadata: + creationTimestamp: null + labels: + k8s.kuma.io/service-name: example + kuma.io/mesh: default + name: very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-lo-86d6685d5b + namespace: demo + ownerReferences: + - apiVersion: v1 + kind: Pod + name: very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-long-name + uid: very-long-1 + resourceVersion: "1" + spec: + ports: + - port: 80 + protocol: http + targetPort: 8080 + - port: 443 + protocol: tcp + targetPort: 8443 + selector: + dataplaneRef: + name: very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-long-name + status: + tls: {} + vips: + - ip: 192.168.0.7 metadata: {} diff --git a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml index 3979cbe250ab..b92f6b24a3cc 100644 --- a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml +++ b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml @@ -22,6 +22,13 @@ endpoints: name: example-2 namespace: demo uid: example-2-1 + - addresses: + - 192.168.0.7 + targetRef: + kind: Pod + name: very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-long-name + namespace: demo + uid: very-long-1 --- apiVersion: v1 kind: Service diff --git a/pkg/util/k8s/name_converter.go b/pkg/util/k8s/name_converter.go index 87d94c3fa3f6..aeef407777a9 100644 --- a/pkg/util/k8s/name_converter.go +++ b/pkg/util/k8s/name_converter.go @@ -31,6 +31,17 @@ func NewHasher() hash.Hash32 { return fnv.New32a() } +// HashToString calculates a hash the same way Pod template hashes are computed func HashToString(h hash.Hash32) string { return rand.SafeEncodeString(fmt.Sprint(h.Sum32())) } + +// MaxHashStringLength is the max length of a string returned by HashToString +const MaxHashStringLength = 10 + +func EnsureMaxLength(s string, length int) string { + if len(s) <= length { + return s + } + return s[0:length] +} From 283aae39b7d0bfb5a45cc7e4e6fb0649ea4e857d Mon Sep 17 00:00:00 2001 From: Mike Beaumont Date: Tue, 28 May 2024 14:40:24 +0200 Subject: [PATCH 08/10] chore: update golden Signed-off-by: Mike Beaumont --- .../install-control-plane.cni-enabled.golden.yaml | 8 ++++++++ .../install-control-plane.defaults.golden.yaml | 13 +++++++++++++ .../install-control-plane.gateway-api-present.yaml | 13 +++++++++++++ .../install-control-plane.global.golden.yaml | 8 ++++++++ ...tall-control-plane.override-env-vars.golden.yaml | 8 ++++++++ .../install-control-plane.overrides.golden.yaml | 8 ++++++++ .../install-control-plane.registry.golden.yaml | 8 ++++++++ ...ane.tproxy-ebpf-experimental-enabled.golden.yaml | 8 ++++++++ .../install-control-plane.with-egress.golden.yaml | 8 ++++++++ .../install-control-plane.with-helm-set.yaml | 13 +++++++++++++ .../install-control-plane.with-helm-values.yaml | 8 ++++++++ .../install-control-plane.with-ingress.golden.yaml | 8 ++++++++ .../testdata/install-control-plane.zone.golden.yaml | 8 ++++++++ .../doNotChangeTlsChecksum.golden.yaml | 8 ++++++++ .../testdata/install-cp-helm/empty.golden.yaml | 8 ++++++++ .../testdata/install-cp-helm/fix4485.golden.yaml | 8 ++++++++ .../testdata/install-cp-helm/fix4496.golden.yaml | 8 ++++++++ .../testdata/install-cp-helm/fix4935.golden.yaml | 8 ++++++++ .../testdata/install-cp-helm/fix5978.golden.yaml | 8 ++++++++ .../testdata/install-cp-helm/fix7724.golden.yaml | 8 ++++++++ .../testdata/install-cp-helm/fix7824.golden.yaml | 8 ++++++++ .../install-cp-helm/minReadySeconds.golden.yaml | 8 ++++++++ .../install-cp-helm/securityContext.golden.yaml | 8 ++++++++ .../install/testdata/install-crds.all.golden.yaml | 5 +++++ 24 files changed, 204 insertions(+) diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.cni-enabled.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.cni-enabled.golden.yaml index a758ed1cb60c..450320cd30af 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.cni-enabled.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.cni-enabled.golden.yaml @@ -114,6 +114,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml index 41b99707c248..8f9dc4d903e6 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml @@ -4918,6 +4918,11 @@ spec: x-kubernetes-list-type: map selector: properties: + dataplaneRef: + properties: + name: + type: string + type: object dataplaneTags: additionalProperties: type: string @@ -8218,6 +8223,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.gateway-api-present.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.gateway-api-present.yaml index 61acf63fb04f..2dfbb1374f1d 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.gateway-api-present.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.gateway-api-present.yaml @@ -4918,6 +4918,11 @@ spec: x-kubernetes-list-type: map selector: properties: + dataplaneRef: + properties: + name: + type: string + type: object dataplaneTags: additionalProperties: type: string @@ -8218,6 +8223,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.global.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.global.golden.yaml index 83ee8d34b0ae..0c32545deab7 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.global.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.global.golden.yaml @@ -59,6 +59,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.override-env-vars.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.override-env-vars.golden.yaml index 9fdccb2e5cc0..5b28d714e75f 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.override-env-vars.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.override-env-vars.golden.yaml @@ -59,6 +59,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.overrides.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.overrides.golden.yaml index ec72054431ea..d2d447916594 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.overrides.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.overrides.golden.yaml @@ -59,6 +59,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.registry.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.registry.golden.yaml index 903713a99ebe..90b4e123c982 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.registry.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.registry.golden.yaml @@ -59,6 +59,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.tproxy-ebpf-experimental-enabled.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.tproxy-ebpf-experimental-enabled.golden.yaml index 461792c815a2..128bc0ece0a5 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.tproxy-ebpf-experimental-enabled.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.tproxy-ebpf-experimental-enabled.golden.yaml @@ -59,6 +59,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.with-egress.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.with-egress.golden.yaml index 6e0cc245247b..e69a32662113 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.with-egress.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.with-egress.golden.yaml @@ -69,6 +69,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.with-helm-set.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.with-helm-set.yaml index 335f0b07a287..5cf4f173e9f7 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.with-helm-set.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.with-helm-set.yaml @@ -4938,6 +4938,11 @@ spec: x-kubernetes-list-type: map selector: properties: + dataplaneRef: + properties: + name: + type: string + type: object dataplaneTags: additionalProperties: type: string @@ -8238,6 +8243,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.with-helm-values.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.with-helm-values.yaml index ec352507b234..8175b0fa390b 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.with-helm-values.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.with-helm-values.yaml @@ -59,6 +59,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.with-ingress.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.with-ingress.golden.yaml index 8eae9b01b413..2a2e36a89437 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.with-ingress.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.with-ingress.golden.yaml @@ -69,6 +69,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.zone.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.zone.golden.yaml index 41f0ff600f19..65dad29819f1 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.zone.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.zone.golden.yaml @@ -59,6 +59,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-cp-helm/doNotChangeTlsChecksum.golden.yaml b/app/kumactl/cmd/install/testdata/install-cp-helm/doNotChangeTlsChecksum.golden.yaml index 02b3c5bf58a1..e4ce2b3b6d62 100644 --- a/app/kumactl/cmd/install/testdata/install-cp-helm/doNotChangeTlsChecksum.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-cp-helm/doNotChangeTlsChecksum.golden.yaml @@ -59,6 +59,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-cp-helm/empty.golden.yaml b/app/kumactl/cmd/install/testdata/install-cp-helm/empty.golden.yaml index f51017c2d6d2..659f4f3aa2c5 100644 --- a/app/kumactl/cmd/install/testdata/install-cp-helm/empty.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-cp-helm/empty.golden.yaml @@ -59,6 +59,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-cp-helm/fix4485.golden.yaml b/app/kumactl/cmd/install/testdata/install-cp-helm/fix4485.golden.yaml index 382c9897a3ae..e279c6e39e2d 100644 --- a/app/kumactl/cmd/install/testdata/install-cp-helm/fix4485.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-cp-helm/fix4485.golden.yaml @@ -76,6 +76,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-cp-helm/fix4496.golden.yaml b/app/kumactl/cmd/install/testdata/install-cp-helm/fix4496.golden.yaml index 26c12da9fc4c..6c6469fb119c 100644 --- a/app/kumactl/cmd/install/testdata/install-cp-helm/fix4496.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-cp-helm/fix4496.golden.yaml @@ -73,6 +73,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-cp-helm/fix4935.golden.yaml b/app/kumactl/cmd/install/testdata/install-cp-helm/fix4935.golden.yaml index 8662b6eb57b6..d944621034d0 100644 --- a/app/kumactl/cmd/install/testdata/install-cp-helm/fix4935.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-cp-helm/fix4935.golden.yaml @@ -134,6 +134,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-cp-helm/fix5978.golden.yaml b/app/kumactl/cmd/install/testdata/install-cp-helm/fix5978.golden.yaml index 37f0c0455955..c7a2e4d193d1 100644 --- a/app/kumactl/cmd/install/testdata/install-cp-helm/fix5978.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-cp-helm/fix5978.golden.yaml @@ -79,6 +79,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-cp-helm/fix7724.golden.yaml b/app/kumactl/cmd/install/testdata/install-cp-helm/fix7724.golden.yaml index 270679f89244..ba7ca652e706 100644 --- a/app/kumactl/cmd/install/testdata/install-cp-helm/fix7724.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-cp-helm/fix7724.golden.yaml @@ -62,6 +62,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-cp-helm/fix7824.golden.yaml b/app/kumactl/cmd/install/testdata/install-cp-helm/fix7824.golden.yaml index c84caefc8ab0..4d443fec9e68 100644 --- a/app/kumactl/cmd/install/testdata/install-cp-helm/fix7824.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-cp-helm/fix7824.golden.yaml @@ -94,6 +94,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-cp-helm/minReadySeconds.golden.yaml b/app/kumactl/cmd/install/testdata/install-cp-helm/minReadySeconds.golden.yaml index d22211bb1fa9..c82a1222dedb 100644 --- a/app/kumactl/cmd/install/testdata/install-cp-helm/minReadySeconds.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-cp-helm/minReadySeconds.golden.yaml @@ -59,6 +59,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-cp-helm/securityContext.golden.yaml b/app/kumactl/cmd/install/testdata/install-cp-helm/securityContext.golden.yaml index abf135a817fb..7e8310b8a65c 100644 --- a/app/kumactl/cmd/install/testdata/install-cp-helm/securityContext.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-cp-helm/securityContext.golden.yaml @@ -59,6 +59,14 @@ rules: verbs: - list - watch + - apiGroups: + - "discovery.k8s.io" + resources: + - endpointslices + verbs: + - get + - list + - watch - apiGroups: - "apps" resources: diff --git a/app/kumactl/cmd/install/testdata/install-crds.all.golden.yaml b/app/kumactl/cmd/install/testdata/install-crds.all.golden.yaml index 574486f1a724..a994c61d7ca8 100644 --- a/app/kumactl/cmd/install/testdata/install-crds.all.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-crds.all.golden.yaml @@ -6342,6 +6342,11 @@ spec: x-kubernetes-list-type: map selector: properties: + dataplaneRef: + properties: + name: + type: string + type: object dataplaneTags: additionalProperties: type: string From 1ab2e765e063860b18ce75a2a0eab22eac85a91d Mon Sep 17 00:00:00 2001 From: Mike Beaumont Date: Tue, 28 May 2024 15:32:16 +0200 Subject: [PATCH 09/10] refactor: Pod names are 63 characters max so we don't need to worry about length Signed-off-by: Mike Beaumont --- .../runtime/k8s/controllers/meshservice_controller.go | 10 +++------- .../testdata/meshservice/headless.meshservice.yaml | 6 +++--- .../testdata/meshservice/headless.resources.yaml | 2 +- pkg/util/k8s/name_converter.go | 7 ------- 4 files changed, 7 insertions(+), 18 deletions(-) diff --git a/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go b/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go index 460c9c2beb76..b1f2f59daf12 100644 --- a/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go +++ b/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go @@ -201,16 +201,12 @@ func (r *MeshServiceReconciler) Reconcile(ctx context.Context, req kube_ctrl.Req for current, endpoint := range servicePodEndpoints { // Our name is unique depending on the service identity and pod name - // but we also might hash the pod name because it might need to be truncated - namePrefix := current.Name + // Note that a Pod name can be max 63 characters so we won't hit the 253 + // limit with our MeshService name canonicalNameHasher := k8s.NewHasher() canonicalNameHasher.Write([]byte(svc.Name)) canonicalNameHasher.Write([]byte(svc.Namespace)) - if len(current.Name)+k8s.MaxHashStringLength+1 > 253 { - canonicalNameHasher.Write([]byte(current.Name)) - namePrefix = k8s.EnsureMaxLength(namePrefix, 253-k8s.MaxHashStringLength-1) - } - canonicalName := fmt.Sprintf("%s-%s", namePrefix, k8s.HashToString(canonicalNameHasher)) + canonicalName := fmt.Sprintf("%s-%s", current.Name, k8s.HashToString(canonicalNameHasher)) op, err := r.manageMeshService( ctx, svc, diff --git a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml index 6fb6d0cccb06..69f4b5678d20 100644 --- a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml +++ b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.meshservice.yaml @@ -60,12 +60,12 @@ items: labels: k8s.kuma.io/service-name: example kuma.io/mesh: default - name: very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-lo-86d6685d5b + name: very-long-very-long-very-long-very-long-very-long-v-87ff74c98 namespace: demo ownerReferences: - apiVersion: v1 kind: Pod - name: very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-long-name + name: very-long-very-long-very-long-very-long-very-long-v uid: very-long-1 resourceVersion: "1" spec: @@ -78,7 +78,7 @@ items: targetPort: 8443 selector: dataplaneRef: - name: very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-long-name + name: very-long-very-long-very-long-very-long-very-long-v status: tls: {} vips: diff --git a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml index b92f6b24a3cc..ec09c7edf854 100644 --- a/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml +++ b/pkg/plugins/runtime/k8s/controllers/testdata/meshservice/headless.resources.yaml @@ -26,7 +26,7 @@ endpoints: - 192.168.0.7 targetRef: kind: Pod - name: very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-very-long-long-name + name: very-long-very-long-very-long-very-long-very-long-v namespace: demo uid: very-long-1 --- diff --git a/pkg/util/k8s/name_converter.go b/pkg/util/k8s/name_converter.go index aeef407777a9..3a9faa631656 100644 --- a/pkg/util/k8s/name_converter.go +++ b/pkg/util/k8s/name_converter.go @@ -38,10 +38,3 @@ func HashToString(h hash.Hash32) string { // MaxHashStringLength is the max length of a string returned by HashToString const MaxHashStringLength = 10 - -func EnsureMaxLength(s string, length int) string { - if len(s) <= length { - return s - } - return s[0:length] -} From fbc6be2fc2b579ed79373cf45aef3bb7aaa7e28f Mon Sep 17 00:00:00 2001 From: Mike Beaumont Date: Tue, 28 May 2024 15:49:49 +0200 Subject: [PATCH 10/10] chore: check whether owner is a Pod Signed-off-by: Mike Beaumont --- pkg/plugins/runtime/k8s/controllers/meshservice_controller.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go b/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go index b1f2f59daf12..fcba6f57f47d 100644 --- a/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go +++ b/pkg/plugins/runtime/k8s/controllers/meshservice_controller.go @@ -150,7 +150,9 @@ func (r *MeshServiceReconciler) Reconcile(ctx context.Context, req kube_ctrl.Req continue } owner := svc.GetOwnerReferences()[0] - // TODO check kinds of owner + if owner.Kind != "Pod" || owner.APIVersion != kube_core.SchemeGroupVersion.String() { + continue + } trackedPodEndpoints[kube_types.NamespacedName{Namespace: svc.Namespace, Name: owner.Name}] = struct{}{} }