目录
注意: patch 是一种更新操作,其作用域为对象的一些特定字段而不是整个对象。 这使得你可以更新对象的特定字段集合而不必先要读回对象。
kubectl apply
更新对象的现时配置,它是通过向 API 服务器发送一个 patch 请求 来执行更新动作的。 所提交的补丁中定义了对现时对象配置中特定字段的更新。 kubectl apply
命令会使用当前的配置文件、现时配置以及现时配置中保存的 last-applied-configuration
注解内容来计算补丁更新内容。
合并补丁计算
kubectl apply
命令将配置文件的内容写入到 kubectl.kubernetes.io/last-applied-configuration
注解中。 这些内容用来识别配置文件中已经移除的、因而也需要从现时配置中删除的字段。 用来计算要删除或设置哪些字段的步骤如下:
- 计算要删除的字段,即在
last-applied-configuration
中存在但在 配置文件中不再存在的字段。- 计算要添加或设置的字段,即在配置文件中存在但其取值与现时配置不同的字段。
下面是一个例子。假定此文件是某 Deployment 对象的配置文件:
-
apiVersion: apps/v1
-
-
kind: Deployment
-
-
metadata:
-
-
name: nginx-deployment
-
-
spec:
-
-
selector:
-
-
matchLabels:
-
-
app: nginx
-
-
template:
-
-
metadata:
-
-
labels:
-
-
app: nginx
-
-
spec:
-
-
containers:
-
-
- name: nginx
-
-
image: nginx:1.16.1 # 更新该镜像
-
-
ports:
-
-
- containerPort: 80
同时假定同一 Deployment 对象的现时配置如下:
-
apiVersion: apps/v1
-
kind: Deployment
-
metadata:
-
annotations:
-
# ...
-
kubectl.kubernetes.io/last-applied-configuration: |
-
{
"apiVersion":
"apps/v1",
"kind":
"Deployment",
-
"metadata":{
"annotations":{},
"name":
"nginx-deployment",
"namespace":
"default"},
-
"spec":{
"minReadySeconds":5,
"selector":{
"matchLabels":{
"app":nginx}},
"template":{
"metadata":{
"labels":{
"app":
"nginx"}},
-
"spec":{
"containers":[{
"image":
"nginx:1.14.2",
"name":
"nginx",
-
"ports":[{
"containerPort":80}]}]}}}}
-
# ...
-
spec:
-
replicas: 2
-
# ...
-
minReadySeconds: 5
-
selector:
-
matchLabels:
-
# ...
-
app: nginx
-
template:
-
metadata:
-
# ...
-
labels:
-
app: nginx
-
spec:
-
containers:
-
- image: nginx:1.14.2
-
# ...
-
name: nginx
-
ports:
-
- containerPort: 80
-
# ...
下面是 kubectl apply
将执行的合并计算:
- 通过读取
last-applied-configuration
并将其与配置文件中的值相比较, 计算要删除的字段。 对于本地对象配置文件中显式设置为空的字段,清除其在现时配置中的设置, 无论这些字段是否出现在last-applied-configuration
中。 在此例中,minReadySeconds
出现在last-applied-configuration
注解中,但 并不存在于配置文件中。 动作: 从现时配置中删除minReadySeconds
字段。- 通过读取配置文件中的值并将其与现时配置相比较,计算要设置的字段。 在这个例子中,配置文件中的
image
值与现时配置中的image
不匹配。 动作:设置现时配置中的image
值。- 设置
last-applied-configuration
注解的内容,使之与配置文件匹配。- 将第 1、2、3 步骤得出的结果合并,构成向 API 服务器发送的补丁请求内容。
下面是此合并操作之后形成的现时配置:
-
apiVersion: apps/v1
-
kind: Deployment
-
metadata:
-
annotations:
-
# ...
-
# 注解中包含更新后的 image,nginx 1.11.9,
-
# 但不包含更新后的 replicas
-
kubectl.kubernetes.io/last-applied-configuration: |
-
{
"apiVersion":
"apps/v1",
"kind":
"Deployment",
-
"metadata":{
"annotations":{},
"name":
"nginx-deployment",
"namespace":
"default"},
-
"spec":{
"selector":{
"matchLabels":{
"app":nginx}},
"template":{
"metadata":{
"labels":{
"app":
"nginx"}},
-
"spec":{
"containers":[{
"image":
"nginx:1.16.1",
"name":
"nginx",
-
"ports":[{
"containerPort":80}]}]}}}}
-
# ...
-
spec:
-
selector:
-
matchLabels:
-
# ...
-
app: nginx
-
replicas: 2
-
# minReadySeconds 此字段被清除
-
# ...
-
template:
-
metadata:
-
# ...
-
labels:
-
app: nginx
-
spec:
-
containers:
-
- image: nginx:1.16.1
-
# ...
-
name: nginx
-
ports:
-
- containerPort: 80
-
# ...
-
# ...
-
# ...
-
# ...
不同类型字段的合并方式
配置文件中的特定字段与现时配置合并时,合并方式取决于字段类型。 字段类型有几种:
基本类型:字段类型为
string
、integer
或boolean
之一。 例如:image
和replicas
字段都是基本类型字段。动作: 替换。
map:也称作 object。类型为
map
或包含子域的复杂结构。例如,labels
、annotations
、spec
和metadata
都是 map。动作: 合并元素或子字段。
list:包含元素列表的字段,其中每个元素可以是基本类型或 map。 例如,
containers
、ports
和args
都是 list。动作: 不一定。
当 kubectl apply
更新某个 map 或 list 字段时,它通常不会替换整个字段,而是会 更新其中的各个子元素。例如,当合并 Deployment 的 spec
时,kubectl
并不会 将其整个替换掉。相反,实际操作会是对 replicas
这类 spec
的子字段来执行比较和更新。
合并对基本类型字段的更新
基本类型字段会被替换或清除。
说明:
-
表示的是“不适用”,因为指定数值未被使用。
字段在对象配置文件中 | 字段在现时对象配置中 | 字段在 last-applied-configuration 中 |
动作 |
---|---|---|---|
是 | 是 | - | 将配置文件中值设置到现时配置上。 |
是 | 否 | - | 将配置文件中值设置到现时配置上。 |
否 | - | 是 | 从现时配置中移除。 |
否 | - | 否 | 什么也不做。保持现时值。 |
合并对 map 字段的变更
用来表示映射的字段在合并时会逐个子字段或元素地比较:
说明:
-
表示的是“不适用”,因为指定数值未被使用。
键存在于对象配置文件中 | 键存在于现时对象配置中 | 键存在于 last-applied-configuration 中 |
动作 |
---|---|---|---|
是 | 是 | - | 比较子域取值。 |
是 | 否 | - | 将现时配置设置为本地配置值。 |
否 | - | 是 | 从现时配置中删除键。 |
否 | - | 否 | 什么也不做,保留现时值。 |
合并 list 类型字段的变更
对 list 类型字段的变更合并会使用以下三种策略之一:
- 如果 list 所有元素都是基本类型则替换整个 list。
- 如果 list 中元素是复合结构则逐个元素执行合并操作。
- 合并基本类型元素构成的 list。
策略的选择是基于各个字段做出的。
如果 list 中元素都是基本类型则替换整个 list
将整个 list 视为一个基本类型字段。或者整个替换或者整个删除。 此操作会保持 list 中元素顺序不变
示例: 使用 kubectl apply
来更新 Pod 中 Container 的 args
字段。此操作会 将现时配置中的 args
值设为配置文件中的值。 所有之前添加到现时配置中的 args
元素都会丢失。 配置文件中的 args
元素的顺序在被添加到现时配置中时保持不变。
-
# last-applied-configuration 值
-
args: [
"a",
"b"]
-
-
# 配置文件值
-
args: [
"a",
"c"]
-
-
# 现时配置
-
args: [
"a",
"b",
"d"]
-
-
# 合并结果
-
args: [
"a",
"c"]
合并操作将配置文件中的值当做新的 list 值。
如果 list 中元素为复合类型则逐个执行合并
此操作将 list 视为 map,并将每个元素中的特定字段当做其主键。 逐个元素地执行添加、删除或更新操作。结果顺序无法得到保证。
此合并策略会使用每个字段上的一个名为 patchMergeKey
的特殊标签。 Kubernetes 源代码中为每个字段定义了 patchMergeKey
: types.go 当合并由 map 组成的 list 时,给定元素中被设置为 patchMergeKey
的字段会被 当做该元素的 map 键值来使用。
例如: 使用 kubectl apply
来更新 Pod 规约中的 containers
字段。 此操作会将 containers
列表视作一个映射来执行合并,每个元素的主键为 name
。
-
# last-applied-configuration 值
-
containers:
-
-
name: nginx
-
image:
nginx:
1.16
-
-
name: nginx-helper-a
# 键 nginx-helper-a 会被删除
-
image:
helper:
1.3
-
-
name: nginx-helper-b
# 键 nginx-helper-b 会被保留
-
image:
helper:
1.3
-
-
# 配置文件值
-
containers:
-
-
name: nginx
-
image:
nginx:
1.16
-
-
name: nginx-helper-b
-
image:
helper:
1.3
-
-
name: nginx-helper-c
# 键 nginx-helper-c 会被添加
-
image:
helper:
1.3
-
-
# 现时配置
-
containers:
-
-
name: nginx
-
image:
nginx:
1.16
-
-
name: nginx-helper-a
-
image:
helper:
1.3
-
-
name: nginx-helper-b
-
image:
helper:
1.3
-
args: [
"run"]
# 字段会被保留
-
-
name: nginx-helper-d
# 键 nginx-helper-d 会被保留
-
image:
helper:
1.3
-
-
# 合并结果
-
containers:
-
-
name: nginx
-
image:
nginx:
1.16
-
# 元素 nginx-helper-a 被删除
-
-
name: nginx-helper-b
-
image:
helper:
1.3
-
args: [
"run"]
# 字段被保留
-
-
name: nginx-helper-c
# 新增元素
-
image:
helper:
1.3
-
-
name: nginx-helper-d
# 此元素被忽略(保留)
-
image:
helper:
1.3
解释:
- 名为 "nginx-helper-a" 的容器被删除,因为配置文件中不存在同名的容器。
- 名为 "nginx-helper-b" 的容器的现时配置中的
args
被保留。kubectl apply
能够辩识出现时配置中的容器 "nginx-helper-b" 与配置文件 中的容器 "nginx-helper-b" 相同,即使它们的字段值有些不同(配置文件中未给定args
值)。这是因为patchMergeKey
字段(name)的值在两个版本中都一样。- 名为 "nginx-helper-c" 的容器是新增的,因为在配置文件中的这个容器尚不存在 于现时配置中。
- 名为 "nginx-helper-d" 的容器被保留下来,因为在 last-applied-configuration 中没有与之同名的元素。
合并基本类型元素 list
在 Kubernetes 1.5 中,尚不支持对由基本类型元素构成的 list 进行合并。
说明: 选择上述哪种策略是由源码中给定字段的
patchStrategy
标记来控制的: types.go 如果 list 类型字段未设置patchStrategy
,则整个 list 会被替换掉。
转载:https://blog.csdn.net/Trollz/article/details/128312857