未验证 提交 d4b7d88b 编写于 作者: Z zryfish 提交者: GitHub

fix cluster status unchanged when cluster agent is already unavailable (#2188)

上级 259971c0
...@@ -34,6 +34,14 @@ import ( ...@@ -34,6 +34,14 @@ import (
"time" "time"
) )
// Cluster controller only runs under multicluster mode. Cluster controller is following below steps,
// 1. Populates proxy spec if cluster connection type is proxy
// 1.1 Wait for cluster agent is ready if connection type is proxy
// 2. Join cluster into federation control plane if kubeconfig is ready.
// 3. Pull cluster version and configz, set result to cluster status
// Also put all clusters back into queue every 5 * time.Minute to sync cluster status, this is needed
// in case there aren't any cluster changes made.
const ( const (
// maxRetries is the number of times a service will be retried before it is dropped out of the queue. // maxRetries is the number of times a service will be retried before it is dropped out of the queue.
// With the current rate-limiter in use (5ms*2^(maxRetries-1)) the following numbers represent the // With the current rate-limiter in use (5ms*2^(maxRetries-1)) the following numbers represent the
...@@ -44,6 +52,7 @@ const ( ...@@ -44,6 +52,7 @@ const (
kubefedNamespace = "kube-federation-system" kubefedNamespace = "kube-federation-system"
// Actually host cluster name can be anything, there is only necessary when calling JoinFederation function
hostClusterName = "kubesphere" hostClusterName = "kubesphere"
// allocate kubernetesAPIServer port in range [portRangeMin, portRangeMax] for agents if port is not specified // allocate kubernetesAPIServer port in range [portRangeMin, portRangeMax] for agents if port is not specified
...@@ -51,7 +60,7 @@ const ( ...@@ -51,7 +60,7 @@ const (
portRangeMin = 6000 portRangeMin = 6000
portRangeMax = 7000 portRangeMax = 7000
// Service port // Proxy service port
kubernetesPort = 6443 kubernetesPort = 6443
kubespherePort = 80 kubespherePort = 80
...@@ -307,6 +316,7 @@ func (c *clusterController) syncCluster(key string) error { ...@@ -307,6 +316,7 @@ func (c *clusterController) syncCluster(key string) error {
} }
} }
// remove our cluster finalizer
finalizers := sets.NewString(cluster.ObjectMeta.Finalizers...) finalizers := sets.NewString(cluster.ObjectMeta.Finalizers...)
finalizers.Delete(clusterv1alpha1.Finalizer) finalizers.Delete(clusterv1alpha1.Finalizer)
cluster.ObjectMeta.Finalizers = finalizers.List() cluster.ObjectMeta.Finalizers = finalizers.List()
...@@ -317,10 +327,13 @@ func (c *clusterController) syncCluster(key string) error { ...@@ -317,10 +327,13 @@ func (c *clusterController) syncCluster(key string) error {
return nil return nil
} }
// save a old copy of cluster
oldCluster := cluster.DeepCopy() oldCluster := cluster.DeepCopy()
// prepare for proxy to member cluster // prepare for proxy to member cluster
if cluster.Spec.Connection.Type == clusterv1alpha1.ConnectionTypeProxy { if cluster.Spec.Connection.Type == clusterv1alpha1.ConnectionTypeProxy {
// allocate ports for kubernetes and kubesphere endpoint
if cluster.Spec.Connection.KubeSphereAPIServerPort == 0 || if cluster.Spec.Connection.KubeSphereAPIServerPort == 0 ||
cluster.Spec.Connection.KubernetesAPIServerPort == 0 { cluster.Spec.Connection.KubernetesAPIServerPort == 0 {
port, err := c.allocatePort() port, err := c.allocatePort()
...@@ -338,6 +351,7 @@ func (c *clusterController) syncCluster(key string) error { ...@@ -338,6 +351,7 @@ func (c *clusterController) syncCluster(key string) error {
cluster.Spec.Connection.Token = c.generateToken() cluster.Spec.Connection.Token = c.generateToken()
} }
// create a proxy service spec
mcService := v1.Service{ mcService := v1.Service{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: serviceName, Name: serviceName,
...@@ -370,7 +384,7 @@ func (c *clusterController) syncCluster(key string) error { ...@@ -370,7 +384,7 @@ func (c *clusterController) syncCluster(key string) error {
} }
service, err := c.client.CoreV1().Services(defaultAgentNamespace).Get(serviceName, metav1.GetOptions{}) service, err := c.client.CoreV1().Services(defaultAgentNamespace).Get(serviceName, metav1.GetOptions{})
if err != nil { if err != nil { // proxy service not found
if errors.IsNotFound(err) { if errors.IsNotFound(err) {
service, err = c.client.CoreV1().Services(defaultAgentNamespace).Create(&mcService) service, err = c.client.CoreV1().Services(defaultAgentNamespace).Create(&mcService)
if err != nil { if err != nil {
...@@ -379,7 +393,7 @@ func (c *clusterController) syncCluster(key string) error { ...@@ -379,7 +393,7 @@ func (c *clusterController) syncCluster(key string) error {
} }
return err return err
} else { } else { // update existed proxy service
if !reflect.DeepEqual(service.Spec, mcService.Spec) { if !reflect.DeepEqual(service.Spec, mcService.Spec) {
mcService.ObjectMeta = service.ObjectMeta mcService.ObjectMeta = service.ObjectMeta
mcService.Spec.ClusterIP = service.Spec.ClusterIP mcService.Spec.ClusterIP = service.Spec.ClusterIP
...@@ -391,7 +405,7 @@ func (c *clusterController) syncCluster(key string) error { ...@@ -391,7 +405,7 @@ func (c *clusterController) syncCluster(key string) error {
} }
} }
// populated the kubernetes apiEndpoint and kubesphere apiEndpoint // populates the kubernetes apiEndpoint and kubesphere apiEndpoint
cluster.Spec.Connection.KubernetesAPIEndpoint = fmt.Sprintf("https://%s:%d", service.Spec.ClusterIP, kubernetesPort) cluster.Spec.Connection.KubernetesAPIEndpoint = fmt.Sprintf("https://%s:%d", service.Spec.ClusterIP, kubernetesPort)
cluster.Spec.Connection.KubeSphereAPIEndpoint = fmt.Sprintf("http://%s:%d", service.Spec.ClusterIP, kubespherePort) cluster.Spec.Connection.KubeSphereAPIEndpoint = fmt.Sprintf("http://%s:%d", service.Spec.ClusterIP, kubespherePort)
...@@ -415,10 +429,12 @@ func (c *clusterController) syncCluster(key string) error { ...@@ -415,10 +429,12 @@ func (c *clusterController) syncCluster(key string) error {
} }
} }
// kubeconfig not ready, nothing to do
if len(cluster.Spec.Connection.KubeConfig) == 0 { if len(cluster.Spec.Connection.KubeConfig) == 0 {
return nil return nil
} }
// build up cached cluster data if there isn't any
c.mu.Lock() c.mu.Lock()
clusterDt, ok := c.clusterMap[cluster.Name] clusterDt, ok := c.clusterMap[cluster.Name]
if !ok || clusterDt == nil || !equality.Semantic.DeepEqual(clusterDt.cachedKubeconfig, cluster.Spec.Connection.KubeConfig) { if !ok || clusterDt == nil || !equality.Semantic.DeepEqual(clusterDt.cachedKubeconfig, cluster.Spec.Connection.KubeConfig) {
...@@ -502,6 +518,19 @@ func (c *clusterController) syncCluster(key string) error { ...@@ -502,6 +518,19 @@ func (c *clusterController) syncCluster(key string) error {
c.updateClusterCondition(cluster, clusterReadyCondition) c.updateClusterCondition(cluster, clusterReadyCondition)
} }
if !isConditionTrue(cluster, clusterv1alpha1.ClusterAgentAvailable) {
clusterNotReadyCondition := clusterv1alpha1.ClusterCondition{
Type: clusterv1alpha1.ClusterReady,
Status: v1.ConditionFalse,
LastUpdateTime: metav1.Now(),
LastTransitionTime: metav1.Now(),
Reason: "Unable to establish connection with cluster",
Message: "Cluster is not available now",
}
c.updateClusterCondition(cluster, clusterNotReadyCondition)
}
if !reflect.DeepEqual(oldCluster, cluster) { if !reflect.DeepEqual(oldCluster, cluster) {
_, err = c.clusterClient.Update(cluster) _, err = c.clusterClient.Update(cluster)
if err != nil { if err != nil {
...@@ -513,6 +542,7 @@ func (c *clusterController) syncCluster(key string) error { ...@@ -513,6 +542,7 @@ func (c *clusterController) syncCluster(key string) error {
return nil return nil
} }
// tryToFetchKubeSphereComponents will send requests to member cluster configz api using kube-apiserver proxy way
func (c *clusterController) tryToFetchKubeSphereComponents(host string, transport http.RoundTripper) (map[string]bool, error) { func (c *clusterController) tryToFetchKubeSphereComponents(host string, transport http.RoundTripper) (map[string]bool, error) {
client := http.Client{ client := http.Client{
Transport: transport, Transport: transport,
...@@ -569,6 +599,7 @@ func (c *clusterController) handleErr(err error, key interface{}) { ...@@ -569,6 +599,7 @@ func (c *clusterController) handleErr(err error, key interface{}) {
utilruntime.HandleError(err) utilruntime.HandleError(err)
} }
// isConditionTrue checks cluster specific condition value is True, return false if condition not exists
func isConditionTrue(cluster *clusterv1alpha1.Cluster, conditionType clusterv1alpha1.ClusterConditionType) bool { func isConditionTrue(cluster *clusterv1alpha1.Cluster, conditionType clusterv1alpha1.ClusterConditionType) bool {
for _, condition := range cluster.Status.Conditions { for _, condition := range cluster.Status.Conditions {
if condition.Type == conditionType && condition.Status == v1.ConditionTrue { if condition.Type == conditionType && condition.Status == v1.ConditionTrue {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册