From d2e06c1b0799388e52a29d4e6ad76cfde657e7f5 Mon Sep 17 00:00:00 2001 From: Oleksii Khliupin Date: Wed, 27 Feb 2019 10:08:02 -0500 Subject: [PATCH] Distinguish between gke_container and k8s_container monitored resource type (#90) * Distinguish between gke_container and k8s_container monitored resource type * remove unused field * add nil check --- monitoredresource/gcp_metadata_config.go | 27 +++++++++++++++++ monitoredresource/monitored_resources.go | 24 ++++++++++----- monitoredresource/monitored_resources_test.go | 30 +++++++++++++++++++ 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/monitoredresource/gcp_metadata_config.go b/monitoredresource/gcp_metadata_config.go index ceb754e..412e347 100644 --- a/monitoredresource/gcp_metadata_config.go +++ b/monitoredresource/gcp_metadata_config.go @@ -15,11 +15,15 @@ package monitoredresource import ( + "context" + "fmt" "log" "os" "strings" "cloud.google.com/go/compute/metadata" + "cloud.google.com/go/container/apiv1" + containerpb "google.golang.org/genproto/googleapis/container/v1" ) // gcpMetadata represents metadata retrieved from GCP (GKE and GCE) environment. @@ -45,6 +49,8 @@ type gcpMetadata struct { // zone is the Compute Engine zone in which the VM is running. zone string + + monitoringV2 bool } // retrieveGCPMetadata retrieves value of each Attribute from Metadata Server @@ -70,6 +76,9 @@ func retrieveGCPMetadata() *gcpMetadata { logError(err) gcpMetadata.clusterName = strings.TrimSpace(clusterName) + clusterLocation, err := metadata.InstanceAttributeValue("cluster-location") + logError(err) + // Following attributes are derived from environment variables. They are configured // via yaml file. For details refer to: // https://cloud.google.com/kubernetes-engine/docs/tutorials/custom-metrics-autoscaling#exporting_metrics_from_the_application @@ -77,6 +86,24 @@ func retrieveGCPMetadata() *gcpMetadata { gcpMetadata.containerName = os.Getenv("CONTAINER_NAME") gcpMetadata.podID = os.Getenv("HOSTNAME") + // Monitoring API version can be obtained from cluster info.q + if gcpMetadata.clusterName != "" { + ctx := context.Background() + c, err := container.NewClusterManagerClient(ctx) + logError(err) + if c != nil { + req := &containerpb.GetClusterRequest{ + Name: fmt.Sprintf("projects/%s/locations/%s/clusters/%s", gcpMetadata.projectID, strings.TrimSpace(clusterLocation), gcpMetadata.clusterName), + } + resp, err := c.GetCluster(ctx, req) + logError(err) + if resp != nil && resp.GetMonitoringService() == "monitoring.googleapis.com/kubernetes" && + resp.GetLoggingService() == "logging.googleapis.com/kubernetes" { + gcpMetadata.monitoringV2 = true + } + } + } + return &gcpMetadata } diff --git a/monitoredresource/monitored_resources.go b/monitoredresource/monitored_resources.go index c07e55c..139f1c0 100644 --- a/monitoredresource/monitored_resources.go +++ b/monitoredresource/monitored_resources.go @@ -52,6 +52,9 @@ type GKEContainer struct { // Zone is the Compute Engine zone in which the VM is running. Zone string + + // LoggingMonitoringV2Enabled is the identifier if user enabled V2 logging and monitoring for GKE + LoggingMonitoringV2Enabled bool } // MonitoredResource returns resource type and resource labels for GKEContainer @@ -65,7 +68,11 @@ func (gke *GKEContainer) MonitoredResource() (resType string, labels map[string] "namespace_id": gke.NamespaceID, "pod_id": gke.PodID, } - return "gke_container", labels + typ := "gke_container" + if gke.LoggingMonitoringV2Enabled { + typ = "k8s_container" + } + return typ, labels } // GCEInstance represents gce_instance type monitored resource. @@ -187,13 +194,14 @@ func createGCEInstanceMonitoredResource(gcpMetadata *gcpMetadata) *GCEInstance { // gcpMetadata contains GCP (GKE or GCE) specific attributes. func createGKEContainerMonitoredResource(gcpMetadata *gcpMetadata) *GKEContainer { gkeContainer := GKEContainer{ - ProjectID: gcpMetadata.projectID, - InstanceID: gcpMetadata.instanceID, - Zone: gcpMetadata.zone, - ContainerName: gcpMetadata.containerName, - ClusterName: gcpMetadata.clusterName, - NamespaceID: gcpMetadata.namespaceID, - PodID: gcpMetadata.podID, + ProjectID: gcpMetadata.projectID, + InstanceID: gcpMetadata.instanceID, + Zone: gcpMetadata.zone, + ContainerName: gcpMetadata.containerName, + ClusterName: gcpMetadata.clusterName, + NamespaceID: gcpMetadata.namespaceID, + PodID: gcpMetadata.podID, + LoggingMonitoringV2Enabled: gcpMetadata.monitoringV2, } return &gkeContainer } diff --git a/monitoredresource/monitored_resources_test.go b/monitoredresource/monitored_resources_test.go index 3bbffdc..23d7238 100644 --- a/monitoredresource/monitored_resources_test.go +++ b/monitoredresource/monitored_resources_test.go @@ -58,6 +58,36 @@ func TestGKEContainerMonitoredResources(t *testing.T) { } } +func TestGKEContainerMonitoredResourcesV2(t *testing.T) { + os.Setenv("KUBERNETES_SERVICE_HOST", "127.0.0.1") + gcpMetadata := gcpMetadata{ + instanceID: GCPInstanceIDStr, + projectID: GCPProjectIDStr, + zone: GCPZoneStr, + clusterName: GKEClusterNameStr, + containerName: GKEContainerNameStr, + namespaceID: GKENamespaceStr, + podID: GKEPodIDStr, + monitoringV2: true, + } + autoDetected := detectResourceType(nil, &gcpMetadata) + + if autoDetected == nil { + t.Fatal("GKEContainerMonitoredResource nil") + } + resType, labels := autoDetected.MonitoredResource() + if resType != "k8s_container" || + labels["instance_id"] != GCPInstanceIDStr || + labels["project_id"] != GCPProjectIDStr || + labels["cluster_name"] != GKEClusterNameStr || + labels["container_name"] != GKEContainerNameStr || + labels["zone"] != GCPZoneStr || + labels["namespace_id"] != GKENamespaceStr || + labels["pod_id"] != GKEPodIDStr { + t.Errorf("GKEContainerMonitoredResourceV2 Failed: %v", autoDetected) + } +} + func TestGCEInstanceMonitoredResources(t *testing.T) { os.Setenv("KUBERNETES_SERVICE_HOST", "") gcpMetadata := gcpMetadata{