使用 Golang 修补 Kubernetes 资源
补丁资源比获取资源并整体更新 spec 更快速、更简单。然而,文档略显不足。经过一些试验和错误,我成功了,这里是解决方案。我想分享给其他人,希望能有所帮助!
最近,我需要能够快速调整 Kubernetes 副本控制器中的副本数量。我之前看到的一个解决方案是获取 spec,修改它,然后更新它。有一个更好的方法!
存在一个 Kubernetes 资源的补丁 API。 补丁资源比获取资源并整体更新 spec 更快速、更简单。然而,文档略显不足。
经过一些试验和错误,我成功了,这里是解决方案。我想分享给其他人,希望能有所帮助!
解决方案
我将从解决方案开始。如果这就是你所需要的,那么你可以直接使用。该方案的工作原理的细节将在之后介绍。在这个例子中,我将更新 my-rc
控制器中的副本数量
package main
import (
"encoding/json"
"fmt"
types "k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/client-go/tools/clientcmd"
)
var (
// Leave blank for the default context in your kube config.
context = ""
// Name of the replication controller to scale, and the desired number of replicas.
replicationControllerName = "my-rc"
replicas = uint32(3)
)
// patchStringValue specifies a patch operation for a string.
type patchStringValue struct {
Op string `json:"op"`
Path string `json:"path"`
Value string `json:"value"`
}
// patchStringValue specifies a patch operation for a uint32.
type patchUInt32Value struct {
Op string `json:"op"`
Path string `json:"path"`
Value uint32 `json:"value"`
}
func scaleReplicationController(clientSet *kubernetes.Clientset,
replicasetName string, scale uint32) error {
payload := []patchUInt32Value{{
Op: "replace",
Path: "/spec/replicas",
Value: scale,
}}
payloadBytes, _ := json.Marshal(payload)
_, err := clientSet.
CoreV1().
ReplicationControllers("default").
Patch(replicasetName, types.JSONPatchType, payloadBytes)
return err
}
func main() {
// Get the local kube config.
fmt.Printf("Connecting to Kubernetes Context %v\n", context)
config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
clientcmd.NewDefaultClientConfigLoadingRules(),
&clientcmd.ConfigOverrides{CurrentContext: context}).ClientConfig()
if err != nil {
panic(err.Error())
}
// Creates the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
// Scale our replication controller.
fmt.Printf("Scaling replication controller %v to %v\n", replicationControllerName, replicas)
err = scaleReplicationController(clientset, replicationControllerName, replicas)
if err != nil {
panic(err.Error())
}
}
此代码也作为 gist 提供
机制
Kubernetes 补丁 API 支持几种不同的方法来修改资源。重要的是要意识到,在 REST API 中,没有普遍接受的“标准”方法来表示对资源的更改。
你可以使用三种策略进行补丁
merge
:遵循 JSON Merge Patch Spec (RFC 7386)strategic
:一种战略合并,解决了合并补丁的一些限制(在 此文档中说明)。json
:遵循 JSON Patch Spec (RFC 6902)
这些在以下位置有详细的文档说明
我在这里使用的机制是 json
,我认为这对于读者来说是最清晰的。要使用此策略,我们需要构建一个 payload,描述我们要更改的内容。它可能如下所示
{
"op": "replace",
"path": "/spec/replicas",
"value": 4
}
op
字段可以是 remove
、replace
、add
等(所有细节都在 RFC 6902 中),或者更易读的 jsonpatch.com)。这使得操作对读者来说非常明确,这很有帮助。我们创建一个 struct
,它表示对 string
或整数(或我们需要的任何数据类型)的操作,对其进行序列化并传递给 API。
在底层,Golang 客户端会将此简单地转换为类似于以下内容的 HTTP 调用
PATCH /api/v1/namespaces/default/replicationcontrollers/app-server-blue HTTP/1.1
Host: 127.0.0.1
Content-Type: application/json-patch+json
Content-Length: 70
[{
"op": "replace",
"path": "/spec/replicas",
"value": 4
}]
这对应于 Patch Operations 上的文档。请注意,补丁操作类型在 Content-Type
标头中指定。
希望这能帮助你,如果你需要补丁资源,正在与文档作斗争,并且像我一样是 Go 新手! 欢迎提出任何关于如何使代码更简洁或更符合惯例的建议。
感谢以下文章和 issue 帮助我理解了这一点