使用 kubectl patch 更新 API 对象
这个任务展示了如何使用 kubectl patch
就地更新 API 对象。这个任务中的练习演示了一个策略性合并 patch 和一个 JSON 合并 patch。
准备开始
你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 如果你还没有集群,你可以通过 Minikube 构建一 个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:
要获知版本信息,请输入 kubectl version
.
使用策略合并 patch 更新 Deployment
下面是具有两个副本的 Deployment 的配置文件。每个副本是一个 Pod,有一个容器:
application/deployment-patch.yaml |
---|
|
创建 Deployment:
kubectl create -f https://k8s.io/examples/application/deployment-patch.yaml
查看与 Deployment 相关的 Pod:
kubectl get pods
输出显示 Deployment 有两个 Pod。1/1
表示每个 Pod 有一个容器:
NAME READY STATUS RESTARTS AGE
patch-demo-28633765-670qr 1/1 Running 0 23s
patch-demo-28633765-j5qs3 1/1 Running 0 23s
把运行的 Pod 的名字记下来。稍后,您将看到这些 Pod 被终止并被新的 Pod 替换。
此时,每个 Pod 都有一个运行 nginx 镜像的容器。现在假设您希望每个 Pod 有两个容器:一个运行 nginx,另一个运行 redis。
创建一个名为 patch-file-containers.yaml
的文件。内容如下:
spec:
template:
spec:
containers:
- name: patch-demo-ctr-2
image: redis
修补您的 Deployment:
kubectl patch deployment patch-demo --patch "$(cat patch-file-containers.yaml)"
查看修补后的 Deployment:
kubectl get deployment patch-demo --output yaml
输出显示 Deployment 中的 PodSpec 有两个容器:
containers:
- image: redis
imagePullPolicy: Always
name: patch-demo-ctr-2
...
- image: nginx
imagePullPolicy: Always
name: patch-demo-ctr
...
查看与 patch Deployment 相关的 Pod:
kubectl get pods
输出显示正在运行的 Pod 与以前运行的 Pod 有不同的名称。Deployment 终止了旧的 Pod,并创建了两个 符合更新的部署规范的新 Pod。2/2
表示每个 Pod 有两个容器:
NAME READY STATUS RESTARTS AGE
patch-demo-1081991389-2wrn5 2/2 Running 0 1m
patch-demo-1081991389-jmg7b 2/2 Running 0 1m
仔细查看其中一个 patch-demo Pod:
kubectl get pod <your-pod-name> --output yaml
输出显示 Pod 有两个容器:一个运行 nginx,一个运行 redis:
containers:
- image: redis
...
- image: nginx
...
策略性合并类的 patch
您在前面的练习中所做的 patch 称为策略性合并 patch
。 请注意,patch 没有替换容器
列表。相反,它向列表中添加了一个新容器。换句话说, patch 中的列表与现有列表合并。当您在列表中使用策略性合并 patch 时,并不总是这样。 在某些情况下,列表是替换的,而不是合并的。
对于策略性合并 patch,列表可以根据其 patch 策略进行替换或合并。patch 策略由 Kubernetes 源代码中字段标记中的 patchStrategy
键的值指定。 例如,PodSpec
结构体的 Containers
字段有 merge
的 patchStrategy
:
type PodSpec struct {
...
Containers []Container `json:"containers" patchStrategy:"merge" patchMergeKey:"name" ...`
您还可以在 OpenApi spec 规范中看到 patch 策略:
"io.k8s.api.core.v1.PodSpec": {
...
"containers": {
"description": "List of containers belonging to the pod. ...
},
"x-kubernetes-patch-merge-key": "name",
"x-kubernetes-patch-strategy": "merge"
},
您可以在 Kubernetes API 文档 中看到 patch 策略
创建一个名为 patch-file-tolerations.yaml
的文件。内容如下:
spec:
template:
spec:
tolerations:
- effect: NoSchedule
key: disktype
value: ssd
patch Deployment:
kubectl patch deployment patch-demo --patch "$(cat patch-file-containers.yaml)"
kubectl patch deployment patch-demo --patch $(cat patch-file-containers.yaml)
查看 patch Deployment:
kubectl get deployment patch-demo --output yaml
输出结果显示部署中的 PodSpec 只有一个默认:
containers:
- image: redis
imagePullPolicy: Always
name: patch-demo-ctr-2
...
- image: nginx
imagePullPolicy: Always
name: patch-demo-ctr
...
tolerations:
- effect: NoSchedule
key: disktype
value: ssd
请注意,PodSpec 中的 tolerations
列表被替换,而不是合并。这是因为 PodSpec 的 tolerance 字段的字段标签中没有 patchStrategy
键。所以策略合并 patch 使用默认的 patch 策略,也就是 replace
。
type PodSpec struct {
...
Tolerations []Toleration `json:"tolerations,omitempty" protobuf:"bytes,22,opt,name=tolerations"`
使用 JSON 合并 patch 更新部署
策略性合并 patch 不同于 JSON 合并 patch。 使用 JSON 合并 patch,如果您想更新列表,您必须指定整个新列表。新的列表完全取代了现有的列表。
kubectl patch
命令有一个 type
参数,您可以将其设置为以下值之一:
Parameter value | Merge type |
---|---|
json | JSON Patch, RFC 6902 |
merge | JSON Merge Patch, RFC 7386 |
strategic | Strategic merge patch |
有关 JSON patch 和 JSON 合并 patch 的比较,查看 JSON patch 和 JSON 合并 patch。
type
参数的默认值是 strategic
。在前面的练习中,我们做了一个策略性的合并 patch。
下一步,在相同的部署上执行 JSON 合并 patch。创建一个名为 patch-file-2
的文件。内容如下:
spec:
template:
spec:
containers:
- name: patch-demo-ctr-3
image: gcr.io/google-samples/node-hello:1.0
在 patch 命令中,将 type
设置为 merge
:
kubectl patch deployment patch-demo --type merge --patch "$(cat patch-file-2.yaml)"
查看 patch 部署:
kubectl get deployment patch-demo --output yaml
patch 中指定的容器
列表只有一个容器。 输出显示您的一个容器列表替换了现有的容器
列表。
spec:
containers:
- image: gcr.io/google-samples/node-hello:1.0
...
name: patch-demo-ctr-3
列表中运行的 Pod:
kubectl get pods
在输出中,您可以看到已经终止了现有的 Pod,并创建了新的 Pod。1/1
表示每个新 Pod只运行一个容器。
NAME READY STATUS RESTARTS AGE
patch-demo-1307768864-69308 1/1 Running 0 1m
patch-demo-1307768864-c86dc 1/1 Running 0 1m
kubectl patch 命令的其他形式
kubectl patch
命令使用 YAML 或 JSON。它可以将 patch 作为文件,也可以直接在命令行中使用。
创建一个文件名称是 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
更改部署对象的实时配置。您没有更改最初用于创建部署对象的配置文件。 用于更新 API 对象的其他命令包括 kubectl annotate, kubectl edit, kubectl replace, kubectl scale, 和 kubectl apply。