refactor deploy ks

Signed-off-by: pixiake <guofeng@yunify.com>
This commit is contained in:
pixiake 2020-08-12 10:33:40 +08:00
parent 2ec9b7c5fe
commit 45cd5b549b
19 changed files with 816 additions and 176 deletions

View File

@ -21,7 +21,7 @@ import (
)
// clusterCmd represents the cluster command
var ksCmd = &cobra.Command{
var deployKsCmd = &cobra.Command{
Use: "kubesphere",
Short: "Deploy KubeSphere on the existing K8s",
RunE: func(cmd *cobra.Command, args []string) error {
@ -30,9 +30,9 @@ var ksCmd = &cobra.Command{
}
func init() {
deployCmd.AddCommand(ksCmd)
deployCmd.AddCommand(deployKsCmd)
ksCmd.Flags().StringVarP(&opt.Kubeconfig, "kubeconfig", "", "", "Specify a kubeconfig file")
ksCmd.Flags().StringVarP(&opt.KsVersion, "version", "v", "v3.0.0", "Specify a supported version of kubesphere")
ksCmd.Flags().StringVarP(&opt.Registry, "registry", "", "", "Specify a image registry address")
deployKsCmd.Flags().StringVarP(&opt.Kubeconfig, "kubeconfig", "", "", "Specify a kubeconfig file")
deployKsCmd.Flags().StringVarP(&opt.KsVersion, "version", "v", "v3.0.0", "Specify a supported version of kubesphere")
deployKsCmd.Flags().StringVarP(&opt.Registry, "registry", "", "", "Specify a image registry address")
}

View File

@ -208,4 +208,4 @@ func serveCRMetrics(cfg *rest.Config, operatorNs string) error {
return err
}
return nil
}
}

38
cmd/upgradeKs.go Normal file
View File

@ -0,0 +1,38 @@
/*
Copyright 2020 The KubeSphere Authors.
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 cmd
import (
"github.com/kubesphere/kubekey/pkg/upgrade"
"github.com/spf13/cobra"
)
// clusterCmd represents the cluster command
var upgradeKsCmd = &cobra.Command{
Use: "kubesphere",
Short: "Deploy KubeSphere on the existing K8s",
RunE: func(cmd *cobra.Command, args []string) error {
return upgrade.KsToV3(opt.KsVersion, opt.Registry, opt.Kubeconfig)
},
}
func init() {
upgradeCmd.AddCommand(upgradeKsCmd)
upgradeKsCmd.Flags().StringVarP(&opt.Kubeconfig, "kubeconfig", "", "", "Specify a kubeconfig file")
upgradeKsCmd.Flags().StringVarP(&opt.KsVersion, "version", "v", "v3.0.0", "Specify a supported version of kubesphere")
upgradeKsCmd.Flags().StringVarP(&opt.Registry, "registry", "", "", "Specify a image registry address")
}

View File

@ -89,7 +89,6 @@ type HostCfg struct {
IsEtcd bool `json:"-"`
IsMaster bool `json:"-"`
IsWorker bool `json:"-"`
IsClient bool `json:"-"`
}
type RoleGroups struct {

View File

@ -19,14 +19,13 @@ var (
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
// SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
AddToScheme = SchemeBuilder.AddToScheme
)
func init() {
SchemeBuilder.Register(addKnownTypes)
}
// Kind takes an unqualified kind and returns GroupKind
func Kind(kind string) schema.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
@ -41,7 +40,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&Cluster{},
&ClusterList{},
)
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

View File

@ -22,14 +22,11 @@ import (
"encoding/base64"
"fmt"
kubekeyapi "github.com/kubesphere/kubekey/pkg/apis/kubekey/v1alpha1"
"github.com/kubesphere/kubekey/pkg/kubesphere"
"github.com/kubesphere/kubekey/pkg/util"
"github.com/lithammer/dedent"
"github.com/pkg/errors"
"github.com/spf13/viper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"net"
"os"
"os/exec"
@ -78,9 +75,6 @@ spec:
registry:
privateRegistry: ""
{{ if .Options.KubeSphereEnabled }}
{{ .Options.KubeSphereConfigMap }}
{{ end }}
`)))
)
@ -108,28 +102,10 @@ type OptionsCluster struct {
ControlPlaneEndpointDomain string
ControlPlaneEndpointAddress string
ControlPlaneEndpointPort string
KubeSphereConfigMap string
KubeSphereEnabled bool
}
func GetInfoFromCluster(config, name string) (*OptionsCluster, error) {
var kubeconfig string
if config != "" {
config, err := filepath.Abs(config)
if err != nil {
return nil, errors.Wrap(err, "Failed to look up current directory")
}
kubeconfig = config
} else {
kubeconfig = filepath.Join(homeDir(), ".kube", "config")
}
// use the current context in kubeconfig
configCluster, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
return nil, err
}
// create the clientset
clientset, err := kubernetes.NewForConfig(configCluster)
clientset, err := util.NewClient(config)
if err != nil {
return nil, err
}
@ -213,6 +189,9 @@ func GetInfoFromCluster(config, name string) (*OptionsCluster, error) {
}
pods, err := clientset.CoreV1().Pods("kube-system").List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, err
}
for _, pod := range pods.Items {
if strings.Contains(pod.Name, "calico") {
opt.NetworkPlugin = "calico"
@ -242,27 +221,12 @@ func GetInfoFromCluster(config, name string) (*OptionsCluster, error) {
return &opt, nil
}
func GenerateConfigFromCluster(cfgPath, kubeconfig, name, ksVersion string, ksEnabled bool) error {
func GenerateConfigFromCluster(cfgPath, kubeconfig, name string) error {
opt, err := GetInfoFromCluster(kubeconfig, name)
if err != nil {
return err
}
if ksEnabled {
switch strings.TrimSpace(ksVersion) {
case "":
opt.KubeSphereConfigMap = kubesphere.V3_0_0
case "v3.0.0":
opt.KubeSphereConfigMap = kubesphere.V3_0_0
case "v2.1.1":
opt.KubeSphereConfigMap = kubesphere.V2_1_1
default:
return errors.New(fmt.Sprintf("Unsupported version: %s", strings.TrimSpace(ksVersion)))
}
}
opt.KubeSphereEnabled = ksEnabled
ClusterCfgStr, err := GenerateClusterCfgStr(opt)
if err != nil {
return errors.Wrap(err, "Faild to generate cluster config")
@ -291,10 +255,3 @@ func GenerateConfigFromCluster(cfgPath, kubeconfig, name, ksVersion string, ksEn
return nil
}
func homeDir() string {
if h := os.Getenv("HOME"); h != "" {
return h
}
return os.Getenv("USERPROFILE") // windows
}

View File

@ -153,7 +153,7 @@ func GenerateClusterObjStr(opt *Options, storageNum int) (string, error) {
func GenerateClusterObj(addons, k8sVersion, ksVersion, name, kubeconfig, clusterCfgPath string, ksEnabled, fromCluster bool) error {
if fromCluster {
err := GenerateConfigFromCluster(clusterCfgPath, kubeconfig, name, ksVersion, ksEnabled)
err := GenerateConfigFromCluster(clusterCfgPath, kubeconfig, name)
if err != nil {
return err
}

View File

@ -43,7 +43,7 @@ func ParseClusterCfg(clusterCfgPath, k8sVersion, ksVersion string, ksEnabled boo
}
clusterCfg = AllinoneCfg(user, k8sVersion, ksVersion, ksEnabled, logger)
} else {
cfg, err := ParseCfg(clusterCfgPath, k8sVersion)
cfg, err := ParseCfg(clusterCfgPath, k8sVersion, ksVersion, ksEnabled)
if err != nil {
return nil, err
}
@ -53,7 +53,7 @@ func ParseClusterCfg(clusterCfgPath, k8sVersion, ksVersion string, ksEnabled boo
return clusterCfg, nil
}
func ParseCfg(clusterCfgPath, k8sVersion string) (*kubekeyapi.Cluster, error) {
func ParseCfg(clusterCfgPath, k8sVersion, ksVersion string, ksEnabled bool) (*kubekeyapi.Cluster, error) {
clusterCfg := kubekeyapi.Cluster{}
fp, err := filepath.Abs(clusterCfgPath)
if err != nil {
@ -106,6 +106,24 @@ func ParseCfg(clusterCfgPath, k8sVersion string) (*kubekeyapi.Cluster, error) {
}
}
}
if ksEnabled {
clusterCfg.Spec.KubeSphere.Enabled = true
switch strings.TrimSpace(ksVersion) {
case "":
clusterCfg.Spec.KubeSphere.Version = "v3.0.0"
clusterCfg.Spec.KubeSphere.Configurations = kubesphere.V3_0_0
case "v3.0.0":
clusterCfg.Spec.KubeSphere.Version = "v3.0.0"
clusterCfg.Spec.KubeSphere.Configurations = kubesphere.V3_0_0
case "v2.1.1":
clusterCfg.Spec.KubeSphere.Version = "v2.1.1"
clusterCfg.Spec.KubeSphere.Configurations = kubesphere.V2_1_1
default:
return nil, errors.New(fmt.Sprintf("Unsupported version: %s", strings.TrimSpace(ksVersion)))
}
}
return &clusterCfg, nil
}

View File

@ -24,6 +24,7 @@ import (
jsonpatch "github.com/evanphx/json-patch"
"github.com/ghodss/yaml"
"github.com/kubesphere/kubekey/pkg/kubesphere"
"github.com/kubesphere/kubekey/pkg/util"
"github.com/pkg/errors"
kubeErr "k8s.io/apimachinery/pkg/api/errors"
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
@ -32,16 +33,21 @@ import (
)
const (
customResourceDefinition = "/apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions"
namespaces = "/api/v1/namespaces"
serviceAccount = "/api/v1/namespaces/kubesphere-system/serviceaccounts"
clusterRole = "/apis/rbac.authorization.k8s.io/v1/clusterroles"
clusterRoleBinding = "/apis/rbac.authorization.k8s.io/v1/clusterrolebindings"
deployment = "/apis/apps/v1/namespaces/kubesphere-system/deployments"
clusterConfiguration = "/apis/installer.kubesphere.io/v1alpha1/namespaces/kubesphere-system/clusterconfigurations"
CustomResourceDefinition = "/apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions"
Namespaces = "/api/v1/namespaces"
ServiceAccount = "/api/v1/namespaces/kubesphere-system/serviceaccounts"
ClusterRole = "/apis/rbac.authorization.k8s.io/v1/clusterroles"
ClusterRoleBinding = "/apis/rbac.authorization.k8s.io/v1/clusterrolebindings"
Deployment = "/apis/apps/v1/namespaces/kubesphere-system/deployments"
ClusterConfiguration = "/apis/installer.kubesphere.io/v1alpha1/namespaces/kubesphere-system/clusterconfigurations"
)
func DeployKubeSphere(version, repo, kubeconfig string) error {
clientset, err := util.NewClient(kubeconfig)
if err != nil {
return err
}
var kubesphereConfig, installerYaml string
switch version {
@ -70,11 +76,6 @@ func DeployKubeSphere(version, repo, kubeconfig string) error {
return errors.New(fmt.Sprintf("Unsupported version: %s", strings.TrimSpace(version)))
}
clientset, err := newClient(kubeconfig)
if err != nil {
return err
}
b1 := bufio.NewReader(bytes.NewReader([]byte(installerYaml)))
for {
result := make(map[string]interface{})
@ -98,7 +99,7 @@ func DeployKubeSphere(version, repo, kubeconfig string) error {
switch result["kind"] {
case "CustomResourceDefinition":
if err := createObject(clientset, j2, customResourceDefinition); err != nil {
if err := CreateObject(clientset, j2, CustomResourceDefinition); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
@ -108,7 +109,7 @@ func DeployKubeSphere(version, repo, kubeconfig string) error {
fmt.Printf("%s/%s created\n", result["kind"], metadata["name"])
case "Namespace":
if err := createObject(clientset, j2, namespaces); err != nil {
if err := CreateObject(clientset, j2, Namespaces); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
@ -117,7 +118,7 @@ func DeployKubeSphere(version, repo, kubeconfig string) error {
metadata := result["metadata"].(map[string]interface{})
fmt.Printf("%s/%s created\n", result["kind"], metadata["name"])
case "ServiceAccount":
if err := createObject(clientset, j2, serviceAccount); err != nil {
if err := CreateObject(clientset, j2, ServiceAccount); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
@ -126,7 +127,7 @@ func DeployKubeSphere(version, repo, kubeconfig string) error {
metadata := result["metadata"].(map[string]interface{})
fmt.Printf("%s/%s created\n", result["kind"], metadata["name"])
case "ClusterRole":
if err := createObject(clientset, j2, clusterRole); err != nil {
if err := CreateObject(clientset, j2, ClusterRole); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
@ -135,7 +136,7 @@ func DeployKubeSphere(version, repo, kubeconfig string) error {
metadata := result["metadata"].(map[string]interface{})
fmt.Printf("%s/%s created\n", result["kind"], metadata["name"])
case "ClusterRoleBinding":
if err := createObject(clientset, j2, clusterRoleBinding); err != nil {
if err := CreateObject(clientset, j2, ClusterRoleBinding); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
@ -144,7 +145,7 @@ func DeployKubeSphere(version, repo, kubeconfig string) error {
metadata := result["metadata"].(map[string]interface{})
fmt.Printf("%s/%s created\n", result["kind"], metadata["name"])
case "Deployment":
if err := createObject(clientset, j2, deployment); err != nil {
if err := CreateObject(clientset, j2, Deployment); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
@ -173,7 +174,7 @@ func DeployKubeSphere(version, repo, kubeconfig string) error {
return err
}
if err := createObject(clientset, modified, clusterConfiguration); err != nil {
if err := CreateObject(clientset, modified, ClusterConfiguration); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
@ -188,7 +189,7 @@ func DeployKubeSphere(version, repo, kubeconfig string) error {
return nil
}
func createObject(clientset *kubernetes.Clientset, body []byte, request string) error {
func CreateObject(clientset *kubernetes.Clientset, body []byte, request string) error {
if err := clientset.
RESTClient().Post().
AbsPath(request).

View File

@ -165,7 +165,11 @@ EOF
caFile := "/etc/ssl/etcd/ssl/ca.pem"
certFile := fmt.Sprintf("/etc/ssl/etcd/ssl/node-%s.pem", mgr.EtcdNodes[0].Name)
keyFile := fmt.Sprintf("/etc/ssl/etcd/ssl/node-%s-key.pem", mgr.EtcdNodes[0].Name)
_, _ = mgr.Runner.ExecuteCmd(fmt.Sprintf("sudo -E /bin/sh -c \"/usr/local/bin/kubectl -n kubesphere-monitoring-system create secret generic kube-etcd-client-certs --from-file=etcd-client-ca.crt=%s --from-file=etcd-client.crt=%s --from-file=etcd-client.key=%s\"", caFile, certFile, keyFile), 5, true)
if output, err := mgr.Runner.ExecuteCmd(fmt.Sprintf("sudo -E /bin/sh -c \"/usr/local/bin/kubectl -n kubesphere-monitoring-system create secret generic kube-etcd-client-certs --from-file=etcd-client-ca.crt=%s --from-file=etcd-client.crt=%s --from-file=etcd-client.key=%s\"", caFile, certFile, keyFile), 1, true); err != nil {
if !strings.Contains(output, "AlreadyExists") {
return err
}
}
deployKubesphereCmd := "sudo -E /bin/sh -c \"/usr/local/bin/kubectl apply -f /etc/kubernetes/addons/kubesphere.yaml\""

109
pkg/kubesphere/v2/types.go Normal file
View File

@ -0,0 +1,109 @@
/*
Copyright 2020 The KubeSphere Authors.
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 v2
type V2 struct {
Persistence Persistence `yaml:"persistence"`
Common Common `yaml:"common"`
Etcd Etcd `yaml:"etcd"`
MetricsServerOld MetricsServerOld `yaml:"metrics-server"`
MetricsServerNew MetricsServerNew `yaml:"metrics_server"`
Console Console `yaml:"console"`
Monitoring Monitoring `yaml:"monitoring"`
Logging Logging `yaml:"logging"`
Openpitrix Openpitrix `yaml:"openpitrix"`
Devops Devops `yaml:"devops"`
Servicemesh Servicemesh `yaml:"servicemesh"`
Notification Notification `yaml:"notification"`
Alerting Alerting `yaml:"alerting"`
LocalRegistry string `yaml:"local_registry"`
}
type Persistence struct {
StorageClass string `yaml:"storageClass"`
}
type Etcd struct {
Monitoring bool `yaml:"monitoring"`
EndpointIps string `yaml:"endpointIps"`
Port int `yaml:"port"`
TlsEnable bool `yaml:"tlsEnable"`
}
type Common struct {
MysqlVolumeSize string `yaml:"mysqlVolumeSize"`
MinioVolumeSize string `yaml:"minioVolumeSize"`
EtcdVolumeSize string `yaml:"etcdVolumeSize"`
OpenldapVolumeSize string `yaml:"openldapVolumeSize"`
RedisVolumSize string `yaml:"redisVolumSize"`
}
type MetricsServerOld struct {
Enabled string `yaml:"enabled"`
}
type MetricsServerNew struct {
Enabled string `yaml:"enabled"`
}
type Console struct {
EnableMultiLogin bool `yaml:"enableMultiLogin"`
Port int `yaml:"port"`
}
type Monitoring struct {
PrometheusReplicas int `yaml:"prometheusReplicas"`
PrometheusMemoryRequest string `yaml:"prometheusMemoryRequest"`
PrometheusVolumeSize string `yaml:"prometheusVolumeSize"`
}
type Logging struct {
Enabled bool `yaml:"enabled"`
ElasticsearchMasterReplicas int `yaml:"elasticsearchMasterReplicas"`
ElasticsearchDataReplicas int `yaml:"elasticsearchDataReplicas"`
LogsidecarReplicas int `yaml:"logsidecarReplicas"`
ElasticsearchVolumeSize string `yaml:"elasticsearchVolumeSize"`
ElasticsearchMasterVolumeSize string `yaml:"elasticsearchMasterVolumeSize"`
ElasticsearchDataVolumeSize string `yaml:"elasticsearchDataVolumeSize"`
LogMaxAge int `yaml:"logMaxAge"`
ElkPrefix string `yaml:"elkPrefix"`
}
type Openpitrix struct {
Enabled bool `yaml:"enabled"`
}
type Devops struct {
Enabled bool `yaml:"enabled"`
JenkinsMemoryLim string `yaml:"jenkinsMemoryLim"`
JenkinsMemoryReq string `yaml:"jenkinsMemoryReq"`
JenkinsVolumeSize string `yaml:"jenkinsVolumeSize"`
JenkinsjavaoptsXms string `yaml:"jenkinsJavaOpts_Xms"`
JenkinsjavaoptsXmx string `yaml:"jenkinsJavaOpts_Xmx"`
JenkinsjavaoptsMaxram string `yaml:"jenkinsJavaOpts_MaxRAM"`
}
type Servicemesh struct {
Enabled bool `yaml:"enabled"`
}
type Notification struct {
Enabled bool `yaml:"enabled"`
}
type Alerting struct {
Enabled bool `yaml:"enabled"`
}

160
pkg/kubesphere/v3/types.go Normal file
View File

@ -0,0 +1,160 @@
/*
Copyright 2020 The KubeSphere Authors.
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 v3
type ClusterConfig struct {
ApiVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
Metadata Metadata `yaml:"metadata"`
Spec *V3 `yaml:"spec"`
}
type Metadata struct {
Name string `yaml:"name"`
Namespace string `yaml:"namespace"`
Label Label `yaml:"labels"`
}
type Label struct {
Version string `yaml:"version"`
}
type V3 struct {
Persistence Persistence `yaml:"persistence"`
Authentication Authentication `yaml:"authentication"`
Common Common `yaml:"common"`
Etcd Etcd `yaml:"etcd"`
MetricsServer MetricsServer `yaml:"metrics_server"`
Console Console `yaml:"console"`
Monitoring Monitoring `yaml:"monitoring"`
Logging Logging `yaml:"logging"`
Openpitrix Openpitrix `yaml:"openpitrix"`
Devops Devops `yaml:"devops"`
Servicemesh Servicemesh `yaml:"servicemesh"`
Notification Notification `yaml:"notification"`
Alerting Alerting `yaml:"alerting"`
Auditing Auditing `yaml:"auditing"`
Events Events `yaml:"events"`
Multicluster Multicluster `yaml:"multicluster"`
Networkpolicy Networkpolicy `yaml:"networkpolicy"`
LocalRegistry string `yaml:"local_registry"`
}
type Persistence struct {
StorageClass string `yaml:"storageClass"`
}
type MetricsServer struct {
Enabled bool `yaml:"enabled"`
}
type Authentication struct {
JwtSecret string `yaml:"jwtSecret"`
}
type Etcd struct {
Monitoring bool `yaml:"monitoring"`
EndpointIps string `yaml:"endpointIps"`
Port int `yaml:"port"`
TlsEnable bool `yaml:"tlsEnable"`
}
type Common struct {
MysqlVolumeSize string `yaml:"mysqlVolumeSize"`
MinioVolumeSize string `yaml:"minioVolumeSize"`
EtcdVolumeSize string `yaml:"etcdVolumeSize"`
OpenldapVolumeSize string `yaml:"openldapVolumeSize"`
RedisVolumSize string `yaml:"redisVolumSize"`
ES ES `yaml:"es"`
}
type ES struct {
ElasticsearchMasterReplicas int `yaml:"elasticsearchMasterReplicas"`
ElasticsearchDataReplicas int `yaml:"elasticsearchDataReplicas"`
ElasticsearchMasterVolumeSize string `yaml:"elasticsearchMasterVolumeSize"`
ElasticsearchDataVolumeSize string `yaml:"elasticsearchDataVolumeSize"`
LogMaxAge int `yaml:"logMaxAge"`
ElkPrefix string `yaml:"elkPrefix"`
}
type Console struct {
EnableMultiLogin bool `yaml:"enableMultiLogin"`
Port int `yaml:"port"`
}
type Alerting struct {
Enabled bool `yaml:"enabled"`
}
type Auditing struct {
Enabled bool `yaml:"enabled"`
}
type Devops struct {
Enabled bool `yaml:"enabled"`
JenkinsMemoryLim string `yaml:"jenkinsMemoryLim"`
JenkinsMemoryReq string `yaml:"jenkinsMemoryReq"`
JenkinsVolumeSize string `yaml:"jenkinsVolumeSize"`
JenkinsjavaoptsXms string `yaml:"jenkinsJavaOpts_Xms"`
JenkinsjavaoptsXmx string `yaml:"jenkinsJavaOpts_Xmx"`
JenkinsjavaoptsMaxram string `yaml:"jenkinsJavaOpts_MaxRAM"`
}
type Events struct {
Enabled bool `yaml:"enabled"`
Ruler Ruler `yaml:"ruler"`
}
type Ruler struct {
Enabled bool `yaml:"enabled"`
Replicas int `yaml:"replicas"`
}
type Logging struct {
Enabled bool `yaml:"enabled"`
LogsidecarReplicas int `yaml:"logsidecarReplicas"`
}
type Metrics struct {
Enabled bool `yaml:"enabled"`
}
type Monitoring struct {
AlertmanagerReplicas int `yaml:"alertmanagerReplicas"`
PrometheusReplicas int `yaml:"prometheusReplicas"`
PrometheusMemoryRequest string `yaml:"prometheusMemoryRequest"`
PrometheusVolumeSize string `yaml:"prometheusVolumeSize"`
}
type Multicluster struct {
ClusterRole string `yaml:"clusterRole"`
}
type Networkpolicy struct {
Enabled bool `yaml:"enabled"`
}
type Notification struct {
Enabled bool `yaml:"enabled"`
}
type Openpitrix struct {
Enabled bool `yaml:"enabled"`
}
type Servicemesh struct {
Enabled bool `yaml:"enabled"`
}

View File

@ -1,16 +0,0 @@
/*
Copyright 2020 The KubeSphere Authors.
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 upgrade

View File

@ -1,9 +1,10 @@
package kubernetes
package upgrade
import (
"encoding/base64"
"fmt"
kubekeyapi "github.com/kubesphere/kubekey/pkg/apis/kubekey/v1alpha1"
"github.com/kubesphere/kubekey/pkg/cluster/kubernetes"
"github.com/kubesphere/kubekey/pkg/cluster/kubernetes/tmpl"
"github.com/kubesphere/kubekey/pkg/cluster/preinstall"
"github.com/kubesphere/kubekey/pkg/files"
@ -98,7 +99,7 @@ func upgradeKubeMasters(mgr *manager.Manager, node *kubekeyapi.HostCfg) error {
return errors.Wrap(err, "Failed to get current kubelet version")
}
if strings.Split(kubeletVersion, " ")[1] != mgr.Cluster.Kubernetes.Version {
if err := SyncKubeBinaries(mgr, node); err != nil {
if err := kubernetes.SyncKubeBinaries(mgr, node); err != nil {
return err
}
@ -132,7 +133,7 @@ func upgradeKubeMasters(mgr *manager.Manager, node *kubekeyapi.HostCfg) error {
return errors.Wrap(errors.WithStack(err2), fmt.Sprintf("Failed to upgrade master: %s", node.Name))
}
if err := SetKubelet(mgr, node); err != nil {
if err := kubernetes.SetKubelet(mgr, node); err != nil {
return err
}
@ -151,11 +152,11 @@ func upgradeKubeWorkers(mgr *manager.Manager, node *kubekeyapi.HostCfg) error {
}
if strings.Split(kubeletVersion, " ")[1] != mgr.Cluster.Kubernetes.Version {
if err := SyncKubeBinaries(mgr, node); err != nil {
if err := kubernetes.SyncKubeBinaries(mgr, node); err != nil {
return err
}
if err := SetKubelet(mgr, node); err != nil {
if err := kubernetes.SetKubelet(mgr, node); err != nil {
return err
}

289
pkg/upgrade/kubesphere.go Normal file
View File

@ -0,0 +1,289 @@
/*
Copyright 2020 The KubeSphere Authors.
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 upgrade
import (
"bufio"
"bytes"
"context"
"fmt"
"github.com/ghodss/yaml"
kubekeyapi "github.com/kubesphere/kubekey/pkg/apis/kubekey/v1alpha1"
"github.com/kubesphere/kubekey/pkg/deploy"
"github.com/kubesphere/kubekey/pkg/kubesphere"
ksv2 "github.com/kubesphere/kubekey/pkg/kubesphere/v2"
ksv3 "github.com/kubesphere/kubekey/pkg/kubesphere/v3"
"github.com/kubesphere/kubekey/pkg/util"
"github.com/kubesphere/kubekey/pkg/util/manager"
"github.com/pkg/errors"
yamlV2 "gopkg.in/yaml.v2"
kubeErr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
"strings"
)
func KsToV3(version, repo, kubeconfig string) error {
clientset, err := util.NewClient(kubeconfig)
if err != nil {
return err
}
clusterConfigMap, err1 := clientset.CoreV1().ConfigMaps("kubesphere-system").Get(context.TODO(), "ks-installer", metav1.GetOptions{})
if err1 != nil {
return err1
}
clusterCfgV2 := ksv2.V2{}
clusterCfgV3 := ksv3.V3{}
if err := yamlV2.Unmarshal([]byte(clusterConfigMap.Data["ks-config.yaml"]), &clusterCfgV2); err != nil {
return err
}
configV3, err := MigrateConfig2to3(&clusterCfgV2, &clusterCfgV3)
if err != nil {
return err
}
fmt.Println(configV3)
var kubesphereConfig, installerYaml string
switch version {
case "":
kubesphereConfig = configV3
str, err := kubesphere.GenerateKubeSphereYaml(repo, "latest")
if err != nil {
return err
}
installerYaml = str
case "v3.0.0":
kubesphereConfig = configV3
str, err := kubesphere.GenerateKubeSphereYaml(repo, "latest")
if err != nil {
return err
}
installerYaml = str
default:
return errors.New(fmt.Sprintf("Unsupported version: %s", strings.TrimSpace(version)))
}
b1 := bufio.NewReader(bytes.NewReader([]byte(installerYaml)))
for {
result := make(map[string]interface{})
content, err := k8syaml.NewYAMLReader(b1).Read()
if len(content) == 0 {
break
}
if err != nil {
return errors.Wrap(err, "Unable to read the manifests")
}
err = yaml.Unmarshal(content, &result)
if err != nil {
return errors.Wrap(err, "Unable to unmarshal the manifests")
}
j2, err1 := yaml.YAMLToJSON(content)
if err1 != nil {
return err
}
switch result["kind"] {
case "CustomResourceDefinition":
if err := deploy.CreateObject(clientset, j2, deploy.CustomResourceDefinition); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
}
metadata := result["metadata"].(map[string]interface{})
fmt.Printf("%s/%s created\n", result["kind"], metadata["name"])
case "Namespace":
if err := deploy.CreateObject(clientset, j2, deploy.Namespaces); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
}
metadata := result["metadata"].(map[string]interface{})
fmt.Printf("%s/%s created\n", result["kind"], metadata["name"])
case "ServiceAccount":
if err := deploy.CreateObject(clientset, j2, deploy.ServiceAccount); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
}
metadata := result["metadata"].(map[string]interface{})
fmt.Printf("%s/%s created\n", result["kind"], metadata["name"])
case "ClusterRole":
if err := deploy.CreateObject(clientset, j2, deploy.ClusterRole); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
}
metadata := result["metadata"].(map[string]interface{})
fmt.Printf("%s/%s created\n", result["kind"], metadata["name"])
case "ClusterRoleBinding":
if err := deploy.CreateObject(clientset, j2, deploy.ClusterRoleBinding); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
}
metadata := result["metadata"].(map[string]interface{})
fmt.Printf("%s/%s created\n", result["kind"], metadata["name"])
case "Deployment":
if err := deploy.CreateObject(clientset, j2, deploy.Deployment); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
}
metadata := result["metadata"].(map[string]interface{})
fmt.Printf("%s/%s created\n", result["kind"], metadata["name"])
}
}
j2, err1 := yaml.YAMLToJSON([]byte(kubesphereConfig))
if err1 != nil {
return err
}
if err := deploy.CreateObject(clientset, j2, deploy.ClusterConfiguration); err != nil {
if !kubeErr.IsAlreadyExists(err) {
return err
}
}
result := make(map[string]interface{})
err = yaml.Unmarshal([]byte(kubesphereConfig), &result)
if err != nil {
return errors.Wrap(err, "Unable to unmarshal the manifests")
}
metadata := result["metadata"].(map[string]interface{})
fmt.Printf("%s/%s created\n", result["kind"], metadata["name"])
return nil
}
func MigrateConfig2to3(v2 *ksv2.V2, v3 *ksv3.V3) (string, error) {
v3.Etcd = ksv3.Etcd(v2.Etcd)
v3.Persistence = ksv3.Persistence(v2.Persistence)
v3.Alerting = ksv3.Alerting(v2.Alerting)
v3.Notification = ksv3.Notification(v2.Notification)
v3.LocalRegistry = v2.LocalRegistry
v3.Servicemesh = ksv3.Servicemesh(v2.Servicemesh)
v3.Devops = ksv3.Devops(v2.Devops)
v3.Openpitrix = ksv3.Openpitrix(v2.Openpitrix)
v3.Console = ksv3.Console(v2.Console)
if v2.MetricsServerNew.Enabled == "" {
if v2.MetricsServerOld.Enabled == "true" || v2.MetricsServerOld.Enabled == "True" {
v3.MetricsServer.Enabled = true
} else {
v3.MetricsServer.Enabled = false
}
} else {
if v2.MetricsServerNew.Enabled == "true" || v2.MetricsServerNew.Enabled == "True" {
v3.MetricsServer.Enabled = true
} else {
v3.MetricsServer.Enabled = false
}
}
v3.Monitoring.PrometheusMemoryRequest = v2.Monitoring.PrometheusMemoryRequest
v3.Monitoring.PrometheusReplicas = v2.Monitoring.PrometheusReplicas
v3.Monitoring.PrometheusVolumeSize = v2.Monitoring.PrometheusVolumeSize
v3.Monitoring.AlertmanagerReplicas = 1
v3.Common.EtcdVolumeSize = v2.Common.EtcdVolumeSize
v3.Common.MinioVolumeSize = v2.Common.MinioVolumeSize
v3.Common.MysqlVolumeSize = v2.Common.MysqlVolumeSize
v3.Common.OpenldapVolumeSize = v2.Common.OpenldapVolumeSize
v3.Common.RedisVolumSize = v2.Common.RedisVolumSize
v3.Common.ES.ElasticsearchDataReplicas = v2.Logging.ElasticsearchDataReplicas
v3.Common.ES.ElasticsearchMasterReplicas = v2.Logging.ElasticsearchMasterReplicas
v3.Common.ES.ElkPrefix = v2.Logging.ElkPrefix
v3.Common.ES.LogMaxAge = v2.Logging.LogMaxAge
if v2.Logging.ElasticsearchVolumeSize == "" {
v3.Common.ES.ElasticsearchDataVolumeSize = v2.Logging.ElasticsearchDataVolumeSize
v3.Common.ES.ElasticsearchMasterVolumeSize = v2.Logging.ElasticsearchMasterVolumeSize
} else {
v3.Common.ES.ElasticsearchMasterVolumeSize = "4Gi"
v3.Common.ES.ElasticsearchDataVolumeSize = v2.Logging.ElasticsearchVolumeSize
}
v3.Logging.Enabled = v2.Logging.Enabled
v3.Logging.LogsidecarReplicas = v2.Logging.LogsidecarReplicas
v3.Authentication.JwtSecret = ""
v3.Multicluster.ClusterRole = "none"
v3.Events.Ruler.Replicas = 2
var clusterConfiguration = ksv3.ClusterConfig{
ApiVersion: "installer.kubesphere.io/v1alpha1",
Kind: "ClusterConfiguration",
Metadata: ksv3.Metadata{
Name: "ks-installer",
Namespace: "kubesphere-system",
Label: ksv3.Label{Version: "v3.0.0"},
},
Spec: v3,
}
configV3, err := yamlV2.Marshal(clusterConfiguration)
if err != nil {
return "", err
}
return string(configV3), nil
}
func SyncConfiguration(mgr *manager.Manager) error {
if err := mgr.RunTaskOnMasterNodes(syncConfiguration, true); err != nil {
return err
}
return nil
}
func syncConfiguration(mgr *manager.Manager, _ *kubekeyapi.HostCfg) error {
if mgr.Runner.Index == 0 {
configV2Str, err := mgr.Runner.ExecuteCmd("sudo -E /bin/sh -c \"/usr/local/bin/kubectl get cm -n kubesphere-system ks-installer -o jsonpath='{.data.ks-config\\.yaml}'\"", 2, false)
if err != nil {
return err
}
clusterCfgV2 := ksv2.V2{}
clusterCfgV3 := ksv3.V3{}
if err := yamlV2.Unmarshal([]byte(configV2Str), &clusterCfgV2); err != nil {
return err
}
configV3, err := MigrateConfig2to3(&clusterCfgV2, &clusterCfgV3)
if err != nil {
return err
}
mgr.Cluster.KubeSphere.Configurations = "---\n" + configV3
}
return nil
}

View File

@ -1,68 +0,0 @@
/*
Copyright 2020 The KubeSphere Authors.
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 upgrade
import (
"bufio"
"fmt"
kubekeyapi "github.com/kubesphere/kubekey/pkg/apis/kubekey/v1alpha1"
"github.com/kubesphere/kubekey/pkg/util/manager"
"os"
"strings"
)
func GetClusterInfo(mgr *manager.Manager) error {
return mgr.RunTaskOnMasterNodes(getClusterInfo, true)
}
func getClusterInfo(mgr *manager.Manager, node *kubekeyapi.HostCfg) error {
if mgr.Runner.Index == 0 {
componentstatus, err := mgr.Runner.ExecuteCmd("sudo -E /bin/bash -c \"/usr/local/bin/kubectl get componentstatus\"", 2, false)
if err != nil {
return err
}
fmt.Println("Cluster components status:")
fmt.Println(componentstatus + "\n")
nodestatus, err := mgr.Runner.ExecuteCmd("sudo -E /bin/sh -c \"/usr/local/bin/kubectl get node -o wide\"", 2, false)
if err != nil {
return err
}
fmt.Println("Cluster nodes status:")
fmt.Println(nodestatus + "\n\n")
reader := bufio.NewReader(os.Stdin)
Loop:
for {
fmt.Printf("Continue upgrading cluster? [yes/no]: ")
input, err := reader.ReadString('\n')
if err != nil {
mgr.Logger.Fatal(err)
}
input = strings.TrimSpace(input)
switch input {
case "yes":
break Loop
case "no":
os.Exit(0)
default:
continue
}
}
}
return nil
}

149
pkg/upgrade/precheck.go Normal file
View File

@ -0,0 +1,149 @@
/*
Copyright 2020 The KubeSphere Authors.
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 upgrade
import (
"bufio"
"fmt"
kubekeyapi "github.com/kubesphere/kubekey/pkg/apis/kubekey/v1alpha1"
"github.com/kubesphere/kubekey/pkg/util/manager"
"github.com/pkg/errors"
versionutil "k8s.io/apimachinery/pkg/util/version"
"os"
"strings"
)
var versionCheck = map[string]map[string]map[string]bool{
"v3.0.0": {
"k8s": {
"v1.18": true,
"v1.17": true,
"v1.16": true,
"v1.15": true,
},
"ks": {
"v2.1.0": true,
"v2.1.1": true,
},
},
"v2.1.1": {
"k8s": {
"v1.18": true,
"v1.17": true,
"v1.16": true,
"v1.15": true,
},
},
}
func GetClusterInfo(mgr *manager.Manager) error {
return mgr.RunTaskOnMasterNodes(getClusterInfo, true)
}
func getClusterInfo(mgr *manager.Manager, _ *kubekeyapi.HostCfg) error {
if mgr.Runner.Index == 0 {
k8sVersionStr, err := mgr.Runner.ExecuteCmd("sudo -E /bin/sh -c \"cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep 'image:' | cut -d ':' -f 3\"", 3, false)
if err != nil {
return errors.Wrap(err, "Failed to get current kube-apiserver version")
}
ksVersion, err := mgr.Runner.ExecuteCmd("sudo -E /bin/sh -c \"/usr/local/bin/kubectl get deploy -n kubesphere-system ks-console -o jsonpath='{.metadata.labels.version}'\"", 2, false)
if err != nil {
if mgr.Cluster.KubeSphere.Enabled {
return err
}
} else {
if mgr.Cluster.KubeSphere.Enabled {
if _, ok := versionCheck[mgr.Cluster.KubeSphere.Version]; !ok {
return errors.New(fmt.Sprintf("Unsupported version: %s", mgr.Cluster.KubeSphere.Version))
}
if _, ok := versionCheck[mgr.Cluster.KubeSphere.Version]["ks"][ksVersion]; !ok {
return errors.New(fmt.Sprintf("Unsupported upgrade plan: %s to %s", strings.TrimSpace(ksVersion), mgr.Cluster.KubeSphere.Version))
}
K8sTargetVersion := versionutil.MustParseSemantic(mgr.Cluster.Kubernetes.Version)
if _, ok := versionCheck[mgr.Cluster.KubeSphere.Version]["k8s"][fmt.Sprintf("v%v.%v", K8sTargetVersion.Major(), K8sTargetVersion.Minor())]; !ok {
return errors.New(fmt.Sprintf("KubeSphere %s does not support running on Kubernetes %s", mgr.Cluster.KubeSphere.Version, fmt.Sprintf("v%v.%v", K8sTargetVersion.Major(), K8sTargetVersion.Minor())))
}
} else {
if _, ok := versionCheck[ksVersion]; !ok {
return errors.New(fmt.Sprintf("Unsupported version: %s", ksVersion))
}
K8sTargetVersion := versionutil.MustParseSemantic(mgr.Cluster.Kubernetes.Version)
if _, ok := versionCheck[ksVersion]["k8s"][fmt.Sprintf("v%v.%v", K8sTargetVersion.Major(), K8sTargetVersion.Minor())]; !ok {
return errors.New(fmt.Sprintf("KubeSphere %s does not support running on Kubernetes %s", ksVersion, fmt.Sprintf("v%v.%v", K8sTargetVersion.Major(), K8sTargetVersion.Minor())))
}
}
}
if err := getNodestatus(mgr); err != nil {
return err
}
if err := getComponentStatus(mgr); err != nil {
return err
}
fmt.Println("Upgrade Confirmation:")
fmt.Printf("kubernetes version: %s to %s\n", k8sVersionStr, mgr.Cluster.Kubernetes.Version)
if mgr.Cluster.KubeSphere.Enabled {
fmt.Printf("kubesphere version: %s to %s\n\n", ksVersion, mgr.Cluster.KubeSphere.Version)
} else {
fmt.Println()
}
reader := bufio.NewReader(os.Stdin)
Loop:
for {
fmt.Printf("Continue upgrading cluster? [yes/no]: ")
input, err := reader.ReadString('\n')
if err != nil {
mgr.Logger.Fatal(err)
}
input = strings.TrimSpace(input)
switch input {
case "yes":
break Loop
case "no":
os.Exit(0)
default:
continue
}
}
}
return nil
}
func getComponentStatus(mgr *manager.Manager) error {
componentStatusStr, err := mgr.Runner.ExecuteCmd("sudo -E /bin/bash -c \"/usr/local/bin/kubectl get componentstatus -o go-template='{{range .items}}{{ printf \\\"%s: \\\" .metadata.name}}{{range .conditions}}{{ printf \\\"%v\\n\\\" .message }}{{end}}{{end}}'\"", 1, false)
if err != nil {
return err
}
fmt.Println("Components Status:")
fmt.Println(componentStatusStr + "\n")
return nil
}
func getNodestatus(mgr *manager.Manager) error {
nodestatus, err := mgr.Runner.ExecuteCmd("sudo -E /bin/sh -c \"/usr/local/bin/kubectl get node\"", 2, false)
if err != nil {
return err
}
fmt.Println("Cluster nodes status:")
fmt.Println(nodestatus + "\n")
return nil
}

View File

@ -18,7 +18,6 @@ package upgrade
import (
"fmt"
"github.com/kubesphere/kubekey/pkg/cluster/kubernetes"
"github.com/kubesphere/kubekey/pkg/config"
"github.com/kubesphere/kubekey/pkg/kubesphere"
"github.com/kubesphere/kubekey/pkg/util"
@ -52,8 +51,9 @@ func ExecTasks(mgr *manager.Manager) error {
{Task: GetClusterInfo, ErrMsg: "Failed to get cluster info"},
//{Task: preinstall.InitOS, ErrMsg: "Failed to download kube binaries"},
//{Task: preinstall.PrePullImages, ErrMsg: "Failed to pre-pull images"},
{Task: kubernetes.GetCurrentVersions, ErrMsg: "Failed to get current version"},
{Task: kubernetes.UpgradeKubeCluster, ErrMsg: "Failed to upgrade kube cluster"},
{Task: GetCurrentVersions, ErrMsg: "Failed to get current version"},
{Task: UpgradeKubeCluster, ErrMsg: "Failed to upgrade kube cluster"},
{Task: SyncConfiguration, ErrMsg: "Failed to sync configuration"},
{Task: kubesphere.DeployKubeSphere, ErrMsg: "Failed to upgrade kubesphere"},
}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package deploy
package util
import (
"github.com/pkg/errors"
@ -24,7 +24,7 @@ import (
"path/filepath"
)
func newClient(config string) (*kubernetes.Clientset, error) {
func NewClient(config string) (*kubernetes.Clientset, error) {
var kubeconfig string
if config != "" {
config, err := filepath.Abs(config)