reconcile host cluster (#2354)

print friendly error when component failed

update dockerfile
This commit is contained in:
zryfish
2020-07-08 23:55:13 +08:00
committed by GitHub
parent 99aff3c7da
commit 693a4143db
18 changed files with 328 additions and 101 deletions

View File

@@ -70,8 +70,35 @@ const (
// proxy format
proxyFormat = "%s/api/v1/namespaces/kubesphere-system/services/:ks-apiserver:80/proxy/%s"
// mulitcluster configuration name
configzMultiCluster = "multicluster"
)
// Cluster template for reconcile host cluster if there is none.
var hostCluster = &clusterv1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "host",
Annotations: map[string]string{
"kubesphere.io/description": "Automatically created by kubesphere, " +
"we encourage you use host cluster for cluster management only, " +
"deploy workloads to member clusters.",
},
Labels: map[string]string{
clusterv1alpha1.HostCluster: "",
clusterv1alpha1.ClusterGroup: "production",
},
},
Spec: clusterv1alpha1.ClusterSpec{
JoinFederation: true,
Enable: true,
Provider: "kubesphere",
Connection: clusterv1alpha1.Connection{
Type: clusterv1alpha1.ConnectionTypeDirect,
},
},
}
// ClusterData stores cluster client
type clusterData struct {
@@ -176,11 +203,17 @@ func (c *clusterController) Run(workers int, stopCh <-chan struct{}) error {
go wait.Until(c.worker, c.workerLoopPeriod, stopCh)
}
// refresh cluster configz every 2 minutes
go wait.Until(func() {
if err := c.syncStatus(); err != nil {
klog.Errorf("Error periodically sync cluster status, %v", err)
}
}, 5*time.Minute, stopCh)
if err := c.reconcileHostCluster(); err != nil {
klog.Errorf("Error create host cluster, error %v", err)
}
}, 2*time.Minute, stopCh)
<-stopCh
return nil
@@ -256,6 +289,26 @@ func (c *clusterController) syncStatus() error {
return nil
}
// reconcileHostCluster will create a host cluster if there are no clusters labeled 'cluster-role.kubesphere.io/host'
func (c *clusterController) reconcileHostCluster() error {
clusters, err := c.clusterLister.List(labels.SelectorFromSet(labels.Set{clusterv1alpha1.HostCluster: ""}))
if err != nil {
return err
}
if len(clusters) == 0 {
hostKubeConfig, err := buildKubeconfigFromRestConfig(c.hostConfig)
if err != nil {
return err
}
hostCluster.Spec.Connection.KubeConfig = hostKubeConfig
_, err = c.clusterClient.Create(hostCluster)
return err
}
return nil
}
func (c *clusterController) syncCluster(key string) error {
startTime := time.Now()
@@ -524,6 +577,14 @@ func (c *clusterController) syncCluster(key string) error {
cluster.Status.Configz = configz
}
// label cluster host cluster if configz["multicluster"]==true, this is
if mc, ok := configz[configzMultiCluster]; ok && mc && c.checkIfClusterIsHostCluster(nodes) {
if cluster.Labels == nil {
cluster.Labels = make(map[string]string)
}
cluster.Labels[clusterv1alpha1.HostCluster] = ""
}
clusterReadyCondition := clusterv1alpha1.ClusterCondition{
Type: clusterv1alpha1.ClusterReady,
Status: v1.ConditionTrue,
@@ -577,6 +638,27 @@ func (c *clusterController) syncCluster(key string) error {
return nil
}
func (c *clusterController) checkIfClusterIsHostCluster(memberClusterNodes *v1.NodeList) bool {
hostNodes, err := c.client.CoreV1().Nodes().List(metav1.ListOptions{})
if err != nil {
return false
}
if hostNodes == nil || memberClusterNodes == nil {
return false
}
if len(hostNodes.Items) != len(memberClusterNodes.Items) {
return false
}
if len(hostNodes.Items) > 0 && (hostNodes.Items[0].Status.NodeInfo.MachineID != memberClusterNodes.Items[0].Status.NodeInfo.MachineID) {
return false
}
return true
}
// 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) {
client := http.Client{
@@ -671,16 +753,6 @@ func (c *clusterController) updateClusterCondition(cluster *clusterv1alpha1.Clus
}
}
func isHostCluster(cluster *clusterv1alpha1.Cluster) bool {
for k, v := range cluster.Annotations {
if k == clusterv1alpha1.IsHostCluster && v == "true" {
return true
}
}
return false
}
// joinFederation joins a cluster into federation clusters.
// return nil error if kubefed cluster already exists.
func (c *clusterController) joinFederation(clusterConfig *rest.Config, joiningClusterName string, labels map[string]string) (*fedv1b1.KubeFedCluster, error) {

View File

@@ -1 +1,37 @@
package cluster
import (
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/clientcmd/api"
)
func buildKubeconfigFromRestConfig(config *rest.Config) ([]byte, error) {
apiConfig := api.NewConfig()
apiConfig.Clusters["kubernetes"] = &api.Cluster{
Server: config.Host,
CertificateAuthorityData: config.CAData,
CertificateAuthority: config.CAFile,
}
apiConfig.AuthInfos["kubernetes-admin"] = &api.AuthInfo{
ClientCertificate: config.CertFile,
ClientCertificateData: config.CertData,
ClientKey: config.KeyFile,
ClientKeyData: config.KeyData,
TokenFile: config.BearerTokenFile,
Token: config.BearerToken,
Username: config.Username,
Password: config.Password,
}
apiConfig.Contexts["kubernetes-admin@kubernetes"] = &api.Context{
Cluster: "kubernetes",
AuthInfo: "kubernetes-admin",
}
apiConfig.CurrentContext = "kubernetes-admin@kubernetes"
return clientcmd.Write(*apiConfig)
}