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

@@ -10,7 +10,7 @@ const (
ResourcesSingularCluster = "cluster"
ResourcesPluralCluster = "clusters"
IsHostCluster = "cluster.kubesphere.io/is-host-cluster"
HostCluster = "cluster-role.kubesphere.io/host"
// Description of which region the cluster been placed
ClusterRegion = "cluster.kubesphere.io/region"
// Name of the cluster group

View File

@@ -260,10 +260,8 @@ func isClusterReady(cluster *clusterv1alpha1.Cluster) bool {
}
func isClusterHostCluster(cluster *clusterv1alpha1.Cluster) bool {
for key, value := range cluster.Annotations {
if key == clusterv1alpha1.IsHostCluster && value == "true" {
return true
}
if _, ok := cluster.Labels[clusterv1alpha1.HostCluster]; ok {
return true
}
return false

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)
}

View File

@@ -24,14 +24,18 @@ import (
)
var (
version = "v0.0.0"
gitVersion = "v0.0.0"
gitCommit = "unknown"
gitTreeState = "unknown"
buildDate = "unknown"
gitMajor = "unknown"
gitMinor = "unknown"
)
type Info struct {
Version string `json:"gitVersion"`
GitVersion string `json:"gitVersion"`
GitMajor string `json:"gitMajor"`
GitMinor string `json:"gitMinor"`
GitCommit string `json:"gitCommit"`
GitTreeState string `json:"gitTreeState"`
BuildDate string `json:"buildDate"`
@@ -47,7 +51,8 @@ func Get() Info {
// These variables typically come from -ldflags settings and
// in their absence fallback to the default settings
return Info{
Version: version,
GitVersion: gitVersion,
GitCommit: gitCommit,
GitTreeState: gitTreeState,
BuildDate: buildDate,