diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e32a1bec9..c35d005537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -135,6 +135,8 @@ Adding a new version? You'll need three changes: [#3563](https://github.com/Kong/kubernetes-ingress-controller/pull/3563) - Added `GRPCRoute` controller and implemented basic `GRPCRoute` functionality. [#3537](https://github.com/Kong/kubernetes-ingress-controller/pull/3537) +- Included Konnect sync and Gateway Service discovery features in telemetry reports. + [#3588](https://github.com/Kong/kubernetes-ingress-controller/pull/3588) ### Fixed diff --git a/internal/manager/run.go b/internal/manager/run.go index 37d91fa75c..d805e4a861 100644 --- a/internal/manager/run.go +++ b/internal/manager/run.go @@ -229,11 +229,14 @@ func Run(ctx context.Context, c *Config, diagnostic util.ConfigDumpDiagnostic, d stopAnonymousReports, err := telemetry.SetupAnonymousReports( ctx, kubeconfig, - c.PublishService, - metadata.Release, - len(c.WatchNamespaces) == 0, - featureGates, clientsManager, + telemetry.ReportValues{ + PublishServiceNN: c.PublishService, + FeatureGates: featureGates, + MeshDetection: len(c.WatchNamespaces) == 0, + KonnectSyncEnabled: c.Konnect.ConfigSynchronizationEnabled, + GatewayServiceDiscoveryEnabled: c.KongAdminSvc.String() != "", + }, ) if err != nil { setupLog.Error(err, "failed setting up anonymous reports") diff --git a/internal/manager/telemetry/manager.go b/internal/manager/telemetry/manager.go index 8c738a810e..61edf7a0c6 100644 --- a/internal/manager/telemetry/manager.go +++ b/internal/manager/telemetry/manager.go @@ -32,14 +32,16 @@ const ( type Payload = types.ProviderReport +type ReportValues struct { + FeatureGates map[string]bool + MeshDetection bool + PublishServiceNN apitypes.NamespacedName + KonnectSyncEnabled bool + GatewayServiceDiscoveryEnabled bool +} + // CreateManager creates telemetry manager using the provided rest.Config. -func CreateManager( - restConfig *rest.Config, - fixedPayload Payload, - featureGates map[string]bool, - meshDetection bool, - publishServiceNN apitypes.NamespacedName, -) (telemetry.Manager, error) { +func CreateManager(restConfig *rest.Config, fixedPayload Payload, rv ReportValues) (telemetry.Manager, error) { logger := logrusr.New(logrus.New()) k, err := kubernetes.NewForConfig(restConfig) @@ -52,7 +54,7 @@ func CreateManager( } dyn := dynamic.New(k.Discovery().RESTClient()) - m, err := createManager(k, dyn, cl, fixedPayload, featureGates, meshDetection, publishServiceNN, + m, err := createManager(k, dyn, cl, fixedPayload, rv, telemetry.OptManagerPeriod(telemetryPeriod), telemetry.OptManagerLogger(logger), ) @@ -78,9 +80,7 @@ func createManager( dyn dynamic.Interface, cl client.Client, fixedPayload Payload, - featureGates map[string]bool, - meshDetection bool, - publishServiceNN apitypes.NamespacedName, + rv ReportValues, opts ...telemetry.OptManager, ) (telemetry.Manager, error) { m, err := telemetry.NewManager( @@ -112,7 +112,7 @@ func createManager( // Add mesh detect workflow { - if meshDetection { + if rv.MeshDetection { podNN, err := util.GetPodNN() if err != nil { // Don't fail, just don't include mesh detection workflow. @@ -120,7 +120,7 @@ func createManager( // part responsible for detecting the mesh that current pod is running // gets disabled. } else { - w, err := telemetry.NewMeshDetectWorkflow(cl, podNN, publishServiceNN) + w, err := telemetry.NewMeshDetectWorkflow(cl, podNN, rv.PublishServiceNN) if err != nil { return nil, fmt.Errorf("failed to create mesh detect workflow: %w", err) } @@ -145,7 +145,17 @@ func createManager( w.AddProvider(p) } { - p, err := provider.NewFixedValueProvider("feature-gates", featureGatesToTelemetryPayload(featureGates)) + p, err := provider.NewFixedValueProvider("feature-gates", featureGatesToTelemetryPayload(rv.FeatureGates)) + if err != nil { + return nil, fmt.Errorf("failed to create fixed value provider: %w", err) + } + w.AddProvider(p) + } + { + p, err := provider.NewFixedValueProvider("feature-flags", types.ProviderReport{ + "feature-konnect-sync": rv.KonnectSyncEnabled, + "feature-gateway-service-discovery": rv.GatewayServiceDiscoveryEnabled, + }) if err != nil { return nil, fmt.Errorf("failed to create fixed value provider: %w", err) } diff --git a/internal/manager/telemetry/manager_test.go b/internal/manager/telemetry/manager_test.go index 1f58598bc5..4d80652042 100644 --- a/internal/manager/telemetry/manager_test.go +++ b/internal/manager/telemetry/manager_test.go @@ -38,7 +38,6 @@ func TestCreateManager(t *testing.T) { "knative": false, } ctx = context.Background() - meshDetection = true publishService = apitypes.NamespacedName{ Namespace: "kong", Name: "kong-proxy", @@ -83,7 +82,18 @@ func TestCreateManager(t *testing.T) { Platform: "linux/amd64", } - mgr, err := createManager(k8sclient, dyn, ctrlClient, payload, featureGates, meshDetection, publishService, + mgr, err := createManager( + k8sclient, + dyn, + ctrlClient, + payload, + ReportValues{ + FeatureGates: featureGates, + MeshDetection: true, + PublishServiceNN: publishService, + KonnectSyncEnabled: true, + GatewayServiceDiscoveryEnabled: true, + }, telemetry.OptManagerPeriod(time.Hour), telemetry.OptManagerLogger(logr.Discard()), ) @@ -107,8 +117,10 @@ func TestCreateManager(t *testing.T) { "<14>"+ "signal=test-signal;"+ "db=off;"+ + "feature-gateway-service-discovery=true;"+ "feature-gateway=true;"+ "feature-knative=false;"+ + "feature-konnect-sync=true;"+ "hn=%s;"+ "kv=3.1.1;"+ "uptime=0;"+ diff --git a/internal/manager/telemetry/reports.go b/internal/manager/telemetry/reports.go index 02845048a3..9f9b35cd69 100644 --- a/internal/manager/telemetry/reports.go +++ b/internal/manager/telemetry/reports.go @@ -5,7 +5,6 @@ import ( "fmt" "github.com/google/uuid" - apitypes "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/rest" "github.com/kong/kubernetes-ingress-controller/v2/internal/dataplane" @@ -19,11 +18,8 @@ import ( func SetupAnonymousReports( ctx context.Context, kubeCfg *rest.Config, - publishService apitypes.NamespacedName, - kicVersion string, - meshDetection bool, - featureGates map[string]bool, clientsProvider dataplane.AdminAPIClientsProvider, + rv ReportValues, ) (func(), error) { // if anonymous reports are enabled this helps provide Kong with insights about usage of the ingress controller // which is non-sensitive and predominantly informs us of the controller and cluster versions in use. @@ -35,10 +31,10 @@ func SetupAnonymousReports( // That's fine because we allow for now only 1 set of version and db setting // throughout all Kong instances that 1 KIC instance configures. // - // When we change that and decide to allow heterogenous Kong instances to be + // When we change that and decide to allow heterogeneous Kong instances to be // configured by 1 KIC instance then this will have to change. // - // https://github.com/Kong/kubernetes-ingress-controller/issues/3362 + // https://github.com/Kong/kubernetes-ingress-controller/issues/3589 root, err := clientsProvider.GatewayClients()[0].AdminAPIClient().Root(ctx) if err != nil { return nil, fmt.Errorf("failed to get Kong root config data: %w", err) @@ -65,7 +61,7 @@ func SetupAnonymousReports( "id": uuid.NewString(), // universal unique identifier for this system } - tMgr, err := CreateManager(kubeCfg, fixedPayload, featureGates, meshDetection, publishService) + tMgr, err := CreateManager(kubeCfg, fixedPayload, rv) if err != nil { return nil, fmt.Errorf("failed to create anonymous reports manager: %w", err) } diff --git a/internal/manager/utils/kongconfig/root.go b/internal/manager/utils/kongconfig/root.go index 8e86e58dc3..802c1577d5 100644 --- a/internal/manager/utils/kongconfig/root.go +++ b/internal/manager/utils/kongconfig/root.go @@ -26,6 +26,7 @@ func ValidateRoots(roots []Root, skipCACerts bool) (string, kong.Version, error) return "", kong.Version{}, fmt.Errorf("failed to validate kong Roots: %w", err) } + // To be dropped as a part of https://github.com/Kong/kubernetes-ingress-controller/issues/3590. uniqs := lo.UniqBy(roots, getRootKeyFunc(skipCACerts)) if len(uniqs) != 1 { return "", kong.Version{}, diff --git a/internal/manager/utils/reports.go b/internal/manager/utils/reports.go deleted file mode 100644 index 7859ad0c68..0000000000 --- a/internal/manager/utils/reports.go +++ /dev/null @@ -1,117 +0,0 @@ -package utils - -import ( - "context" - "fmt" - "os" - - "github.com/google/uuid" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - ctrl "sigs.k8s.io/controller-runtime" - - "github.com/kong/kubernetes-ingress-controller/v2/internal/dataplane" - "github.com/kong/kubernetes-ingress-controller/v2/internal/meshdetect" - "github.com/kong/kubernetes-ingress-controller/v2/internal/util" -) - -// RunReport runs the anonymous data report and reports any errors that have occurred. -func RunReport( - ctx context.Context, - kubeCfg *rest.Config, - publishServiceName string, - kicVersion string, - meshDetection bool, - featureGates map[string]bool, - clientsProvider dataplane.AdminAPIClientsProvider, -) error { - // if anonymous reports are enabled this helps provide Kong with insights about usage of the ingress controller - // which is non-sensitive and predominantly informs us of the controller and cluster versions in use. - // This data helps inform us what versions, features, e.t.c. end-users are actively using which helps to inform - // our prioritization of work and we appreciate when our end-users provide them, however if you do feel - // uncomfortable and would rather turn them off run the controller with the "--anonymous-reports false" flag. - - // record the system hostname - hostname, err := os.Hostname() - if err != nil { - return fmt.Errorf("failed to fetch hostname: %w", err) - } - - // create a universal unique identifier for this system - uuid := uuid.NewString() - - // record the current Kubernetes server version - kc, err := kubernetes.NewForConfig(kubeCfg) - if err != nil { - return fmt.Errorf("could not create client-go for Kubernetes discovery: %w", err) - } - k8sVersion, err := kc.Discovery().ServerVersion() - if err != nil { - return fmt.Errorf("failed to fetch k8s api-server version: %w", err) - } - - // This now only uses the first instance for telemetry reporting. - // That's fine because we allow for now only 1 set of version and db setting - // throughout all Kong instances that 1 KIC instance configures. - // - // When we change that and decide to allow heterogenous Kong instances to be - // configured by 1 KIC instance then this will have to change. - // - // https://github.com/Kong/kubernetes-ingress-controller/issues/3362 - - // gather versioning information from the kong client - root, err := clientsProvider.GatewayClients()[0].AdminAPIClient().Root(ctx) - if err != nil { - return fmt.Errorf("failed to get Kong root config data: %w", err) - } - kongVersion, ok := root["version"].(string) - if !ok { - return fmt.Errorf("malformed Kong version found in Kong client root") - } - cfg, ok := root["configuration"].(map[string]interface{}) - if !ok { - return fmt.Errorf("malformed Kong configuration found in Kong client root") - } - kongDB, ok := cfg["database"].(string) - if !ok { - return fmt.Errorf("malformed database configuration found in Kong client root") - } - - // build the final report - info := util.Info{ - KongVersion: kongVersion, - KICVersion: kicVersion, - KubernetesVersion: k8sVersion.String(), - Hostname: hostname, - ID: uuid, - KongDB: kongDB, - FeatureGates: featureGates, - } - - // run the reporter in the background - reporter := util.Reporter{ - Info: info, - Logger: ctrl.Log.WithName("reporter"), - } - - if meshDetection { - // add mesh detector to reporter - podNN, err := util.GetPodNN() - // Don't return the error when we can't get pod info. - // Just don't run the mesh detection. - if err == nil { - detector, err := meshdetect.NewDetectorByConfig(kubeCfg, podNN.Namespace, podNN.Name, publishServiceName, - // logger=reporter.mesh - reporter.Logger.WithName("mesh"), - ) - if err == nil { - reporter.MeshDetectionEnabled = true - reporter.MeshDetector = detector - } - } - } - - go reporter.Run(ctx) - - return nil -}