-
Notifications
You must be signed in to change notification settings - Fork 80
K8SPG-1083 improve platform detection to reduce unknown telemetry values #1655
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c66f531
ef39113
2c321a7
3507d94
813ad19
cbeaad9
610fbfe
63eb16d
86ad80e
3accde1
cc35cc4
2dbf18f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -6,6 +6,7 @@ package main | |||
|
|
||||
| import ( | ||||
| "context" | ||||
| "crypto/tls" | ||||
| "os" | ||||
| goruntime "runtime" | ||||
| "strconv" | ||||
|
|
@@ -145,7 +146,7 @@ func main() { | |||
| log.Info("upgrade checking enabled") | ||||
| // get the URL for the check for upgrades endpoint if set in the env | ||||
| assertNoError(upgradecheck.ManagedScheduler(mgr, | ||||
| isOpenshift(ctx, mgr.GetConfig()), os.Getenv("CHECK_FOR_UPGRADES_URL"), versionString, nil)) | ||||
| false, os.Getenv("CHECK_FOR_UPGRADES_URL"), versionString, nil)) | ||||
| } | ||||
|
|
||||
| assertNoError(mgr.Start(ctx)) | ||||
|
|
@@ -157,13 +158,16 @@ func main() { | |||
| func addControllersToManager(ctx context.Context, mgr manager.Manager) error { | ||||
| os.Setenv("REGISTRATION_REQUIRED", "false") | ||||
|
|
||||
| platform := detectPlatform(ctx, mgr.GetConfig()) | ||||
| openShift := platform == "openshift" | ||||
|
|
||||
| r := &postgrescluster.Reconciler{ | ||||
| Client: mgr.GetClient(), | ||||
| Scheme: mgr.GetScheme(), | ||||
| Owner: postgrescluster.ControllerName, | ||||
| Recorder: mgr.GetEventRecorderFor(postgrescluster.ControllerName), | ||||
| Tracer: otel.Tracer(postgrescluster.ControllerName), | ||||
| IsOpenShift: isOpenshift(ctx, mgr.GetConfig()), | ||||
| IsOpenShift: openShift, | ||||
| CertManagerCtrlFunc: certmanager.NewController, | ||||
| RestConfig: mgr.GetConfig(), | ||||
| } | ||||
|
|
@@ -201,10 +205,10 @@ func addControllersToManager(ctx context.Context, mgr manager.Manager) error { | |||
| Owner: pgcluster.PGClusterControllerName, | ||||
| Recorder: mgr.GetEventRecorderFor(pgcluster.PGClusterControllerName), | ||||
| Tracer: otel.Tracer(pgcluster.PGClusterControllerName), | ||||
| Platform: detectPlatform(ctx, mgr.GetConfig()), | ||||
| Platform: platform, | ||||
| KubeVersion: getServerVersion(ctx, mgr.GetConfig()), | ||||
| CrunchyController: cm.Controller(), | ||||
| IsOpenShift: isOpenshift(ctx, mgr.GetConfig()), | ||||
| IsOpenShift: openShift, | ||||
| Cron: pgcluster.NewCronRegistry(), | ||||
| ExternalChan: externalEvents, | ||||
| StopExternalWatchers: stopChan, | ||||
|
|
@@ -280,7 +284,7 @@ func addControllersToManager(ctx context.Context, mgr manager.Manager) error { | |||
| Client: mgr.GetClient(), | ||||
| Owner: "pgadmin-controller", | ||||
| Recorder: mgr.GetEventRecorderFor(naming.ControllerPGAdmin), | ||||
| IsOpenShift: isOpenshift(ctx, mgr.GetConfig()), | ||||
| IsOpenShift: openShift, | ||||
| } | ||||
|
|
||||
| if err := pgAdminReconciler.SetupWithManager(mgr); err != nil { | ||||
|
|
@@ -366,83 +370,99 @@ func initManager(ctx context.Context) (runtime.Options, error) { | |||
| return options, nil | ||||
| } | ||||
|
|
||||
| func isGKE(ctx context.Context, cfg *rest.Config) bool { | ||||
| // hasAPIGroup returns true if the cluster exposes the given API group name. | ||||
| func hasAPIGroup(ctx context.Context, cfg *rest.Config, groupName string) bool { | ||||
|
hors marked this conversation as resolved.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already have a helper utility I'd suggest we move this to a
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||
| log := logging.FromContext(ctx) | ||||
| dc, err := discovery.NewDiscoveryClientForConfig(cfg) | ||||
| if err != nil { | ||||
| log.V(1).Info("platform detection: could not create discovery client", "error", err.Error()) | ||||
| return false | ||||
| } | ||||
| ok, err := k8s.GroupExists(dc, groupName) | ||||
| if err != nil { | ||||
| log.V(1).Info("platform detection: could not list API groups", "error", err.Error()) | ||||
| return false | ||||
|
Comment on lines
+373
to
+384
|
||||
| } | ||||
| return ok | ||||
| } | ||||
|
|
||||
| const groupName, kind = "cloud.google.com", "BackendConfig" | ||||
|
|
||||
| client, err := discovery.NewDiscoveryClientForConfig(cfg) | ||||
| assertNoError(err) | ||||
| type platformProbe struct { | ||||
| name string | ||||
| label string | ||||
| apiGroups []string | ||||
| hosts []string | ||||
| custom func(ctx context.Context, cfg *rest.Config) bool | ||||
| } | ||||
|
|
||||
| groups, err := client.ServerGroups() | ||||
| if err != nil { | ||||
| assertNoError(err) | ||||
| func (p platformProbe) detect(ctx context.Context, cfg *rest.Config) bool { | ||||
| if p.custom != nil { | ||||
| return p.custom(ctx, cfg) | ||||
| } | ||||
| for _, g := range groups.Groups { | ||||
| if g.Name != groupName { | ||||
| continue | ||||
| for _, g := range p.apiGroups { | ||||
| if hasAPIGroup(ctx, cfg, g) { | ||||
| return true | ||||
| } | ||||
| for _, v := range g.Versions { | ||||
| resourceList, err := client.ServerResourcesForGroupVersion(v.GroupVersion) | ||||
| if err != nil { | ||||
| assertNoError(err) | ||||
| } | ||||
| for _, r := range resourceList.APIResources { | ||||
| if r.Kind == kind { | ||||
| log.Info("detected GKE environment") | ||||
| return true | ||||
| } | ||||
| } | ||||
| } | ||||
| for _, h := range p.hosts { | ||||
| if strings.Contains(cfg.Host, h) { | ||||
| return true | ||||
| } | ||||
| } | ||||
|
|
||||
| return false | ||||
| } | ||||
|
|
||||
| func isEKS(ctx context.Context, cfg *rest.Config) bool { | ||||
| log := logging.FromContext(ctx) | ||||
|
|
||||
| const groupName, kind = "vpcresources.k8s.aws", "SecurityGroupPolicy" | ||||
|
|
||||
| client, err := discovery.NewDiscoveryClientForConfig(cfg) | ||||
| assertNoError(err) | ||||
| var platformProbes = []platformProbe{ | ||||
| {name: "openshift", label: "Openshift", apiGroups: []string{"security.openshift.io"}}, | ||||
|
|
||||
| {name: "gke", label: "GKE", apiGroups: []string{"networking.gke.io"}}, | ||||
| // crd.k8s.amazonaws.com (VPC CNI) and metrics.eks.amazonaws.com are independent EKS signals. | ||||
| {name: "eks", label: "EKS", apiGroups: []string{"crd.k8s.amazonaws.com", "metrics.eks.amazonaws.com"}}, | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if rancher run on AWS, what's the api group returned?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we have a more eks specific signal?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The most reliable truly-EKS signal without extra RBAC requires both groups The problem is that clusters without the metrics addon enabled would fall back to unknown :( |
||||
| // AKS exposes no unique API groups; inspect the API server TLS cert SAN instead. | ||||
| {name: "aks", label: "AKS", custom: detectAKS}, | ||||
| {name: "doks", label: "DOKS", apiGroups: []string{"dataplane-operator.doks.digitalocean.com"}}, | ||||
| {name: "oke", label: "OKE", apiGroups: []string{"oci.oraclecloud.com"}, hosts: []string{".oraclecloud.com"}}, | ||||
| {name: "ack", label: "ACK", apiGroups: []string{"alibabacloud.com"}, hosts: []string{".aliyuncs.com"}}, | ||||
| // kommander.mesosphere.io is the legacy D2iQ/Konvoy group name for NKP. | ||||
| {name: "nkp", label: "NKP", apiGroups: []string{"nkp.nutanix.com", "kommander.mesosphere.io"}}, | ||||
| {name: "platform9", label: "Platform9", hosts: []string{".platform9.io", ".platform9.net"}}, | ||||
| {name: "tanzu", label: "Tanzu", apiGroups: []string{"run.tanzu.vmware.com"}}, | ||||
| {name: "rancher", label: "Rancher", apiGroups: []string{"management.cattle.io"}}, | ||||
| } | ||||
|
|
||||
| groups, err := client.ServerGroups() | ||||
| func detectAKS(ctx context.Context, cfg *rest.Config) bool { | ||||
| tlsCfg, err := rest.TLSConfigFor(cfg) | ||||
| if err != nil { | ||||
| assertNoError(err) | ||||
| } | ||||
| for _, g := range groups.Groups { | ||||
| if g.Name != groupName { | ||||
| continue | ||||
| } | ||||
| for _, v := range g.Versions { | ||||
| resourceList, err := client.ServerResourcesForGroupVersion(v.GroupVersion) | ||||
| if err != nil { | ||||
| assertNoError(err) | ||||
| } | ||||
| for _, r := range resourceList.APIResources { | ||||
| if r.Kind == kind { | ||||
| log.Info("detected EKS environment") | ||||
| return true | ||||
| } | ||||
| logging.FromContext(ctx).V(1).Info("platform detection: could not build TLS config", "error", err.Error()) | ||||
| return false | ||||
| } | ||||
| host := strings.TrimPrefix(cfg.Host, "https://") | ||||
| host = strings.TrimPrefix(host, "http://") | ||||
| dialCtx, cancel := context.WithTimeout(ctx, 5*time.Second) | ||||
| defer cancel() | ||||
| netConn, err := (&tls.Dialer{Config: tlsCfg}).DialContext(dialCtx, "tcp", host) | ||||
| if err != nil { | ||||
| logging.FromContext(ctx).V(1).Info("platform detection: could not dial API server", "error", err.Error()) | ||||
| return false | ||||
| } | ||||
| defer netConn.Close() | ||||
| conn := netConn.(*tls.Conn) | ||||
| for _, cert := range conn.ConnectionState().PeerCertificates { | ||||
|
hors marked this conversation as resolved.
|
||||
| for _, san := range cert.DNSNames { | ||||
| if strings.HasSuffix(san, ".azmk8s.io") { | ||||
| return true | ||||
| } | ||||
| } | ||||
| } | ||||
|
|
||||
| return false | ||||
| } | ||||
|
|
||||
| func detectPlatform(ctx context.Context, cfg *rest.Config) string { | ||||
| switch { | ||||
| case isOpenshift(ctx, cfg): | ||||
| return "openshift" | ||||
| case isGKE(ctx, cfg): | ||||
| return "gke" | ||||
| case isEKS(ctx, cfg): | ||||
| return "eks" | ||||
| default: | ||||
| return "unknown" | ||||
| for _, probe := range platformProbes { | ||||
| if probe.detect(ctx, cfg) { | ||||
| logging.FromContext(ctx).Info("detected " + probe.label + " environment") | ||||
| return probe.name | ||||
| } | ||||
| } | ||||
|
Comment on lines
+459
to
+464
|
||||
| return "unknown" | ||||
| } | ||||
|
|
||||
| // getServerVersion returns the stringified server version (i.e., the same info `kubectl version` | ||||
|
|
@@ -503,38 +523,6 @@ func getLogLevel() zapcore.LevelEnabler { | |||
| } | ||||
| } | ||||
|
|
||||
| func isOpenshift(ctx context.Context, cfg *rest.Config) bool { | ||||
| log := logging.FromContext(ctx) | ||||
|
|
||||
| const sccGroupName, sccKind = "security.openshift.io", "SecurityContextConstraints" | ||||
|
|
||||
| client, err := discovery.NewDiscoveryClientForConfig(cfg) | ||||
| assertNoError(err) | ||||
|
|
||||
| groups, err := client.ServerGroups() | ||||
| if err != nil { | ||||
| assertNoError(err) | ||||
| } | ||||
| for _, g := range groups.Groups { | ||||
| if g.Name != sccGroupName { | ||||
| continue | ||||
| } | ||||
| for _, v := range g.Versions { | ||||
| resourceList, err := client.ServerResourcesForGroupVersion(v.GroupVersion) | ||||
| if err != nil { | ||||
| assertNoError(err) | ||||
| } | ||||
| for _, r := range resourceList.APIResources { | ||||
| if r.Kind == sccKind { | ||||
| log.Info("detected Openshift environment") | ||||
| return true | ||||
| } | ||||
| } | ||||
| } | ||||
| } | ||||
|
|
||||
| return false | ||||
| } | ||||
|
|
||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [gofmt] reported by reviewdog 🐶
Suggested change
|
||||
| type envConfig struct { | ||||
| LeaderElection bool `default:"true" envconfig:"PGO_CONTROLLER_LEADER_ELECTION_ENABLED"` | ||||
|
|
||||
Uh oh!
There was an error while loading. Please reload this page.