From 20c75956fd990b5c0d1cd6473914e8bb644cdd29 Mon Sep 17 00:00:00 2001 From: Quinton Hoole Date: Wed, 25 May 2016 16:41:18 -0700 Subject: [PATCH 1/2] Add federation cluster status zone and region update. --- .../cluster/cluster_client.go | 55 +++++++++++++++++++ .../cluster/clustercontroller.go | 22 ++++++++ 2 files changed, 77 insertions(+) diff --git a/federation/pkg/federation-controller/cluster/cluster_client.go b/federation/pkg/federation-controller/cluster/cluster_client.go index 12df45edc46..d177c7709ce 100644 --- a/federation/pkg/federation-controller/cluster/cluster_client.go +++ b/federation/pkg/federation-controller/cluster/cluster_client.go @@ -22,15 +22,19 @@ import ( "os" "strings" + "github.com/golang/glog" federation_v1alpha1 "k8s.io/kubernetes/federation/apis/federation/v1alpha1" + "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/v1" + clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/typed/discovery" client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" utilnet "k8s.io/kubernetes/pkg/util/net" + "k8s.io/kubernetes/pkg/util/sets" ) const ( @@ -153,3 +157,54 @@ func (self *ClusterClient) GetClusterHealthStatus() *federation_v1alpha1.Cluster } return &clusterStatus } + +// GetClusterZones gets the kubernetes cluster zones and region by inspecting labels on nodes in the cluster. +func GetClusterZones(client *clientset.Clientset) (zones []string, region string, err error) { + return getZoneNames(client) +} + +// Find the name of the zone in which a Node is running +func getZoneNameForNode(node api.Node) (string, error) { + for key, value := range node.Labels { + if key == unversioned.LabelZoneFailureDomain { + return value, nil + } + } + return "", fmt.Errorf("Zone name for node %s not found. No label with key %s", + node.Name, unversioned.LabelZoneFailureDomain) +} + +// Find the name of the region in which a Node is running +func getRegionNameForNode(node api.Node) (string, error) { + for key, value := range node.Labels { + if key == unversioned.LabelZoneRegion { + return value, nil + } + } + return "", fmt.Errorf("Region name for node %s not found. No label with key %s", + node.Name, unversioned.LabelZoneRegion) +} + +// Find the names of all zones and the region in which we have nodes in this cluster. +func getZoneNames(client *clientset.Clientset) (zones []string, region string, err error) { + zoneNames := sets.NewString() + nodes, err := client.Core().Nodes().List(api.ListOptions{}) + if err != nil { + glog.Errorf("Failed to list nodes while getting zone names: %v", err) + return nil, "", err + } + for i, node := range nodes.Items { + zoneName, err := getZoneNameForNode(node) + if err != nil { + return nil, "", err + } + zoneNames.Insert(zoneName) + if i == 0 { + region, err = getRegionNameForNode(node) + if err != nil { + return nil, "", err + } + } + } + return zoneNames.List(), region, nil +} diff --git a/federation/pkg/federation-controller/cluster/clustercontroller.go b/federation/pkg/federation-controller/cluster/clustercontroller.go index 3b1ae48e9ac..f3a10982a96 100644 --- a/federation/pkg/federation-controller/cluster/clustercontroller.go +++ b/federation/pkg/federation-controller/cluster/clustercontroller.go @@ -27,6 +27,9 @@ import ( federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_release_1_3" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/client/cache" + clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + "k8s.io/kubernetes/pkg/client/restclient" + "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller/framework" "k8s.io/kubernetes/pkg/runtime" @@ -184,6 +187,14 @@ func (cc *ClusterController) UpdateClusterStatus() error { } } } + clusterClientSet, _ := NewClusterClientset(&cluster) + zones, region, err := GetClusterZones(clusterClientSet) + if err != nil { + glog.Errorf("Failed to get zones and region for cluster %s: %v", cluster.Name, err) + } else { + clusterStatusNew.Zones = zones + clusterStatusNew.Region = region + } cc.clusterClusterStatusMap[cluster.Name] = *clusterStatusNew cluster.Status = *clusterStatusNew cluster, err := cc.federationClient.Federation().Clusters().UpdateStatus(&cluster) @@ -194,3 +205,14 @@ func (cc *ClusterController) UpdateClusterStatus() error { } return nil } + +func NewClusterClientset(c *federation_v1alpha1.Cluster) (*clientset.Clientset, error) { // TODO: Stolen from federation/pkg/federation-controller/service/cluster_helper.go - factor it out of there. + clusterConfig, err := clientcmd.BuildConfigFromFlags(c.Spec.ServerAddressByClientCIDRs[0].ServerAddress, "") + if err != nil { + return nil, err + } + clusterConfig.QPS = KubeAPIQPS + clusterConfig.Burst = KubeAPIBurst + clientset := clientset.NewForConfigOrDie(restclient.AddUserAgent(clusterConfig, UserAgentName)) + return clientset, nil +} From 85a0de33005bfb738109c9a62ca1f5e131ef61bb Mon Sep 17 00:00:00 2001 From: Quinton Hoole Date: Sat, 28 May 2016 11:12:59 -0700 Subject: [PATCH 2/2] Use secrets to configure kube clients in federation cluster controller, and cache kube clients. --- .../cluster/cluster_client.go | 14 +++++++-- .../cluster/clustercontroller.go | 29 +++++++------------ 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/federation/pkg/federation-controller/cluster/cluster_client.go b/federation/pkg/federation-controller/cluster/cluster_client.go index d177c7709ce..7f5aa57e217 100644 --- a/federation/pkg/federation-controller/cluster/cluster_client.go +++ b/federation/pkg/federation-controller/cluster/cluster_client.go @@ -72,6 +72,7 @@ var KubeconfigGetterForCluster = func(c *federation_v1alpha1.Cluster) clientcmd. type ClusterClient struct { discoveryClient *discovery.DiscoveryClient + kubeClient *clientset.Clientset } func NewClusterClientSet(c *federation_v1alpha1.Cluster) (*ClusterClient, error) { @@ -105,6 +106,10 @@ func NewClusterClientSet(c *federation_v1alpha1.Cluster) (*ClusterClient, error) if clusterClientSet.discoveryClient == nil { return nil, nil } + clusterClientSet.kubeClient = clientset.NewForConfigOrDie((restclient.AddUserAgent(clusterConfig, UserAgentName))) + if clusterClientSet.kubeClient == nil { + return nil, nil + } } return &clusterClientSet, err } @@ -159,8 +164,8 @@ func (self *ClusterClient) GetClusterHealthStatus() *federation_v1alpha1.Cluster } // GetClusterZones gets the kubernetes cluster zones and region by inspecting labels on nodes in the cluster. -func GetClusterZones(client *clientset.Clientset) (zones []string, region string, err error) { - return getZoneNames(client) +func (self *ClusterClient) GetClusterZones() (zones []string, region string, err error) { + return getZoneNames(self.kubeClient) } // Find the name of the zone in which a Node is running @@ -194,6 +199,11 @@ func getZoneNames(client *clientset.Clientset) (zones []string, region string, e return nil, "", err } for i, node := range nodes.Items { + // TODO: quinton-hoole make this more efficient. + // For non-multi-zone clusters the zone will + // be identical for all nodes, so we only need to look at one node + // For multi-zone clusters we know at build time + // which zones are included. Rather get this info from there, because it's cheaper. zoneName, err := getZoneNameForNode(node) if err != nil { return nil, "", err diff --git a/federation/pkg/federation-controller/cluster/clustercontroller.go b/federation/pkg/federation-controller/cluster/clustercontroller.go index f3a10982a96..1d3d2d5b88b 100644 --- a/federation/pkg/federation-controller/cluster/clustercontroller.go +++ b/federation/pkg/federation-controller/cluster/clustercontroller.go @@ -27,9 +27,6 @@ import ( federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_release_1_3" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller/framework" "k8s.io/kubernetes/pkg/runtime" @@ -187,10 +184,16 @@ func (cc *ClusterController) UpdateClusterStatus() error { } } } - clusterClientSet, _ := NewClusterClientset(&cluster) - zones, region, err := GetClusterZones(clusterClientSet) + clusterClient, found := cc.clusterKubeClientMap[cluster.Name] + if !found { + glog.Warningf("Failed to client for cluster %s", cluster.Name) + continue + } + + zones, region, err := clusterClient.GetClusterZones() if err != nil { - glog.Errorf("Failed to get zones and region for cluster %s: %v", cluster.Name, err) + glog.Warningf("Failed to get zones and region for cluster %s: %v", cluster.Name, err) + // Don't return err here, as we want the rest of the status update to proceed. } else { clusterStatusNew.Zones = zones clusterStatusNew.Region = region @@ -199,20 +202,10 @@ func (cc *ClusterController) UpdateClusterStatus() error { cluster.Status = *clusterStatusNew cluster, err := cc.federationClient.Federation().Clusters().UpdateStatus(&cluster) if err != nil { - glog.Infof("Failed to update the status of cluster: %v ,error is : %v", cluster.Name, err) + glog.Warningf("Failed to update the status of cluster: %v ,error is : %v", cluster.Name, err) + // Don't return err here, as we want to continue processing remaining clusters. continue } } return nil } - -func NewClusterClientset(c *federation_v1alpha1.Cluster) (*clientset.Clientset, error) { // TODO: Stolen from federation/pkg/federation-controller/service/cluster_helper.go - factor it out of there. - clusterConfig, err := clientcmd.BuildConfigFromFlags(c.Spec.ServerAddressByClientCIDRs[0].ServerAddress, "") - if err != nil { - return nil, err - } - clusterConfig.QPS = KubeAPIQPS - clusterConfig.Burst = KubeAPIBurst - clientset := clientset.NewForConfigOrDie(restclient.AddUserAgent(clusterConfig, UserAgentName)) - return clientset, nil -}