pkg/common/config.go (160 lines of code) (raw):

// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package common import ( "errors" "fmt" "os" "strings" "time" "cloud.google.com/go/compute/metadata" appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( DefaultMode = "cluster" DefaultReportInterval = time.Duration(1 * time.Minute) ModeNode = "node" ModeCluster = "cluster" UserAgent = "google-pso-tool/gke-prober/v0.0.2" WarmingPeriod = 5 * time.Minute AddonNameAnnotation = "components.gke.io/component-name" AddonVersionAnnotation = "components.gke.io/component-version" ) var MetricPrefix string type Config struct { ProjectID string Location string Cluster string Mode string NodeName string NodeIP string Nodepool string HostNetwork bool ReportInterval time.Duration ConnProbes bool ClusterProbes bool NodeProbes bool UserAgent string MetricPrefix string } type Addon struct { Name string Kind string Version string } func (a Addon) String() string { return fmt.Sprintf("[%s: %s (%s)]", a.Kind, a.Name, a.Version) } // AddonFromPod returns an Addon from a pod, and whether an Addon was successfully identified. func AddonFromPod(p *v1.Pod) (Addon, bool) { addonName, addonVersion, ok := addonMetaFromObjectMeta(p.ObjectMeta) if !ok { return Addon{}, false } // TODO: recursively get owner references up to root for _, ref := range p.OwnerReferences { if ref.APIVersion == "apps/v1" && *ref.Controller == true { if ref.Kind == "ReplicaSet" { return Addon{ Name: addonName, Kind: "Deployment", Version: addonVersion, }, true } else { return Addon{ Name: addonName, Kind: ref.Kind, Version: addonVersion, }, true } } } return Addon{}, false } func AddonFromDaemonSet(d *appsv1.DaemonSet) (Addon, bool) { addonName, addonVersion, ok := addonMetaFromObjectMeta(d.Spec.Template.ObjectMeta) if !ok { return Addon{}, false } return Addon{ Name: addonName, Kind: "DaemonSet", Version: addonVersion, }, true } func AddonFromDeployment(d *appsv1.Deployment) (Addon, bool) { addonName, addonVersion, ok := addonMetaFromObjectMeta(d.Spec.Template.ObjectMeta) if !ok { return Addon{}, false } return Addon{ Name: addonName, Kind: "Deployment", Version: addonVersion, }, true } // AddonMetaFromObjectMeta returns the addon Name, Version, and success. func addonMetaFromObjectMeta(m metav1.ObjectMeta) (string, string, bool) { if !metav1.HasAnnotation(m, AddonNameAnnotation) || !metav1.HasAnnotation(m, AddonVersionAnnotation) { return "", "", false } return m.Annotations[AddonNameAnnotation], m.Annotations[AddonVersionAnnotation], true } func GetConfig() Config { mode := os.Getenv("PROBER_MODE") if mode == "" { mode = DefaultMode } nodeIP := os.Getenv("NODE_IP") if mode == ModeNode && nodeIP == "" { panic(errors.New("can't determine node IP for node mode")) } hostNetwork := os.Getenv("POD_IP") == nodeIP reportInterval, _ := time.ParseDuration(os.Getenv("REPORT_INTERVAL")) if reportInterval == 0 { reportInterval = DefaultReportInterval } // Enable Cluster Prober to probe the cluster-wide addon services like metrics-server, kube-dns and so on clusterProbes := os.Getenv("ENABLE_CLUSTER_PROBES") == "true" nodeProbes := os.Getenv("ENABLE_NODE_PROBES") == "true" connProbes := os.Getenv("ENABLE_CONNECTIVITY_PROBES") == "true" projectID, location, clusterName, nodeName := getMetadata(mode) pool := strings.TrimPrefix(nodeName, fmt.Sprintf("gke-%s-", clusterName)) // Strip off ending node identifiers ("-13a25f43-chwu") pool = pool[:len(pool)-14] return Config{ ProjectID: projectID, Location: location, Cluster: clusterName, Mode: mode, NodeName: nodeName, NodeIP: nodeIP, Nodepool: pool, HostNetwork: hostNetwork, ReportInterval: reportInterval, ConnProbes: connProbes, ClusterProbes: clusterProbes, NodeProbes: nodeProbes, UserAgent: UserAgent, MetricPrefix: MetricPrefix, } } // Returns best effort for: project, location, cluster name func getMetadata(mode string) (project, location, cluster, nodename string) { project, _ = metadata.ProjectID() location = "local" switch mode { case ModeCluster: // For regional clusters, this will be a region rather than zone location, _ = metadata.InstanceAttributeValue("cluster-location") case ModeNode: location, _ = metadata.Zone() } cluster, _ = metadata.InstanceAttributeValue("cluster-name") // We would normally use metadata.InstanceName() but alas, // that is not available via the GKE metadata server var err error if nodename, err = metadata.Hostname(); err != nil { panic(fmt.Errorf("can't determine hostname from metadata server: %v\n", err)) } // Remove domain portions nodename = strings.Split(nodename, ".")[0] return } func init() { if prefix, ok := os.LookupEnv("METRIC_PREFIX"); ok { MetricPrefix = "workload.googleapis.com/" + prefix } else { MetricPrefix = "workload.googleapis.com/gke-prober" } }