本页面介绍如何在恢复过程中使用转换规则修改 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 控制台中的映射中的键时,需要使用 \
(反斜杠)对 .
(点)进行转义。如果 JSONPath 是在 YAML 上下文中通过 gcloud CLI 或 Terraform 语言提供的,则需要使用 \\
(双反斜杠)。例如,.metadata.labels['app\.kubernetes\.io/name']
等效于 YAML 或 Terraform 中的 .metadata.labels['app\\.kubernetes\\.io/name']
。
我们建议使用支持正则表达式的 JSONPath 评估器工具在使用前测试表达式。您还可以使用 kubectl
验证 JSONPath 表达式的结果。如需查看更多示例,请参阅 JSONPath 支持。
现场活动 (fieldActions
)
字段操作基于 JSON Patch 进行建模,该规范定义了一个 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 元素。
以下操作会向 nginx
容器添加一个值为 "80"
的新环境变量 "PORT"
。
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
以下操作会向 Pod 的新标签 app.kubernetes.io/name: nginx
添加值。
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
替换
value
对于 replace
操作是必需的,并且必须是 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 定义转换规则,请创建一个包含 transformationRules
的 YAML 数组的文件,并将 --transformation-rules-file=
参数添加到 gcloud beta container backup-restore restore-plans create
命令。
转换规则示例
以下示例以 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
将部署
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-mysql- 开头的资源添加标签 app.kubernetes.io/name
。
此示例将值为 mysql
的标签 app.kubernetes.io/name
添加到名称以 mysql-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 类型的服务分配静态 IP 地址
以下示例为命名空间 "nginx"
中的服务 "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"
}
}