Scale deployment replicas with kubernetes go client
Asked Answered
D

2

4

I'm trying to scale a deployment with golang client. The problem I've found is that the golang client does not have a scale method for deployments. I don't know how I should do it. The idea that I have is get a deployment, modify the replicas, and then do an update.

package main

import (
    "context"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    appsv1 "k8s.io/api/apps/v1"
    "flag"
    "fmt"
    "os"
    "path/filepath"

)

func main() {
    var kubeconfig *string
    if home := homedir.HomeDir(); home != "" {
        kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
    } else {
        kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
    }
    flag.Parse()

    config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
    if err != nil {
        panic(err)
    }
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err)
    }
    //get and update replicas
    deploymentsClient := clientset.AppsV1().Deployments(apiv1.NamespaceDefault)
    deployment, _ := deploymentsClient.Get(context.TODO(), "demo-deployment", metav1.GetOptions{})
    deploymentsClient.Update(context.TODO(), deployment, metav1.UpdateOptions{})
}

(Example taken from kubernetes client go github repository)

But I don't know if it is the best aproach.

Divulgence answered 7/5, 2020 at 8:54 Comment(0)
S
3

You can also use patch to apply changes to the deployment object.

// here, 
// "client" be the kubernetes client
// "cur" be the current deployment object
// "mod" be the modified deployment object, 
// make sure to use deep copy before modifying the deployment object.

func PatchDeploymentObject(client kubernetes.Interface, cur, mod *apps.Deployment) (*apps.Deployment, error) {
    curJson, err := json.Marshal(cur)
    if err != nil {
        return nil, err
    }

    modJson, err := json.Marshal(mod)
    if err != nil {
        return nil, err
    }

    patch, err := strategicpatch.CreateTwoWayMergePatch(curJson, modJson, apps.Deployment{})
    if err != nil {
        return nil, err
    }

    if len(patch) == 0 || string(patch) == "{}" {
        return cur, nil
    }

    out, err := client.AppsV1().Deployments(cur.Namespace).Patch(cur.Name, types.StrategicMergePatchType, patch)

    return out, err
}
Steck answered 7/5, 2020 at 9:35 Comment(2)
Do you consider that using patch is more safe than using the get and update approach?Divulgence
I do. Because I prefer to log the patch string and see exactly where the changes are applied.Steck
K
7
package main

import (
    "context"
    "log"
    "path/filepath"

    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/rest"
    "k8s.io/client-go/tools/clientcmd"
    "k8s.io/client-go/util/homedir"
)

func main() {
    kubeconfig := filepath.Join(homedir.HomeDir(), ".kube", "config")
    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        config, err = rest.InClusterConfig()
        if err != nil {
            log.Fatal(err)
        }
    }

    client, err := kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatal(err)
    }

    s, err := client.AppsV1().
        Deployments("default").
        GetScale(context.TODO(), "nginx", metav1.GetOptions{})
    if err != nil {
        log.Fatal(err)
    }

    sc := *s
    sc.Spec.Replicas = 10

    us, err := client.AppsV1().
        Deployments("default").
        UpdateScale(context.TODO(),
            "nginx", &sc, metav1.UpdateOptions{})
    if err != nil {
        log.Fatal(err)
    }

    log.Println(*us)
}
Keniakenilworth answered 16/8, 2020 at 16:8 Comment(1)
I was looking at your answer, and saw that you need to get the namespace first, and then you can get the deployment value, then configure the replica. Thanks for your code!Doorkeeper
S
3

You can also use patch to apply changes to the deployment object.

// here, 
// "client" be the kubernetes client
// "cur" be the current deployment object
// "mod" be the modified deployment object, 
// make sure to use deep copy before modifying the deployment object.

func PatchDeploymentObject(client kubernetes.Interface, cur, mod *apps.Deployment) (*apps.Deployment, error) {
    curJson, err := json.Marshal(cur)
    if err != nil {
        return nil, err
    }

    modJson, err := json.Marshal(mod)
    if err != nil {
        return nil, err
    }

    patch, err := strategicpatch.CreateTwoWayMergePatch(curJson, modJson, apps.Deployment{})
    if err != nil {
        return nil, err
    }

    if len(patch) == 0 || string(patch) == "{}" {
        return cur, nil
    }

    out, err := client.AppsV1().Deployments(cur.Namespace).Patch(cur.Name, types.StrategicMergePatchType, patch)

    return out, err
}
Steck answered 7/5, 2020 at 9:35 Comment(2)
Do you consider that using patch is more safe than using the get and update approach?Divulgence
I do. Because I prefer to log the patch string and see exactly where the changes are applied.Steck

© 2022 - 2024 — McMap. All rights reserved.