Skip to content

Commit

Permalink
Support Karmada addon commands
Browse files Browse the repository at this point in the history
Co-authored-by: duanmeng <duanmeng_yewu@cmss.chinamobile.com>
Signed-off-by: wuyingjun <wuyingjun_yewu@cmss.chinamobile.com>
  • Loading branch information
wuyingjun-lucky and duanmengkk committed Jul 24, 2022
1 parent 6969a5d commit c429520
Show file tree
Hide file tree
Showing 24 changed files with 1,537 additions and 27 deletions.
38 changes: 38 additions & 0 deletions pkg/karmadactl/addons/addons.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package addons

import (
"fmt"

"github.com/spf13/cobra"
"k8s.io/kubectl/pkg/util/templates"

"github.com/karmada-io/karmada/pkg/karmadactl/addons/install"
)

var (
addonsExamples = templates.Examples(`
# Enable or disable Karmada addons to the karmada-host cluster
%[1]s addons enable karmada-search
`)
)

func init() {
install.Install()
}

// NewCommandAddons enable or disable Karmada addons on karmada-host cluster
func NewCommandAddons(parentCommand string) *cobra.Command {
cmd := &cobra.Command{
Use: "addons",
Short: "enable or disable a Karmada addon",
Long: "enable or disable a Karmada addon",
Example: fmt.Sprintf(addonsExamples, parentCommand),
}

addonsParentCommand := fmt.Sprintf("%s %s", parentCommand, "addons")
cmd.AddCommand(NewCmdAddonsList(addonsParentCommand))
cmd.AddCommand(NewCmdAddonsEnable(addonsParentCommand))
cmd.AddCommand(NewCmdAddonsDisable(addonsParentCommand))

return cmd
}
83 changes: 83 additions & 0 deletions pkg/karmadactl/addons/descheduler/descheduler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package descheduler

import (
"context"
"fmt"

appsv1 "k8s.io/api/apps/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kuberuntime "k8s.io/apimachinery/pkg/runtime"
clientsetscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/klog/v2"

addonsinit "github.com/karmada-io/karmada/pkg/karmadactl/addons/init"
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/kubernetes"
initutils "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils"
"github.com/karmada-io/karmada/pkg/karmadactl/utils"
)

var karmadaDeschedulerLabels = map[string]string{"app": addonsinit.DeschedulerResourceName}

// AddonDescheduler describe the descheduler addon command process
var AddonDescheduler = &addonsinit.Addon{
Name: addonsinit.DeschedulerResourceName,
Status: status,
Enable: enableDescheduler,
Disable: disableDescheduler,
}

var status = func(opts *addonsinit.CommandAddonsListOption) (string, error) {
deployment, err := opts.KubeClientSet.AppsV1().Deployments(opts.Namespace).Get(context.TODO(), addonsinit.DeschedulerResourceName, metav1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
return addonsinit.AddonDisabledStatus, nil
}
return addonsinit.AddonUnknownStatus, err
}
if deployment.Status.Replicas != deployment.Status.ReadyReplicas ||
deployment.Status.Replicas != deployment.Status.AvailableReplicas {
return addonsinit.AddonUnhealthyStatus, nil
}

return addonsinit.AddonEnabledStatus, nil
}

var enableDescheduler = func(opts *addonsinit.CommandAddonsEnableOption) error {
// install karmada descheduler deployment on host cluster
karmadaDeschedulerDeploymentBytes, err := utils.ParseTemplate(karmadaDeschedulerDeployment, DeploymentReplace{
Namespace: opts.Namespace,
Replicas: &opts.KarmadaDeschedulerReplicas,
Image: opts.KarmadaDeschedulerImage,
})
if err != nil {
return fmt.Errorf("error when parsing karmada descheduler deployment template :%v", err)
}

karmadaDeschedulerDeployment := &appsv1.Deployment{}
if err := kuberuntime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), karmadaDeschedulerDeploymentBytes, karmadaDeschedulerDeployment); err != nil {
return fmt.Errorf("decode descheduler deployment error: %v", err)
}

if err := utils.CreateOrUpdateDeployment(opts.KubeClientSet, karmadaDeschedulerDeployment); err != nil {
return fmt.Errorf("create karmada descheduler deployment error: %v", err)
}

if err := kubernetes.WaitPodReady(opts.KubeClientSet, opts.Namespace, initutils.MapToString(karmadaDeschedulerLabels), opts.WaitPodReadyTimeout); err != nil {
return fmt.Errorf("wait karmada descheduler pod timeout: %v", err)
}

klog.Infof("Install karmada descheduler deployment on host cluster successfully")
return nil
}

var disableDescheduler = func(opts *addonsinit.CommandAddonsDisableOption) error {
// uninstall karmada descheduler deployment on host cluster
deployClient := opts.KubeClientSet.AppsV1().Deployments(opts.Namespace)
if err := deployClient.Delete(context.TODO(), addonsinit.DeschedulerResourceName, metav1.DeleteOptions{}); err != nil && !apierrors.IsNotFound(err) {
return err
}

klog.Infof("Uninstall karmada descheduler deployment on host cluster successfully")
return nil
}
59 changes: 59 additions & 0 deletions pkg/karmadactl/addons/descheduler/manifests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package descheduler

const karmadaDeschedulerDeployment = `
apiVersion: apps/v1
kind: Deployment
metadata:
name: karmada-descheduler
namespace: {{ .Namespace }}
labels:
app: karmada-descheduler
spec:
selector:
matchLabels:
app: karmada-descheduler
replicas: {{ .Replicas }}
template:
metadata:
labels:
app: karmada-descheduler
spec:
tolerations:
- key: node-role.kubernetes.io/master
operator: Exists
containers:
- name: karmada-descheduler
image: {{ .Image }}
imagePullPolicy: IfNotPresent
command:
- /bin/karmada-descheduler
- --kubeconfig=/etc/kubeconfig
- --bind-address=0.0.0.0
- --leader-elect-resource-namespace={{ .Namespace }}
- --v=4
livenessProbe:
httpGet:
path: /healthz
port: 10358
scheme: HTTP
failureThreshold: 3
initialDelaySeconds: 15
periodSeconds: 15
timeoutSeconds: 5
volumeMounts:
- name: kubeconfig
subPath: kubeconfig
mountPath: /etc/kubeconfig
volumes:
- name: kubeconfig
secret:
secretName: kubeconfig
`

// DeploymentReplace is a struct to help to concrete
// the karamda-descheduler deployment bytes with the deployment template
type DeploymentReplace struct {
Namespace string
Replicas *int32
Image string
}
61 changes: 61 additions & 0 deletions pkg/karmadactl/addons/disable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package addons

import (
"fmt"

"github.com/spf13/cobra"
"k8s.io/kubectl/pkg/util/templates"

addonsinit "github.com/karmada-io/karmada/pkg/karmadactl/addons/init"
)

var (
disableExample = templates.Examples(`
# Disable Karmada all addons except karmada-scheduler-estimator on Kubernetes cluster
%[1]s disable all
# Disable Karmada search on Kubernetes cluster
%[1]s disable karmada-search
# Disable Karmada search and descheduler on Kubernetes cluster
%[1]s disable karmada-search karmada-descheduler
# Disable karmada search and scheduler-estimator of member1 cluster to the kubernetes cluster
%[1]s disable karmada-search karmada-scheduler-estimator --cluster member1
# Specify the host cluster kubeconfig
%[1]s disable Karmada-search --kubeconfig /root/.kube/config
# Specify the Karmada control plane kubeconfig
%[1]s disable karmada-search --karmada-kubeconfig /etc/karmada/karmada-apiserver.config
# Sepcify the namespace where Karmada components are installed
%[1]s disable karmada-search --namespace karmada-system
`)
)

// NewCmdAddonsDisable disable Karmada addons on Kubernetes
func NewCmdAddonsDisable(parentCommand string) *cobra.Command {
opts := addonsinit.CommandAddonsDisableOption{}
cmd := &cobra.Command{
Use: "disable",
Short: "disable karmada addons from Kubernetes",
Long: "disable Karmada addons from Kubernetes",
Example: fmt.Sprintf(disableExample, parentCommand),
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if err := opts.Complete(); err != nil {
return err
}
if err := opts.Validate(args); err != nil {
return err
}
if err := opts.Run(args); err != nil {
return err
}
return nil
},
}
opts.GlobalCommandOptions.AddFlags(cmd.PersistentFlags())
return cmd
}
84 changes: 84 additions & 0 deletions pkg/karmadactl/addons/enable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package addons

import (
"fmt"

"github.com/spf13/cobra"
"k8s.io/klog/v2"
"k8s.io/kubectl/pkg/util/templates"

addonsinit "github.com/karmada-io/karmada/pkg/karmadactl/addons/init"
"github.com/karmada-io/karmada/pkg/version"
)

var (
enableExample = templates.Examples(`
# Enable Karmada all addons except karmada-scheduler-estimator to Kubernetes cluster
%[1]s enable all
# Enable Karmada search to the Kubernetes cluster
%[1]s enable karmada-search
# Enable karmada search and descheduler to the kubernetes cluster
%[1]s enable karmada-search karmada-descheduler
# Enable karmada search and scheduler-estimator of cluster member1 to the kubernetes cluster
%[1]s enable karmada-search karmada-scheduler-estimator -C member1 --member-kubeconfig /etc/karmada/member.config --member-context member1
# Specify the host cluster kubeconfig
%[1]s enable karmada-search --kubeconfig /root/.kube/config
# Specify the Karmada control plane kubeconfig
%[1]s enable karmada-search --karmada-kubeconfig /etc/karmada/karmada-apiserver.config
# Specify the karmada-search image
%[1]s enable karmada-search --karmada-search-image swr.ap-southeast-1.myhuaweicloud.com/karmada/karmada-scheduler-estimator:latest
# Sepcify the namespace where Karmada components are installed
%[1]s enable karmada-search --namespace karmada-system
`)
)

// NewCmdAddonsEnable enable Karmada addons on Kubernetes
func NewCmdAddonsEnable(parentCommand string) *cobra.Command {
opts := addonsinit.CommandAddonsEnableOption{}
cmd := &cobra.Command{
Use: "enable",
Short: "enable Karmada addons from Kubernetes",
Long: "enable Karmada addons from Kubernetes",
Example: fmt.Sprintf(enableExample, parentCommand),
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if err := opts.Complete(); err != nil {
return err
}
if err := opts.Validate(args); err != nil {
return err
}
if err := opts.Run(args); err != nil {
return err
}
return nil
},
}

releaseVer, err := version.ParseGitVersion(version.Get().GitVersion)
if err != nil {
klog.Infof("No default release version found. build version: %s", version.Get().String())
releaseVer = &version.ReleaseVersion{} // initialize to avoid panic
}

flags := cmd.PersistentFlags()
opts.GlobalCommandOptions.AddFlags(flags)
flags.IntVar(&opts.WaitPodReadyTimeout, "pod-timeout", 30, "Wait pod ready timeout.")
flags.IntVar(&opts.WaitAPIServiceReadyTimeout, "apiservice-timeout", 30, "Wait apiservice ready timeout.")
flags.StringVar(&opts.KarmadaSearchImage, "karmada-search-image", fmt.Sprintf("swr.ap-southeast-1.myhuaweicloud.com/karmada/karmada-search:%s", releaseVer.PatchRelease()), "karmada search image")
flags.Int32Var(&opts.KarmadaSearchReplicas, "karmada-search-replicas", 1, "Karmada search replica set")
flags.StringVar(&opts.KarmadaDeschedulerImage, "karmada-descheduler-image", fmt.Sprintf("swr.ap-southeast-1.myhuaweicloud.com/karmada/karmada-descheduler:%s", releaseVer.PatchRelease()), "karmada descheduler image")
flags.Int32Var(&opts.KarmadaDeschedulerReplicas, "karmada-descheduler-replicas", 1, "Karmada descheduler replica set")
flags.StringVar(&opts.KarmadaEstimatorImage, "karmada-estimator-image", fmt.Sprintf("swr.ap-southeast-1.myhuaweicloud.com/karmada/karmada-scheduler-estimator:%s", releaseVer.PatchRelease()), "karmada scheduler-estimator image")
flags.Int32Var(&opts.KarmadaEstimatorReplicas, "karmada-estimator-replicas", 1, "Karmada scheduler estimator replica set")
flags.StringVar(&opts.MemberKubeConfig, "member-kubeconfig", "", "Member cluster's kubeconfig which to deploy scheduler estimator")
flags.StringVar(&opts.MemberContext, "member-context", "", "Member cluster's context which to deploy scheduler estimator")
return cmd
}

0 comments on commit c429520

Please sign in to comment.