本页面介绍如何在恢复过程中使用转换规则修改 Kubernetes 资源。转换规则是对之前称为“替换规则”功能的改进。由于它们不向后兼容替换规则,因此已弃用的替换规则接口仍然可用。
如需查看替换规则的文档,请参阅在恢复期间修改资源。
概览
在恢复过程中修改 Kubernetes 资源的原因可能有多种:
您可能想要使用其他存储空间预配工具创建 PersistentVolumeClaim (PVC)。例如,您希望从 Kubernetes 树内驱动程序迁移到 CSI 驱动程序。
您可能想要恢复命名空间并使用不同的名称。
您可能希望添加、更改或删除与标签或 ConfigMap 键关联的值。
您可能想要更改 Deployment 或 StatefulSet 中的副本数量。
Backup for GKE 提供了一种用于进行这些更改的机制,称为转换规则,您可以选择在 RestorePlan
中定义这些规则。
在恢复过程中,转换规则的工作原理如下:
规则会整理成有序列表。
所有资源(不包括不可用转换的
CustomResourceDefinition
资源)将按顺序通过此规则列表按顺序恢复。每条规则都包含简短说明、匹配条件和资源修改。
如果资源不符合规则的条件,它将移动到列表中的下一条规则,而不会进行修改。
如果资源与规则的条件匹配,则该规则的修改将应用于该资源,然后再移动到列表中的下一条规则。
如果定义了多个规则,则系统会根据先前规则修改的资源版本评估每条规则的匹配条件。
应用任何匹配规则的修改后,资源的最终版本将在集群中创建。
转换规则参数
提供以下信息来创建转换规则:
description
:这是转换规则的简短说明。resourceFilter
:此过滤条件用于匹配资源。如果未提供resourceFilter
,则所有资源都与此规则匹配。fieldActions
:这是对与resourceFilter
匹配的资源进行的修改列表。修改内容作为有序操作列表提供。顺序很重要,因为一个操作的结果可能会影响列表中的下一个操作。如果任何操作失败,整个恢复都会失败。
资源过滤条件 (resourceFilter
)
要定义资源过滤条件,请提供以下参数:
参数 | 必需 | 说明 |
---|---|---|
namespaces |
可选 | 这是命名空间列表。如需匹配此规则,该资源必须是命名空间型资源,并具有给定命名空间之一。如果没有为此参数提供任何值,则所有资源都将匹配(所有命名空间型资源和集群范围资源)。 |
groupKinds |
可选 |
这是 Kubernetes 资源 Group/Kind 元组列表:
|
jsonPath |
可选 | 这是一个 JSONPath 表达式,用于与资源匹配。 |
JSONPath (jsonPath
)
JSONPath 表达式用于与资源进行匹配。如果表达式的结果针对某个资源不为空,则该资源被视为匹配。
假设有以下资源:
YAML
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-cm
labels:
app: mysql
app.kubernetes.io/name: mysql
data:
primary.cnf: |
# Apply this config only on the primary.
[mysqld]
log-bin
replica.cnf: |
# Apply this config only on replicas.
[mysqld]
super-read-only
JSON
{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"name": "mysql-cm",
"labels": {
"app": "mysql",
"app.kubernetes.io/name": "mysql"
}
},
"data": {
"primary.cnf": "# Apply this config only on the primary.\n[mysqld]\nlog-bin\n",
"replica.cnf": "# Apply this config only on replicas.\n[mysqld]\nsuper-read-only\n"
}
}
使用 JSONPath 表达式的示例:
表达式 | 说明 | 结果 |
---|---|---|
.metadata[?(@.name == 'mysql-cm')] |
metadata 对象包含 name 键,其值为“mysql-cm” |
[ |
.metadata.labels['app\.kubernetes\.io/name'] |
metadata.labels 下的键“app.kubernetes.io/name”的字符串值 |
[ |
.data['primary\.cnf'] |
data 下的键“primary.cnf”的对象值 |
[ |
.metadata[?(@.name =~ /^mysql-.*/i)] |
metadata 对象包含 name 键,其值与正则表达式“/^mysql-.*/i”匹配。正斜线 / 用于分隔正则表达式模式。正则表达式末尾的 i 是表示不区分大小写匹配的标志。 |
[ |
只要 JSONPath 表达式的输出不为空,相应的资源就会匹配此规则。因此,.metadata[?(@.name == 'mysql-cm')]
和 .metadata[?(@.name == 'mysql-cm')].name
将生成相同的匹配结果,这与 .metadata.name
为 "mysql-cm"
的资源匹配。
在 JSONPath 中使用过滤条件匹配 Google Cloud 控制台中映射中的键时,需要使用 \
(反斜杠)对 .
(点)进行转义。如果使用 gcloud CLI 或 Terraform Language 在 YAML 环境中提供 JSONPath,则需要 \\
(双反斜杠)。例如,.metadata.labels['app\.kubernetes\.io/name']
等效于 YAML 或 Terraform 中的 .metadata.labels['app\\.kubernetes\\.io/name']
。
我们建议使用支持正则表达式的 JSONPath 评估器工具在使用前测试表达式。您还可以使用 kubectl
验证 JSONPath 表达式的结果。如需查看更多示例,请参阅 JSONPath 支持。
字段操作 (fieldActions
)
字段操作是根据 JSON 补丁建模的,它定义了一个 JSON 文档结构,用于表示要应用于 JSON 文档的操作。要定义字段操作,需要使用以下参数:
path
:这是一个 JSON 指针值,用于引用目标资源中执行操作的位置。JSON 指针始终以/
(斜杠)开头,落在子元素中的属性名称(键)也由/
(斜杠)分隔。op
:这是对资源执行的操作类型,支持五种操作:add
向指定的path
插入新对象或值,具体取决于path
引用的内容。remove
从指定的path
中移除值。replace
将指定path
中的值替换为新值。move
会从某个位置移除值并将其添加到指定的path
。copy
将值从某个位置复制到指定的path
。
您可以使用以下 pod 定义找到每个操作的示例:
YAML
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
JSON
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "nginx",
"namespace": "ns",
"labels": {
"app": "nginx"
}
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx:latest",
"ports": [
{
"containerPort": 80
}
],
"env": [
{
"name": "PROTOCOL",
"value": "https"
}
],
"resources": {
"limits": {
"cpu": "250m",
"memory": "64Mi"
}
}
}
],
"initContainers": [
{
"name": "install",
"image": "busybox:stable",
"command": [
"wget",
"-O",
"/tmp/index.html",
"http://info.cern.ch"
]
}
]
}
}
添加
add
操作始终需要 value
,并且必须是合法 JSON 元素。
以下操作会将值为 "80"
的新环境变量 "PORT"
添加到 nginx
容器。
op: add
path: "/spec/containers/0/env/0"
value: >
{
"name": "PORT",
"value": "80"
}
原始模式
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
已转换
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
- name: PORT # newly added
value: "80" # newly added
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
以下操作会将新标签 app.kubernetes.io/name: nginx
的值添加到 Pod。
op: add
path: "/metadata/labels/app.kubernetes.io~1name"
value: "nginx"
原始模式
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
已转换
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
app.kubernetes.io/name: nginx # newly added
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
以下操作会替换 nginx
容器映像并将其从 "nginx:latest"
更改为 "nginx:stable"
。
op: add
path: "/spec/containers/0/image"
value: nginx:stable
原始模式
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
已转换
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:stable # replaced
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
移除
以下操作移除了 nginx
容器的资源要求。
op: remove
path: "/spec/containers/0/resources"
原始模式
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
已转换
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
# resource requirements are removed
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
替换
replace
操作需要 value
,并且它必须是 JSON 元素。
以下操作会将 nginx
容器映像从 nginx:latest
替换到 nginx:stable
。
op: replace
path: "/spec/containers/0/image"
value: nginx:stable
原始模式
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
已转换
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:stable # replaced
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
移动
move
操作需要 fromPath
。
以下操作会从 nginx
容器中移除环境变量,并将其添加到 install
init 容器中。
op: move
fromPath: "/spec/containers/0/env"
path: "/spec/initContainers/0/env"
原始模式
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
已转换
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
# "env" is moved to "install" container
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
env: # moved "from" nginx container
- name: PROTOCOL
value: https
复制
copy
操作需要 fromPath
。
以下操作会将环境变量从 nginx
容器复制到 install
init 容器。
op: copy
fromPath: "/spec/containers/0/env"
path: "/spec/initContainers/0/env"
原始模式
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
已转换
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: ns
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
env:
- name: PROTOCOL
value: "https"
resources:
limits:
cpu: "250m"
memory: "64Mi"
initContainers:
- name: install
image: busybox:stable
command:
- wget
- "-O"
- "/tmp/index.html"
- http://info.cern.ch
env: # copy from "nginx" container
- name: PROTOCOL
value: https
如需详细了解如何在 Google Cloud 控制台中定义转换规则,请参阅规划一组恢复。
如需通过 gcloud CLI 定义转换规则,请创建一个包含 YAML 数组 transformationRules
的文件,并在 gcloud beta container backup-restore restore-plans create
命令中添加 --transformation-rules-file=
参数。
转换规则示例
以下示例以 gcloud CLI 或 Terraform 配置语言使用的 YAML 格式提供。
更改 PVC 的 StorageClass
以下示例将所有恢复的 PersistentVolumeClaim 资源中的 StorageClass 从 standard
更改为 premium-rwo
:
YAML
transformationRules:
- description: Change StorageClass in PVC from standard to premium-rwo
resourceFilter:
namespaces: []
jsonPath: ".spec[?(@.storageClassName == 'standard')]"
groupKinds:
- resourceGroup: ""
resourceKind: PersistentVolumeClaim
fieldActions:
- op: REPLACE
path: "/spec/storageClassName"
value: "premium-rwo"
Terraform
transformation_rules {
description = "Change StorageClass in PVC from standard to premium-rwo"
resource_filter {
json_path = ".spec[?(@.storageClassName == 'standard')]"
group_kinds {
resource_kind = "PersistentVolumeClaim"
}
}
field_actions {
op = "REPLACE"
path = "/spec/storageClassName"
value = "premium-rwo"
}
}
克隆命名空间
此示例将命名空间从 Alpha 版克隆到 Beta 版 - 创建新的命名空间 "beta"
,并将 "alpha"
中的所有资源恢复到新的 "beta"
命名空间。此示例需要两条转换规则,一条用于命名空间本身,一条用于命名空间内的资源。
YAML
transformationRules:
- description: Rename namespace name from alpha to beta
resourceFilter:
namespaces: []
jsonPath: ".metadata[?(@.name == 'alpha')]"
groupKinds:
- resourceGroup: ""
resourceKind: Namespace
fieldActions:
- op: REPLACE
path: "/metadata/name"
value: "beta"
- description: Clone all resources from namespace alpha to beta
resourceFilter:
namespaces: ["alpha"]
fieldActions:
- op: REPLACE
path: "/metadata/namespace"
value: "beta"
Terraform
transformation_rules {
description = "Rename namespace name from alpha to beta"
resource_filter {
json_path = ".metadata[?(@.name == 'alpha')]"
group_kinds {
resource_kind = "Namespace"
}
}
field_actions {
op = "REPLACE"
path = "/metadata/name"
value = "beta"
}
}
transformation_rules {
description = "Clone all resources from namespace alpha to beta"
resource_filter {
namespaces = ["alpha"]
}
field_actions {
op = "REPLACE"
path = "/metadata/namespace"
value = "beta"
}
}
更改克隆的命名空间中的 PVC StorageClass 和副本数量
此示例会克隆命名空间,然后对新命名空间中的资源应用一组更改:
将 PVC 上的 StorageClass 从
standard
更改为premium-rwo
将 Deployment
nginx
的副本计数更改为3
YAML
transformationRules:
- description: Rename the namespace from alpha to beta
resourceFilter:
namespaces: []
jsonPath: ".metadata[?(@.name == 'alpha')]"
groupKinds:
- resourceGroup: ""
resourceKind: Namespace
fieldActions:
- op: REPLACE
path: "/metadata/name"
value: "beta"
- description: Change all resources from namespace alpha to beta
resourceFilter:
namespaces: ["alpha"]
fieldActions:
- op: REPLACE
path: "/metadata/namespace"
value: "beta"
- description: Change the StorageClass on PVCs from standard to premium-rwo
resourceFilter:
namespaces: ["beta"]
jsonPath: ".spec[?(@.storageClassName == 'standard')]"
groupKinds:
- resourceGroup: ""
resourceKind: PersistentVolumeClaim
fieldActions:
- op: REPLACE
path: "/spec/storageClassName"
value: "premium-rwo"
- description: Change the replica count of the Deployment nginx from 7 to 3
resourceFilter:
namespaces: ["beta"]
jsonPath: ".metadata[?(@.name == 'nginx')]"
groupKinds:
- resourceGroup: apps
resourceKind: Deployment
fieldActions:
- op: REPLACE
path: "/spec/replicas"
value: "3"
Terraform
transformation_rules {
description = "Rename the namespace from alpha to beta"
resource_filter {
json_path = ".metadata[?(@.name == 'alpha')]"
group_kinds {
resource_kind = "Namespace"
}
}
field_actions {
op = "REPLACE"
path = "/metadata/name"
value = "beta"
}
}
transformation_rules {
description = "Change all resources from namespace alpha to beta"
resource_filter {
namespaces = ["alpha"]
}
field_actions {
op = "REPLACE"
path = "/metadata/namespace"
value = "beta"
}
}
transformation_rules {
description = "Change the StorageClass on PVCs from standard to premium-rwo"
resource_filter {
namespaces = ["beta"]
json_path = ".spec[?(@.storageClassName == 'standard')]"
group_kinds {
resource_kind = "PersistentVolumeClaim"
}
}
field_actions {
op = "REPLACE"
path = "/spec/storageClassName"
value = "premium-rwo"
}
}
transformation_rules {
description = "Change the replica count of the Deployment nginx from 7 to 3"
resource_filter {
namespaces = ["beta"]
json_path = ".metadata[?(@.name == 'nginx')]"
group_kinds {
resource_group = "apps"
resource_kind = "Deployment"
}
}
field_actions {
op = "REPLACE"
path = "/spec/replicas"
value = "3"
}
}
更改、插入和移除 ConfigMap 条目
此示例将命名空间 "mysql"
中包含标签键 "app.kubernetes.io/name"
的 ConfigMap
修改为:
将条目
"endpoint"
的值更改为"192.0.2.127"
。插入值为
"30s"
的新条目"connection-timeout"
。移除键为
"read-timeout"
的条目。
YAML
transformationRules:
- description: Change, insert, remove `ConfigMap` entres
resourceFilter:
namespaces: ["mysql"]
jsonPath: ".metadata.labels['app\\.kubernetes\\.io/name']"
groupKinds:
- resourceGroup: ""
resourceKind: ConfigMap
fieldActions:
- op: REPLACE
path: "/data/endpoint"
value: "192.0.2.127"
- op: ADD
path: "/data/connection-timeout"
value: "30s"
- op: REMOVE
path: "/data/read-timeout"
Terraform
transformation_rules {
description = "Change, insert, remove `ConfigMap` entres"
resource_filter {
namespaces = ["mysql"]
json_path = ".metadata.labels['app\\.kubernetes\\.io/name']"
group_kinds {
resource_kind = "ConfigMap"
}
}
field_actions {
op = "REPLACE"
path = "/data/endpoint"
value = "192.0.2.127"
}
field_actions {
op = "ADD"
path = "/data/connection-timeout"
value = "30s"
}
field_actions {
op = "REMOVE"
path = "/data/read-timeout"
}
}
为名称以 mysql- 开头的资源添加标签 app.kubernetes.io/name
。
此示例将值为 mysql
的标签 app.kubernetes.io/name
添加到名称以 mysql- 开头的所有资源:
YAML
transformationRules:
- description: Add a label to resources whose name starts with
resourceFilter:
namespaces: []
jsonPath: ".metadata[?(@.name =~ /^mysql-.*/i)]"
fieldActions:
- op: ADD
path: "/metadata/labels/app.kubernetes.io~1name"
value: "mysql"
Terraform
transformation_rules {
description = "Add a label to resources whose name starts with"
resource_filter {
json_path = ".metadata[?(@.name =~ /^mysql-.*/i)]"
}
field_actions {
op = "ADD"
path = "/metadata/labels/app.kubernetes.io~1name"
value = "mysql"
}
}
为 LoadBalancer 类型 Service 分配静态 IP 地址
此示例为命名空间 "nginx"
中的 Service "nginx-svc"
分配静态 IP 地址:
YAML
transformationRules:
- description: Assign a static IP to Service nginx-svc
resourceFilter:
namespaces: ["nginx"]
jsonPath: ".metadata[?(@.name == 'nginx-svc')]"
groupKinds:
- resourceGroup: ""
resourceKind: Service
fieldActions:
- op: ADD
path: "/spec/loadBalancerIP"
value: "192.0.2.127"
Terraform
transformation_rules {
description = "Assign a static IP to Service nginx-svc"
resource_filter {
namespaces = ["nginx"]
json_path = ".metadata[?(@.name == 'nginx-svc')]"
group_kinds {
resource_kind = "Service"
}
}
field_actions {
op = "ADD"
path = "/spec/loadBalancerIP"
value = "192.0.2.127"
}
}