为了账号安全,请及时绑定邮箱和手机立即绑定

k8s如何秘密更新特定值

k8s如何秘密更新特定值

Go
一只名叫tom的猫 2023-03-07 11:44:09
我需要更新具有特定值的秘密,(秘密包含其他数据)我的问题是我如何才能更新值而不是所有秘密数据(我不想覆盖现有数据)。我的意思是如果这个秘密有额外的价值我不想覆盖他们只是条目fooupdSec := v1.Secret{    TypeMeta: metav1.TypeMeta{},    ObjectMeta: metav1.ObjectMeta{        Name:      "d-values",        Namespace: "terv”,    },    Immutable:  nil,    Data:       nil,    StringData: nil,    Type:       "Opaque",}updSec.Data[“foo”] = newValif err := r.Client.Update(ctx, &updSec); err != nil {    return ctrl.Result{}, err}问题是这个秘密已经存在,我在这里创建新对象,但不确定如何正确地做...我需要一个秘密,它只调用d-values更新newValfor keyfoo更新在我运行后尝试答案中的代码时patch, err := yaml.Marshal(updSec) 数据如下所示,补丁因错误而失败,知道它是否相关吗?如果我尝试使用 c.Client.Update 它可以工作但不能使用Patch但是 Patch 是正确的方法,就好像我之前有联系应该保留它们一样..
查看完整描述

1 回答

?
冉冉说

TA贡献1877条经验 获得超1个赞

我不认为您可以使用该Update方法更新单个密钥,但您当然可以改为使用Patch。这是一个使用 StrategicMergePatch 的示例;它将val2用值替换秘密中的密钥newval:


package main


import (

  "context"

  "encoding/json"

  "flag"

  "fmt"

  "path/filepath"


  v1 "k8s.io/api/core/v1"

  metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

  "k8s.io/apimachinery/pkg/types"

  "k8s.io/client-go/kubernetes"

  "k8s.io/client-go/tools/clientcmd"

  "k8s.io/client-go/util/homedir"

)


func main() {

  var kubeconfig *string

  var namespace *string

  var secretname *string


  namespace = flag.String("namespace", "", "namespace of secret")

  secretname = flag.String("name", "", "name of secret")


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


  if *namespace == "" {

    panic(fmt.Errorf("you must specify a namespace"))

  }


  if *secretname == "" {

    panic(fmt.Errorf("you must specify a secret name"))

  }


  config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)

  if err != nil {

    panic(err)

  }


  clientset, err := kubernetes.NewForConfig(config)

  if err != nil {

    panic(err)

  }


  secretClient := clientset.CoreV1().Secrets(*namespace)

  ctx := context.TODO()


  updSec := v1.Secret{

    Data: map[string][]byte{

      "val2": []byte("newval"),

    },

  }


  payloadBytes, err := json.Marshal(updSec)

  if err != nil {

    panic(err)

  }


  if _, err = secretClient.Patch(ctx, *secretname,

    types.StrategicMergePatchType, payloadBytes, metav1.PatchOptions{}); err != nil {

    panic(err)

  }


  // Fetch updated secret

  sec, err := secretClient.Get(ctx, *secretname, metav1.GetOptions{})

  if err != nil {

    panic(err)

  }

  secJson, err := json.MarshalIndent(sec, "", "  ")

  if err != nil {

    panic(err)

  }


  fmt.Print(string(secJson))

}

例如,如果我创建这样的秘密:


kubectl create secret generic \

  --from-literal val1=key1 \

  --from-literal val2=key2 example

然后像这样运行上面的代码:


go run main.go -namespace default -name example

该代码将输出更新密码。查看该data部分,我们看到:


  "data": {

    "val1": "a2V5MQ==",

    "val2": "bmV3dmFs"

  },

如果我们解码,val2我们会看到:


$ kubectl get secret example -o json | jq '.data.val2|@base64d'

"newval"

使用运营商 SDK

如果您使用的是 Operator SDK,则可以Update在第一次读取现有值时使用,如下所示:


  // Read the existing secret

  secret := &corev1.Secret{}

  if err := r.Get(ctx, req.NamespacedName, secret); err != nil {

    panic(err)

  }


  // Check if it needs to be modified

  val, ok := secret.Data["val2"]


  // If yes, update the secret with a new value and then write

  // the entire object back with Update

  if !ok || !bytes.Equal(val, []byte("val2")) {

    ctxlog.Info("needs update", "secret", secret)

    secret.Data["val2"] = []byte("newval")

    if err := r.Update(ctx, secret); err != nil {

      panic(err)

    }

  }

Patch如果您只想提交部分更新,则可以使用该方法:


  if !ok || !bytes.Equal(val, []byte("val2")) {

    ctxlog.Info("needs update", "secret", secret)

    newVal := corev1.Secret{

      Data: map[string][]byte{

        "val2": []byte("newval"),

      },

    }


    patch, err := json.Marshal(newVal)

    if err != nil {

      panic(err)

    }


    if err := r.Client.Patch(ctx, secret, client.RawPatch(types.StrategicMergePatchType, patch)); err != nil {

      panic(err)

    }

  }

这与前面的示例几乎相同。文档中有使用 client.Patch 方法的示例,但老实说,我觉得示例不是很清楚。


查看完整回答
反对 回复 2023-03-07
  • 1 回答
  • 0 关注
  • 119 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信