@@ -852,6 +852,9 @@ func (c *HostCollector) GetSystemInfo() (*collector.SystemInfo, error) {
852852
853853 info .IsVirtualized , info .VirtualizationType = detectVirtualization ()
854854
855+ // Kubernetes provider detection
856+ info .IsKubernetes , info .K8sProvider = detectK8sProvider ()
857+
855858 // Cloud metadata
856859 info .CloudProvider , info .CloudInstanceID , info .CloudInstanceType ,
857860 info .CloudRegion , info .CloudZone = detectCloudMetadata ()
@@ -887,6 +890,109 @@ func parseUint64(s string) uint64 {
887890 return v
888891}
889892
893+ // detectK8sProvider detects whether the agent is running in a Kubernetes
894+ // environment and returns the specific distribution/provider. The returned
895+ // provider matches K8sProviderEnum values on the platform backend:
896+ // eks, gke, aks, ack, cce, k3s, kind, minikube, rancher, openshift, okd,
897+ // microshift, kubesphere, self-managed. Returns (false, "") when no
898+ // Kubernetes environment is detected.
899+ //
900+ // Detection priority:
901+ // 1. Managed cloud providers (env vars injected by the cloud control plane)
902+ // 2. OpenShift variants (MicroShift → OpenShift → OKD)
903+ // 3. Lightweight/local distributions (k3s → Rancher → minikube → KIND)
904+ // 4. Platform distributions (KubeSphere)
905+ // 5. Generic in-cluster fallback via KUBERNETES_SERVICE_HOST
906+ func detectK8sProvider () (isK8s bool , provider string ) {
907+ // hostRoot is the host filesystem mount point used when running as a
908+ // DaemonSet (e.g. /hostfs). Falls back to empty string so that paths
909+ // are checked directly when running outside a container.
910+ hostRoot := os .Getenv ("TELEMETRYFLOW_HOST_ROOT" )
911+
912+ hostStat := func (path string ) bool {
913+ if _ , err := os .Stat (path ); err == nil {
914+ return true
915+ }
916+ if hostRoot != "" {
917+ if _ , err := os .Stat (hostRoot + path ); err == nil {
918+ return true
919+ }
920+ }
921+ return false
922+ }
923+
924+ // === Managed Cloud Providers ===
925+
926+ // EKS (Amazon Elastic Kubernetes Service)
927+ if os .Getenv ("AWS_REGION" ) != "" || os .Getenv ("EKS_CLUSTER_NAME" ) != "" {
928+ return true , "eks"
929+ }
930+ // GKE (Google Kubernetes Engine)
931+ if os .Getenv ("GOOGLE_CLOUD_PROJECT" ) != "" || os .Getenv ("GKE_CLUSTER_NAME" ) != "" {
932+ return true , "gke"
933+ }
934+ // AKS (Azure Kubernetes Service)
935+ if os .Getenv ("AKS_CLUSTER_NAME" ) != "" || os .Getenv ("AZURE_SUBSCRIPTION_ID" ) != "" {
936+ return true , "aks"
937+ }
938+ // ACK (Alibaba Cloud Container Service for Kubernetes)
939+ if os .Getenv ("ALIBABA_CLOUD_ACCESS_KEY_ID" ) != "" || os .Getenv ("ACK_CLUSTER_ID" ) != "" {
940+ return true , "ack"
941+ }
942+ // CCE (Huawei Cloud Container Engine)
943+ if os .Getenv ("HUAWEICLOUD_SDK_TYPE" ) != "" || os .Getenv ("CCE_CLUSTER_ID" ) != "" {
944+ return true , "cce"
945+ }
946+
947+ // === OpenShift Variants (MicroShift first — it's a subset of OpenShift) ===
948+
949+ if hostStat ("/var/lib/microshift" ) {
950+ return true , "microshift"
951+ }
952+ if os .Getenv ("OPENSHIFT_BUILD_NAMESPACE" ) != "" || os .Getenv ("OPENSHIFT_DEPLOYMENT_NAME" ) != "" ||
953+ hostStat ("/etc/openshift" ) {
954+ return true , "openshift"
955+ }
956+ // OKD (community OpenShift)
957+ if os .Getenv ("OKD_CLUSTER" ) != "" || hostStat ("/etc/okd" ) {
958+ return true , "okd"
959+ }
960+
961+ // === Lightweight / Local Distributions ===
962+
963+ // k3s (must be checked before generic Rancher — k3s lives under /var/lib/rancher/k3s)
964+ if hostStat ("/var/lib/rancher/k3s" ) {
965+ return true , "k3s"
966+ }
967+ // Rancher (RKE / RKE2) — CATTLE_* vars are injected by Rancher into pods
968+ if os .Getenv ("CATTLE_CLUSTER_AGENT_PORT" ) != "" || os .Getenv ("CATTLE_SERVER" ) != "" ||
969+ hostStat ("/var/lib/rancher/rke2" ) || hostStat ("/var/lib/rancher" ) {
970+ return true , "rancher"
971+ }
972+ // minikube
973+ if os .Getenv ("MINIKUBE_ACTIVE_DOCKERD" ) != "" || os .Getenv ("MINIKUBE_HOME" ) != "" {
974+ return true , "minikube"
975+ }
976+ // KIND (Kubernetes IN Docker)
977+ if os .Getenv ("KIND_CLUSTER_NAME" ) != "" {
978+ return true , "kind"
979+ }
980+
981+ // === Platform Distributions ===
982+
983+ if os .Getenv ("KUBESPHERE_NAMESPACE" ) != "" {
984+ return true , "kubesphere"
985+ }
986+
987+ // === Generic in-cluster fallback ===
988+ // KUBERNETES_SERVICE_HOST is injected by the kubelet into every pod.
989+ if os .Getenv ("KUBERNETES_SERVICE_HOST" ) != "" {
990+ return true , "self-managed"
991+ }
992+
993+ return false , ""
994+ }
995+
890996// detectContainer checks if running inside a container
891997func detectContainer () bool {
892998 // Check for Docker
@@ -1019,8 +1125,27 @@ func detectVirtualization() (bool, string) {
10191125
10201126// detectCloudMetadata attempts to detect cloud provider and instance metadata
10211127func detectCloudMetadata () (provider , instanceID , instanceType , region , zone string ) {
1128+ // hostRoot is the mount point for the host filesystem inside the container.
1129+ // DaemonSet mounts host / → /host/root and sets TELEMETRYFLOW_HOST_ROOT=/host/root.
1130+ // k8s-collector Deployment mounts host / → /hostfs and sets TELEMETRYFLOW_HOST_ROOT=/hostfs.
1131+ // Falls back to empty string (direct paths) when running outside a container.
1132+ hostRoot := os .Getenv ("TELEMETRYFLOW_HOST_ROOT" )
1133+
1134+ // hostStat checks the path directly and, if that fails, prefixed by hostRoot.
1135+ hostStat := func (path string ) bool {
1136+ if _ , err := os .Stat (path ); err == nil {
1137+ return true
1138+ }
1139+ if hostRoot != "" {
1140+ if _ , err := os .Stat (hostRoot + path ); err == nil {
1141+ return true
1142+ }
1143+ }
1144+ return false
1145+ }
1146+
10221147 // AWS detection
1023- if _ , err := os . Stat ("/sys/hypervisor/uuid" ); err == nil {
1148+ if hostStat ("/sys/hypervisor/uuid" ) {
10241149 if data , err := os .ReadFile ("/sys/hypervisor/uuid" ); err == nil {
10251150 if strings .HasPrefix (strings .ToLower (string (data )), "ec2" ) {
10261151 provider = "aws"
@@ -1033,22 +1158,51 @@ func detectCloudMetadata() (provider, instanceID, instanceType, region, zone str
10331158 }
10341159
10351160 // GCP detection
1036- if data , err := os .ReadFile ("/sys/class/dmi/id/product_name" ); err == nil {
1037- if strings .Contains (strings .ToLower (string (data )), "google" ) {
1038- provider = "gcp"
1161+ for _ , p := range []string {"/sys/class/dmi/id/product_name" , hostRoot + "/sys/class/dmi/id/product_name" } {
1162+ if data , err := os .ReadFile (p ); err == nil {
1163+ if strings .Contains (strings .ToLower (string (data )), "google" ) {
1164+ provider = "gcp"
1165+ }
1166+ break
10391167 }
10401168 }
10411169 if os .Getenv ("GOOGLE_CLOUD_PROJECT" ) != "" {
10421170 provider = "gcp"
10431171 }
10441172
10451173 // Azure detection
1046- if data , err := os .ReadFile ("/sys/class/dmi/id/sys_vendor" ); err == nil {
1047- if strings .Contains (strings .ToLower (string (data )), "microsoft" ) {
1048- provider = "azure"
1174+ for _ , p := range []string {"/sys/class/dmi/id/sys_vendor" , hostRoot + "/sys/class/dmi/id/sys_vendor" } {
1175+ if data , err := os .ReadFile (p ); err == nil {
1176+ if strings .Contains (strings .ToLower (string (data )), "microsoft" ) {
1177+ provider = "azure"
1178+ }
1179+ break
10491180 }
10501181 }
10511182
1183+ // Rancher / RKE / RKE2 detection
1184+ // CATTLE_* vars are injected by Rancher into pods in the cattle-system namespace.
1185+ // For other namespaces we rely on host filesystem heuristics via hostRoot.
1186+ if os .Getenv ("CATTLE_CLUSTER_AGENT_PORT" ) != "" || os .Getenv ("CATTLE_SERVER" ) != "" {
1187+ provider = "rancher"
1188+ return provider , instanceID , instanceType , region , zone
1189+ }
1190+ // k3s lives under /var/lib/rancher/k3s (check before generic rancher path)
1191+ if hostStat ("/var/lib/rancher/k3s" ) {
1192+ provider = "k3s"
1193+ return provider , instanceID , instanceType , region , zone
1194+ }
1195+ // RKE2
1196+ if hostStat ("/var/lib/rancher/rke2" ) {
1197+ provider = "rancher"
1198+ return provider , instanceID , instanceType , region , zone
1199+ }
1200+ // RKE1 — /var/lib/rancher exists but neither k3s nor rke2 sub-dirs
1201+ if hostStat ("/var/lib/rancher" ) {
1202+ provider = "rancher"
1203+ return provider , instanceID , instanceType , region , zone
1204+ }
1205+
10521206 return provider , instanceID , instanceType , region , zone
10531207}
10541208
0 commit comments