kubectl patch 更新API对象
kubectl patch 命令拥有一个 type 参数,可以将其设置为以下值:
参数值 合并类型
json JSON 补丁, RFC 6902
merge JSON 合并补丁, RFC 7386
strategic 策略性合并补丁(type的默认参数)
关于 JSON 补丁 与 JSON 合并补丁的区别,请查看 JSON 补丁 与 JSON 合并补丁。
http://erosb.github.io/post/json-patch-vs-merge-patch/
1、策略性合并补丁
这里有一个副本数为 2 的 Deployment 配置文件,每个副本是一个拥有单个容器的 Pod :
cat deployment-patch-demo.yaml apiVersion: apps/v1 kind: Deployment metadata: name: patch-demo spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: patch-demo-ctr image: nginx
创建这个 Deployment :
查看和这个 Deployment 关联的 Pod :
kubectl get pods
输出内容显示这个 Deployment 拥有两个 Pod 。1/1 表示每个 Pod 拥有一个容器:
[root@maste test]# kubectl get pods | grep patch patch-demo-7cd4f9bb5c-4hvl9 1/1 Running patch-demo-7cd4f9bb5c-dxjcq 1/1 Running
记下这些运行中的 Pod 的名称,稍后您会看到这些 Pod 被中止了并且会被新的 Pod 所取代。
此时,每个 Pod 拥有一个运行 nginx 镜像的容器。现在假设您希望每个 Pod 拥有两个容器:一个运行 nginx,另一个运行 redis。
创建一个文件 patch-file.yaml ,内容如下:
spec: template: spec: containers: - name: patch-demo-ctr-2 image: redis
给这个 Deployment 打补丁:
kubectl patch deployment patch-demo --patch "$(cat patch-file.yaml)"
查看打补丁后的 Deployment:
kubectl get deployment patch-demo –output yaml
输出内容显示这个 Deployment 的 PodSpec 中有两个容器:
spec: containers: - image: redis imagePullPolicy: Always name: patch-demo-ctr-2 resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File - image: nginx imagePullPolicy: Always name: patch-demo-ctr resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst
查看打补丁后的 Deployment 所关联的 Pod :
kubectl get pods
输出内容显示当前正在运行的 Pod 名称与打补丁之前的 Pod 名称不一样了。这个 Deployment 中止了原先的 Pod 然后使用更新后的 spec 重新创建了两个新的 Pod 。2/2 表示每个 Pod 拥有两个容器:
[root@master test]# kubectl get pods | grep patch patch-demo-78b4db8596-hbtlh 2/2 Running 0 2m patch-demo-78b4db8596-sd4mt 2/2 Running 0 2m
让我们仔细看看这个补丁例子中的其中一个 Pod :
kubectl get pod patch-demo-78b4db8596-sd4mt --output yaml
输出内容显示这个 Pod 拥有两个容器,一个运行 nginx ,一个运行 redis :
containers: - image: redis ... - image: nginx
…
关于策略性合并补丁的说明
通过补丁,您可以避免定义整个对象,只需要定义您希望更改的部分。比如:在上述例子中,您只需要在 PodSpec 中 containers 列表中定义了一个容器。
上述例子中的补丁称为 策略性合并补丁 。通过策略性合并补丁,您只需要定义新增的元素就可以更新一个列表。列表中已有的元素仍然保留,新增的元素和已有的元素会被合并。上述例子中,最终结果的 containers 列表中既有原先的 nginx 容器,也有新增的 redis 容器。
2、使用一个 JSON 合并补丁更新一个 Deployment
策略性合并补丁与 JSON 合并补丁 是不一样的。如果您希望使用 JSON 合并补丁更新一个列表,您必须重新定义整个列表。新的列表会完全替换掉原先的列表。
接下来,做一个 JSON 合并补丁。创建一个名为 patch-file-2.yaml 的文件,内容如下:
spec: template: spec: containers: - name: patch-demo-ctr-3 image: memcached
在 patch 命令中,设置参数 type 的值为 merge :
kubectl patch deployment patch-demo –type merge –patch "$(cat patch-file-2.yaml)"
查看打补丁后的 Deployment :
kubectl get deployment patch-demo --output yaml
在这个补丁中您定义的 containers 列表只有一个容器。输出内容显示这个只有一个容器的 containers 列表把原先的 containers 列表替换了。
spec: containers: - image: gcr.io/google-samples/node-hello:1.0 ... name: memcached
列出运行中的 Pod :
kubectl get pods
在输出内容中,您可以看到原先的 Pod 被中止了,然后有新的 Pod 被创建了。1/1 表示每个 Pod 只拥有一个容器。
[root@master test]# kubectl get pods | grep patch patch-demo-54d9d48dbb-2blrd 1/1 Running 0 12s patch-demo-54d9d48dbb-72sk5 1/1 Running 0 19s
kubectl patch 命令的其它形式
kubectl patch 命令接受 YAML 或 JSON 格式的补丁,且补丁能够以文件或直接以命令行参数的形式进行传递。
创建一个名为 patch-file.json 的文件,内容如下:
{ "spec": { "template": { "spec": { "containers": [ { "name": "patch-demo-ctr-2", "image": "redis" } ] } } } }
以下的命令是等价的:
kubectl patch deployment patch-demo --patch "$(cat patch-file.yaml)" kubectl patch deployment patch-demo --patch $'spec:\n template:\n spec:\n containers:\n - name: patch-demo-ctr-2\n image: redis' kubectl patch deployment patch-demo --patch "$(cat patch-file.json)" kubectl patch deployment patch-demo --patch '{"spec": {"template": {"spec": {"containers": [{"name": "patch-demo-ctr-2","image": "redis"}]}}}}'
结论:
在这个例子中,您使用 kubectl patch 命令对一个 Deployment 的实时配置进行了更新。您并没有改变原先用来创建 Deployment 对象的那个配置文件。其它用于更新 API 对象的命令有: kubectl annotate, kubectl edit, kubectl replace, kubectl scale, and kubectl apply.