diff --git a/docs/user_docs/cli/kbcli_cluster_describe-backup.md b/docs/user_docs/cli/kbcli_cluster_describe-backup.md index 1aa5eb805..898aebd53 100644 --- a/docs/user_docs/cli/kbcli_cluster_describe-backup.md +++ b/docs/user_docs/cli/kbcli_cluster_describe-backup.md @@ -11,8 +11,11 @@ kbcli cluster describe-backup BACKUP-NAME [flags] ### Examples ``` + # describe backups of the cluster + kbcli cluster describe-backup + # describe a backup - kbcli cluster describe-backup backup-default-mycluster-20230616190023 + kbcli cluster describe-backup --names ``` ### Options diff --git a/docs/user_docs/cli/kbcli_playground_init.md b/docs/user_docs/cli/kbcli_playground_init.md index 5acd4a857..9e2924b2a 100644 --- a/docs/user_docs/cli/kbcli_playground_init.md +++ b/docs/user_docs/cli/kbcli_playground_init.md @@ -31,7 +31,8 @@ kbcli playground init [flags] kbcli cluster describe mycluster # connect to database - kbcli cluster connect mycluster + kbcli exec -it mycluster-mysql-0 bash + mysql -h 127.1 -u root -p$MYSQL_ROOT_PASSWORD # view the Grafana kbcli dashboard open kubeblocks-grafana @@ -45,7 +46,7 @@ kbcli playground init [flags] ``` --auto-approve Skip interactive approval during the initialization of playground --cloud-provider string Cloud provider type, one of [local aws] (default "local") - --cluster-type string Specify the cluster type to create, use 'kbcli cluster create --help' to get the available cluster type. (default "apecloud-mysql") + --cluster-type string Specify the cluster type to create, use 'kbcli cluster create --help' to get the available cluster type. (default "mysql") -h, --help help for init --k3d-proxy-image string Specify k3d proxy image if you want to init playground locally (default "docker.io/apecloud/k3d-proxy:5.4.4") --k3s-image string Specify k3s image that you want to use for the nodes if you want to init playground locally (default "rancher/k3s:v1.23.8-k3s1") diff --git a/pkg/cloudprovider/k3d.go b/pkg/cloudprovider/k3d.go index 6e16922bd..e2a9b15d3 100644 --- a/pkg/cloudprovider/k3d.go +++ b/pkg/cloudprovider/k3d.go @@ -282,7 +282,7 @@ func buildClusterConfig(clusterName string, opts k3d.ClusterCreateOpts, k3sImage Role: k3d.ServerRole, Image: k3sImage, ServerOpts: k3d.ServerOpts{}, - Args: []string{"--disable=metrics-server", "--disable=traefik", "--disable=local-storage"}, + Args: []string{"--disable=metrics-server", "--disable=traefik"}, } nodes = append(nodes, &serverNode) diff --git a/pkg/cmd/cluster/create_subcmds.go b/pkg/cmd/cluster/create_subcmds.go index fb29ac41c..2c4acb3e5 100644 --- a/pkg/cmd/cluster/create_subcmds.go +++ b/pkg/cmd/cluster/create_subcmds.go @@ -160,6 +160,14 @@ func (o *CreateSubCmdsOptions) Complete(cmd *cobra.Command) error { } } + if o.Tenancy == "" { + o.Tenancy = "SharedNode" + } + + if o.PodAntiAffinity == "" { + o.PodAntiAffinity = "Preferred" + } + // get values from flags if cmd != nil { o.Values = getValuesFromFlags(cmd.LocalNonPersistentFlags()) diff --git a/pkg/cmd/cluster/dataprotection.go b/pkg/cmd/cluster/dataprotection.go index 338e17277..2102fa3fe 100644 --- a/pkg/cmd/cluster/dataprotection.go +++ b/pkg/cmd/cluster/dataprotection.go @@ -93,8 +93,11 @@ var ( kbcli cluster list-restores --names r1,r2 `) describeBackupExample = templates.Examples(` + # describe backups of the cluster + kbcli cluster describe-backup + # describe a backup - kbcli cluster describe-backup backup-default-mycluster-20230616190023 + kbcli cluster describe-backup --names `) describeBackupPolicyExample = templates.Examples(` # describe the default backup policy of the cluster diff --git a/pkg/cmd/playground/init.go b/pkg/cmd/playground/init.go index af4b4adb1..0698d937b 100644 --- a/pkg/cmd/playground/init.go +++ b/pkg/cmd/playground/init.go @@ -23,6 +23,7 @@ import ( "fmt" "os" "path/filepath" + "runtime" "strings" "time" @@ -30,12 +31,16 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "golang.org/x/exp/slices" + "golang.org/x/net/context" apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/cli-runtime/pkg/genericiooptions" "k8s.io/klog/v2" cmdutil "k8s.io/kubectl/pkg/cmd/util" "k8s.io/kubectl/pkg/util/templates" + "sigs.k8s.io/yaml" cp "github.com/apecloud/kbcli/pkg/cloudprovider" "github.com/apecloud/kbcli/pkg/cluster" @@ -72,7 +77,8 @@ on the created kubernetes cluster, and an apecloud-mysql cluster named mycluster kbcli cluster describe mycluster # connect to database - kbcli cluster connect mycluster + kbcli exec -it mycluster-mysql-0 bash + mysql -h 127.1 -u root -p$MYSQL_ROOT_PASSWORD # view the Grafana kbcli dashboard open kubeblocks-grafana @@ -207,6 +213,18 @@ func (o *initOptions) local() error { } } + if clusterInfo.K3sImage == "" { + if o.prevCluster != nil { + playgrouddir, err := initPlaygroundDir() + if err != nil { + return err + } + return fmt.Errorf(fmt.Sprintf("k3s image not specified, you can run `rm -rf %s ` and retry", playgrouddir)) + } + clusterInfo.K3sImage = cp.K3sImageDefault + clusterInfo.K3dProxyImage = cp.K3dProxyImageDefault + } + if err = writeClusterInfo(o.stateFilePath, clusterInfo); err != nil { return errors.Wrapf(err, "failed to write kubernetes cluster info to state file %s:\n %v", o.stateFilePath, clusterInfo) } @@ -410,6 +428,10 @@ func (o *initOptions) installKBAndCluster(info *cp.K8sClusterInfo) error { return errors.Wrap(err, "failed to install KubeBlocks") } klog.V(1).Info("KubeBlocks installed successfully") + if err = o.createSnapshotController(); err != nil { + return errors.Wrap(err, "failed to install snapshot controller") + } + klog.V(1).Info("create snapshot controller addon successfully") // install database cluster clusterInfo := "ClusterType: " + o.clusterType s := spinner.New(o.Out, spinnerMsg("Create cluster %s (%s)", kbClusterName, clusterInfo)) @@ -494,6 +516,46 @@ func (o *initOptions) installKubeBlocks(k8sClusterName string) error { return insOpts.Install() } +func (o *initOptions) createSnapshotController() error { + if o.cloudProvider != cp.Local { + return nil + } + cli, err := util.NewFactory().DynamicClient() + if err != nil { + return err + } + _, currentFile, _, _ := runtime.Caller(1) + baseDir := filepath.Dir(currentFile) + getUnstructured := func(fileName string) (*unstructured.Unstructured, error) { + cmBytes, err := os.ReadFile(fileName) + if err != nil { + return nil, err + } + cm := &unstructured.Unstructured{} + if err := yaml.Unmarshal(cmBytes, cm); err != nil { + return nil, err + } + return cm, err + } + snapshotControllerCM, err := getUnstructured(baseDir + "/snapshot-controller/snapshot-controller-cm.yaml") + if err != nil { + return err + } + snapshotControllerCM.SetNamespace(defaultNamespace) + if _, err = cli.Resource(types.ConfigmapGVR()).Namespace(defaultNamespace).Create(context.TODO(), snapshotControllerCM, metav1.CreateOptions{}); err != nil { + return err + } + + snapshotControllerAddon, err := getUnstructured(baseDir + "/snapshot-controller/snapshot-controller-addon.yaml") + if err != nil { + return err + } + if _, err = cli.Resource(types.AddonGVR()).Namespace("").Create(context.TODO(), snapshotControllerAddon, metav1.CreateOptions{}); err != nil { + return err + } + return nil +} + // createCluster constructs a cluster create options and run func (o *initOptions) createCluster() error { c, err := cmdcluster.NewSubCmdsOptions(&cmdcluster.NewCreateOptions(util.NewFactory(), genericiooptions.NewTestIOStreamsDiscard()).CreateOptions, cluster.ClusterType(o.clusterType)) diff --git a/pkg/cmd/playground/snapshot-controller/snapshot-controller-addon.yaml b/pkg/cmd/playground/snapshot-controller/snapshot-controller-addon.yaml new file mode 100644 index 000000000..b2e31c0d8 --- /dev/null +++ b/pkg/cmd/playground/snapshot-controller/snapshot-controller-addon.yaml @@ -0,0 +1,71 @@ +apiVersion: extensions.kubeblocks.io/v1alpha1 +kind: Addon +metadata: + name: snapshot-controller +spec: + defaultInstallValues: + - enabled: true + resources: {} + tolerations: '[{"effect":"NoSchedule","key":"kb-controller","operator":"Equal","value":"true"}]' + - resources: {} + selectors: + - key: KubeGitVersion + operator: Contains + values: + - eks + storageClass: ebs.csi.aws.com + tolerations: '[{"effect":"NoSchedule","key":"kb-controller","operator":"Equal","value":"true"}]' + - resources: {} + selectors: + - key: KubeGitVersion + operator: Contains + values: + - gke + storageClass: pd.csi.storage.gke.io + tolerations: '[{"effect":"NoSchedule","key":"kb-controller","operator":"Equal","value":"true"}]' + - resources: {} + selectors: + - key: KubeGitVersion + operator: Contains + values: + - aks + storageClass: disk.csi.azure.com + tolerations: '[{"effect":"NoSchedule","key":"kb-controller","operator":"Equal","value":"true"}]' + description: 'Deploys a Snapshot Controller in a cluster. Snapshot Controllers are + often bundled with the Kubernetes distribution, this chart is meant for cases + where it is not. ' + helm: + chartLocationURL: file:///snapshot-controller-1.7.2.tgz + chartsImage: apecloud-registry.cn-zhangjiakou.cr.aliyuncs.com/apecloud/kubeblocks-charts:0.9.3 + chartsPathInImage: /charts + installValues: + configMapRefs: + - key: values-kubeblocks-override.yaml + name: snapshot-controller-chart-kubeblocks-values + valuesMapping: + jsonMap: + tolerations: tolerations + resources: + cpu: + limits: resources.limits.cpu + requests: resources.requests.cpu + memory: + limits: resources.limits.memory + requests: resources.requests.memory + valueMap: + replicaCount: replicaCount + storageClass: volumeSnapshotClasses[0].driver + installable: + autoInstall: true + selectors: + - key: KubeGitVersion + operator: DoesNotContain + values: + - tke + - aliyun. + - key: KubeProvider + operator: DoesNotContain + values: + - huaweiCloud + - azure + type: Helm diff --git a/pkg/cmd/playground/snapshot-controller/snapshot-controller-cm.yaml b/pkg/cmd/playground/snapshot-controller/snapshot-controller-cm.yaml new file mode 100644 index 000000000..04aeeae42 --- /dev/null +++ b/pkg/cmd/playground/snapshot-controller/snapshot-controller-cm.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +data: + values-kubeblocks-override.yaml: |- + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: kb-controller + operator: In + values: + - "true" + weight: 100 + enabled: true + image: + repository: apecloud-registry.cn-zhangjiakou.cr.aliyuncs.com/apecloud/snapshot-controller + tag: v6.2.1 + replicaCount: 1 + tolerations: + - effect: NoSchedule + key: kb-controller + operator: Equal + value: "true" + volumeSnapshotClasses: + - deletionPolicy: Delete + driver: hostpath.csi.k8s.io + name: default-vsc +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/instance: kubeblocks + app.kubernetes.io/name: kubeblocks + name: snapshot-controller-chart-kubeblocks-values diff --git a/pkg/cmd/playground/types.go b/pkg/cmd/playground/types.go index 1bfe60d86..069e77aa7 100644 --- a/pkg/cmd/playground/types.go +++ b/pkg/cmd/playground/types.go @@ -32,7 +32,7 @@ const ( const ( defaultCloudProvider = cloudprovider.Local - defaultClusterType = "apecloud-mysql" + defaultClusterType = "mysql" // defaultNamespace is the namespace of playground cluster defaultNamespace = "default"