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.

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注