Kubernetes Upgrade and Rollback

当集群中的某个服务需要升级时,需要停止目前与该服务相关的所有 Pod,然后下载新版本镜像并创建新的 Pod。如果集群规模较大,则这个工作就变成了一个挑战,而且先全部停止然后逐步升级的方式会导致较长时间的服务不可用。Kubernetes 提供了滚动升级功能来解决上述问题。

如果 Pod 是通过 Deployment 创建的,则用户可以在运行时修改 Deployment 的 Pod 定义(spec.template)或镜像名称,并应用到 Deployment 对象上,系统即可完成 Deployment 的自动更新操作。如果在更新过程中发生了错误,则还可以通过回滚(Rollback)操作恢复 Pod 的版本。

nginx-deployment.yaml

apiVersion: apps/v1beta1

kind: Deployment

metadata:

  name: nginx-deployment

spec:

  replicas: 3

  template:

    metadata:

      labels:

        app: nginx

    spec:

      containers:

      - name: nginx

        image: nginx:1.7.9

        ports:

        - containerPort: 80

启动服务:

$ kubectl apply -f nginx-deployment.yaml

deployment "nginx-deployment" created

查看启动的 Pod 副本数量:

$ kubectl get po

NAME                                READY     STATUS        RESTARTS   AGE

nginx-deployment-569477d6d8-k96gw   1/1       Running       0          36s

nginx-deployment-569477d6d8-mdqfl   1/1       Running       0          36s

nginx-deployment-569477d6d8-txrkh   1/1       Running       0          36s

现在 Pod 镜像需要更新 Nginx 为 1.9.1 版本,可以同 kubectl set image 命令为 Deployment 设置新的镜像名称:

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

deployment "nginx-deployment" image updated

另一种更新的方法是使用 kubectl edit 命令修改 Deployment 的配置,将 spec.template.spec.containers[0].image 从 Nginx:1.7.9 修改为 Nginx:1.10.0,然后执行:

$ kubectl edit deployment/nginx-deployment

...

    spec:

      containers:

      - image: nginx:1.10.0

        imagePullPolicy: IfNotPresent

        name: nginx

        ports:

...

deployment "nginx-deployment" edited

一旦镜像名称(或 Pod 定义)发生了修改,则将处罚系统完成 Deployment 所有运行 Pod 的滚动升级。可以使用:

$ kubectl rollout status

命令查看 Deployment 的更新过程:(这里需要在执行 edit 时直接执行,否则如果更新速度过快是看不到结果的)

$ kubectl rollout status deployment/nginx-deployment

Waiting for rollout to finish: 1 out of 3 new replicas have been updated...

Waiting for rollout to finish: 1 out of 3 new replicas have been updated...

Waiting for rollout to finish: 1 out of 3 new replicas have been updated...

Waiting for rollout to finish: 2 out of 3 new replicas have been updated...

Waiting for rollout to finish: 1 old replicas are pending termination...

Waiting for rollout to finish: 1 old replicas are pending termination...

Waiting for rollout to finish: 1 old replicas are pending termination...

deployment "nginx-deployment" successfully rolled out

查看当前运行的 Pod,名称已经更新了:

$ kubectl get po

NAME                                READY     STATUS    RESTARTS   AGE

nginx-deployment-766c4b567f-6x6nl   1/1       Running   0          1m

nginx-deployment-766c4b567f-74wpl   1/1       Running   0          1m

nginx-deployment-766c4b567f-kx94b   1/1       Running   0          1m

查看 Pod 使用的镜像,已经更新为 Nginx:1.10.0 了:

$ kubectl describe po nginx-deployment-766c4b567f-74wpl

...

  nginx:

    Container ID:   docker://51da517b3fccd4276c78f6eee4ab6aa2d393064066dcde1ebc5d02e64b675579

    Image:          nginx:1.10.0

    Image ID:       docker-pullable://nginx@sha256:7224f0a40f2110889889f47dcafa972a8658b7bdd3b50cfa12fd5f80364cbcfe

    Port:           80/TCP

...

它是如何完成 Pod 更新的呢?

可以使用:

$ kubectl describe deployment/nginx-deployment

执行结果 展开源码

命令自行观察 Deployment 的更新过程。初始创建 Deployment 时,系统创建了一个 ReplicaSet(nginx-deployment-569477d6d8),并按用户的需求创建了 3 个 Pod 副本。当更新 Deployment 时,系统创建了一个新的 ReplicaSet(nginx-deployment-6bd4859cdb),并将其副本扩展到 1 ,然后将旧的 ReplicaSet 缩减为 2。之后,系统继续按照相同的更新策略对新旧两个 ReplicaSet 进行逐个调整。最后,新的 ReplicaSet 运行了 3 个新版本 Pod 副本,旧的 ReplicaSet 副本数则缩减为 0。(倒数第二行中的 nginx-deployment-766c4b567f 是我们只想 edit 时的滚动升级而 nginx-deployment-6bd4859cdb 是我们只想 set 时的滚动升级 nginx-deployment-569477d6d8 是执行 kubectl apply 创建的版本,这里围绕着执行 set 操作讲述的说明,而 edit 滚动升级的过程与上述一致。)如图所示:

运行 rs 命令,查看两个 ReplicaSet 的最终状态:(结果为执行 edit 滚动升级的结果)

$ kubectl get rs

NAME                          DESIRED   CURRENT   READY     AGE

nginx-deployment-569477d6d8   0         0         0         28m

nginx-deployment-6bd4859cdb   0         0         0         26m

nginx-deployment-766c4b567f   3         3         3         17m

在整个升级的过程中,系统会至少保证有两个 Pod 可用,并且最多同时运行 4 个 Pod,这是 Deployment 通过复杂的算法完成的。Deployment 需要保证在整个更新过程中只有一定数量的 Pod 可能处于不可用状态,在默认情况下,Deployment 确保可用的 Pod 总数至少为所需的副本的数量(DESIRED)减 1,也就是最多 1 个不可用(maxUnavailable=1)。Deployment 还需要确保在整个更新过程中 Pod 的总数量不会超过所需的副本数太多,在默认情况下,Deployment 确保 Pod 的总数最多比所需的 Pod 数多 1 个,也就是最多 1 个浪涌值(maxSurge=1)。Kubernetes 从 v1.6 版本开始,maxUnavailable 和 maxSurge 的默认值将从 1、1 更新为所需副本数的 25%、25%。

这样,在升级过程中,Deployment 就能够保证服务不中断,并且副本数量始终维持为用户指定的数量(DESIRED)。

在 Deployment 的定义中,可以通过 spec.strategy 指定 Pod 更新的策略,目前支持两种策略:RollingUpdate(滚动更新)和 Recreate(重建),默认值为 RollingUpdate。在前面的例子中使用的就是 RollingUpdate 策略。

  • Recreate(重建):设置 spec.strategy.type=Recreate,表示 Deployment 在更新 Pod 时,会先杀掉所有正在运行的 Pod,然后创建新的 Pod。
  • RollingUpdate(滚动更新):设置 spec.strategy.type=RollingUpdate,表示 Deployment 会以滚动更新的方式来逐个更新 Pod 。同时,可以通过设置 spec.strategy.rollingUpdate 下的两个参数(maxUnavailable 和 maxSurge)来控制滚动更新的过程。

RollingUpdate(滚动更新)时两个主要的参数的说明如下:

  • spec.strategy.rollingUpdate.maxUnavailable:用于指定 Deployment 在更新过程中不可用状态 Pod 数量的上线。该 maxUnavailable 的数值可以是绝对值或 Pod 期望的副本数的百分比(例如 10%)如果设置为百分比,那么系统会先以向下取整的方式计算出绝对值(整数)。而当另一个参数 maxSurge 设置为 0 时,maxUnavailbale 则必须设置为绝对数值大于 0 (从 Kubernetes v1.6 开始,maxUnavailable 的默认值从 1 改为 20%)。举例来说,当 maxUnavailable 设置为 30%,旧的 ReplicaSet 可以再滚动更新开始时立刻将副本数缩小到所需副本总数的 70%。一旦新的 Pod 创建并准备好,则旧的 ReplicaSet 会进一步缩容,新的 ReplicaSet 又继续扩容,整个过程中系统的任意时刻都可以确保可用状态的 Pod 总数至少占 Pod 期望副本总数的 70%。
  • spec.strategy.rollingUpdate.maxSurge:用于指定 Deployment 更新 Pod 过程中 Pod 总数超过 Pod 期望副本数部分的最大值。该 maxSurge 的数值可以是绝对值或 Pod 期望副本数的百分比。如果设置为百分比,那么系统会先按照向上取整的方式计算出绝对值(整数)。举例来说,当 maxSurge 值设置为 30% 时,新的 ReplicaSet 可以在滚动更新开始时立刻进行副本数扩容,只需要保证新旧 ReplicaSet 的 Pod 副本数之和不超过期望副本数的 130% 即可。一旦旧的 Pod 被杀掉,新的 ReplicaSet 会进一步扩容。整个过程中系统在任意时刻都能确保新旧 ReplicaSet 的 Pod 副本总数之和不超过所需副本数的 130%。

这里需要注意多重更新(Rollover)的情况。如果 Deploument 的上一次更新正在进行,此时用户再次发起 Deployment 的更新操作,那么 Deployment 会为每一次更新都创建一个 ReplicaSet,而每次新的 ReplicaSet 创建成功后,会逐个增加 Pod 副本数,同时将之前正在扩容的 ReplicaSet 停止扩容(更新),并将其加入旧版本 ReplicaSet 列表中,然后开始缩容至 0 的操作。

例如,假设我们创建一个 Deployment,这个 Deployment 开始创建 5 个 Nginx:1.7.9 Pod 副本,在这个创建 Pod 动作尚未完成时,我们又将 Deployment 进行更新,在副本数不变的情况下将 Pod 模板中的镜像修改为 Nginx:1.9.1,假设此时 Deployment 已经创建了 3 个 Nginx:1.7.9 的 Pod 副本,则 Deployment 会立刻杀掉已经创建的 3 个 Nginx:1.7.9 Pod,并开始创建 Nginx:1.9.1 Pod。Deployment 不会再等待 Nginx:1.7.9 的 Pod 创建到 5 个之后再进行更新操作。

还需要注意更新 Deployment 的标签选择器(Label selector)的情况。通常来说,不鼓励更新 Deployment 的标签选择器,因为这样会导致 Deployment 选择的 Pod 列表发生变化,也可能与其他控制器发生冲突。如果一定要更新标签选择器,那么请务必谨慎,确保不会出现其他问题。关于 Deployment 标签选择器的更新注意事项如下:

(1)添加选择器标签时,必须同步修改 Deployment 配置的 Pod 的标签,为 Pod 添加新的标签,否则 Deployment 的更新会报验证错误而失败。

添加标签选择器是无法向后兼容的,这意味着新的标签选择器不会匹配和使用旧选择器创建的 ReplicaSets 和 Pod,因此添加选择器将会导致所有旧版本的 ReplicaSets 和由旧 ReplicaSets 创建的 Pod 处于孤立状态(不会被系统自动删除,也不受新的 ReplicaSet 控制)。

(2)更新标签选择器,即更改选择器中标签的键或者值,也会产生与添加选择器标签类似的效果。

(3)删除标签选择器,即从 Deployment 的标签选择器中删除一个或者多个标签,该 Deployment 的 ReplicaSet 和 Pod 不会受到任何影响。但需要注意的是,被删除的标签仍会存在于现有的 Pod 和 ReplicaSets 上。

Deployment Rollback

有时(例如新的 Deployment 不稳定时)我们可能需要将 Deployment 回滚到旧版本。默认情况下,所有 Deployment 的发布历史记录都保留在系统中,以便于我们随时进行回滚(可以配置历史记录数量)。

假设我们在更新 Deployment 镜像时,将容器镜像名误设置成 Nginx:1.91(一个不存在的镜像):

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.91

deployment "nginx-deployment" image updated

则这时 Deployment 的部署过程会被卡住:

$ kubectl rollout status deployment nginx-deployment

Waiting for rollout to finish: 1 out of 3 new replicas have been updated...

由于执行过程卡主,所以需要执行 Ctrl-C 命令来终止这个查看命令:

查看 ReplicaSet,可以看到新建的 ReplicaSet(nginx-deployment-b6d78b976)

$ kubectl get rs

NAME                          DESIRED   CURRENT   READY     AGE

nginx-deployment-6bd4859cdb   3         3         3         9h

nginx-deployment-b6d78b976    1         1         0         2m

再查看创建的 Pod,会发现新的 ReplicaSet 创建的 1 个 Pod 卡在镜像拉取过程中:

$ kubectl get po

NAME                                READY     STATUS         RESTARTS   AGE

nginx-deployment-6bd4859cdb-d8p5f   1/1       Running        0          9h

nginx-deployment-6bd4859cdb-qzh54   1/1       Running        0          9h

nginx-deployment-6bd4859cdb-svbwk   1/1       Running        0          9h

nginx-deployment-b6d78b976-6hwwb    0/1       ErrImagePull   0          3m

为了解决上面的这个问题,我们需要回滚到之前稳定版本的 Deployment。

首先,用下面的命令查看这个 Deployment 部署的历史记录:

$ kubectl rollout history deployment/nginx-deployment

deployments "nginx-deployment"

REVISION  CHANGE-CAUSE

1         kubectl apply --filename=nginx-deployment.yaml --record=true

2         kubectl set image deployment/nginx-deployment nginx=nginx:1.91

注意,在创建 Deployment 时使用 --record 参数(如 --record=true),就可以在 CHANGE-CAUSE 列看到每个版本使用的命令了。另外,Deployment 的更新操作是在 Deployment 进行部署(Rollout)时被触发的,这意味着当且仅当 Deployment 的 Pod 模板(即 spec.template)被更改时才会创建新的修订版本,例如更新模板标签或容器镜像。其他更新操作(如扩展副本数)将不会触发 Deployment 的更新操作,这也意味着我们将 Deployment 回滚到之前的版本时,只有 Deployment 的 Pod 模板部分会被修改。

如果需要查看特定版本的详细信息,则可以加上 --revision=<N> 参数:

$ kubectl rollout history deployment/nginx-deployment --revision=2

deployments "nginx-deployment" with revision #2

Pod Template:

  Labels:   app=nginx

    pod-template-hash=628346532

  Annotations:  kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.91

  Containers:

   nginx:

    Image:  nginx:1.91

    Port:   80/TCP

    Environment:    <none>

    Mounts: <none>

  Volumes:  <none>

现在我们觉得撤销本次发布并回滚到上一个部署版本:

$ kubectl rollout undo deployment/nginx-deployment

deployment "nginx-deployment" rolled back

当然,也可以使用 --to-revision 参数指定回滚到部署版本号:

$ kubectl rollout undo deployment/nginx-deployment --to-revision=2

这样,该 Deployment 就回滚到之前的文档版本了,可以从 Deployment 的事情信息中查看回滚到版本 2 的操作过程:

$ kubectl describe deployment/nginx-deployment

Name:                   nginx-deployment

Namespace:              default

CreationTimestamp:      Fri, 08 Dec 2017 13:18:29 +0000

Labels:                 app=nginx

Annotations:            deployment.kubernetes.io/revision=3

                        kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"apps/v1beta1","kind":"Deployment","metadata":{"annotations":{"kubernetes.io/change-cause":"kubectl apply --filename=nginx-deployment.yam...

                        kubernetes.io/change-cause=kubectl apply --filename=nginx-deployment.yaml --record=true

Selector:               app=nginx

Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable

StrategyType:           RollingUpdate

MinReadySeconds:        0

RollingUpdateStrategy:  25% max unavailable, 25% max surge

Pod Template:

  Labels:  app=nginx

  Containers:

   nginx:

    Image:        nginx:1.9.1

    Port:         80/TCP

    Environment:  <none>

    Mounts:       <none>

  Volumes:        <none>

Conditions:

  Type           Status  Reason

  ----           ------  ------

  Available      True    MinimumReplicasAvailable

  Progressing    True    NewReplicaSetAvailable

OldReplicaSets:  <none>

NewReplicaSet:   nginx-deployment-6bd4859cdb (3/3 replicas created)

Events:

  Type    Reason              Age   From                   Message

  ----    ------              ----  ----                   -------

  Normal  ScalingReplicaSet   4m    deployment-controller  Scaled up replica set nginx-deployment-6bd4859cdb to 3

  Normal  ScalingReplicaSet   3m    deployment-controller  Scaled up replica set nginx-deployment-b6d78b976 to 1

  Normal  DeploymentRollback  2m    deployment-controller  Rolled back deployment "nginx-deployment" to revision 1

  Normal  ScalingReplicaSet   2m    deployment-controller  Scaled down replica set nginx-deployment-b6d78b976 to 0

Suspension and Recovery

对于一次复杂的 Deployment 配置修改,为了避免频繁触发 Deployment 的更新操作,可以先暂停 Deployment 的更新操作,然后进行配置修改,再恢复 Deployment,一次性触发完整的更新操作,就可以避免不必要的 Deployment 更新操作了。

以之前创建的 Nginx 为例:

$ kubectl delete -f nginx-deployment.yaml

$ kubectl apply -f nginx-deployment.yaml --record=true

通过下面的命令暂停 Deployment 的更新操作:

$ kubectl rollout pause deployment/nginx-deployment

deployment "nginx-deployment" paused

然后修改 Deployment 的镜像信息:

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

查看 Deployment 的历史记录,发现并没有触发新的 Deployment 的部署操作:

$ kubectl rollout history deployment/nginx-deployment

deployments "nginx-deployment"

REVISION  CHANGE-CAUSE

1         kubectl apply --filename=nginx-deployment.yaml --record=true

在暂停 Deployment 部署之后,可以根据需要进行任意次数的配置更新。例如,再次更新容器的资源限制:

$ kubectl set resources deployment nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi

deployment "nginx-deployment" resource requirements updated

然后,恢复这个 Deployment 的部署操作:

$ kubectl rollout resume deploy nginx-deployment

deployment "nginx-deployment" resumed

可以看到一个新的 ReplicaSet 被创建出来了:

$ kubectl get rs

NAME                          DESIRED   CURRENT   READY     AGE

nginx-deployment-678d7799d    1         1         0         18s

nginx-deployment-6bd4859cdb   3         3         3         3m

查看 Deployment 的事件信息,可以看到 Deployment 完成了更新:

$ kubectl describe deployment/nginx-deployment

Rolling Update

对于 RC 的滚动升级,Kubernetes 还提供了一个 rolling-update 命令进行实现。该命令创建了一个新的 RC,然后自动控制旧的 RC 中的 Pod 副本的数量逐渐减少到 0,同时新的 RC 中的 Pod 副本的数量从 0 逐步增加到目标值,来完成 Pod 的升级。需要注意的是,系统要求新的 RC 需要与旧的 RC 在相同的命名空间内,既不能把别人的资产统统的转移到自家明细。

以 redis-master 为例,假设当前运行的 redis-master Pod 是 1.0 版本,现在需要升级到 2.0 版本。配置文件:

redis-master-controller-v1.yaml 展开源码

启动 v1 版:

$ kubectl apply -f redis-master-controller-v1.yaml

v2 的配置如下:

redis-master-controller-v2.yaml 展开源码

运行 rolling-update 命令完成 Pod 的滚动升级:

$ kubectl rolling-update redis-master -f redis-master-controller-v2.yaml

Created redis-master-v2

Scaling up redis-master-v2 from 0 to 1, scaling down redis-master from 1 to 0 (keep 1 pods available, don't exceed 2 pods)

Scaling redis-master-v2 up to 1

Scaling redis-master down to 0

Update succeeded. Deleting redis-master

replicationcontroller "redis-master" rolling updated to "redis-master-v2"

等所有新的 Pod 启动完成后,旧的 Pod 也被完全销毁,这样就完成了容器集群的更新工作。

另一种方法是不是有配置文件,直接用命令操作,加上 --image 参数指定新版镜像名称来完成 Pod 的滚动升级:

$ kubectl rolling-update redis-master-v2 --image=redis:3 --image-pull-policy=Always

Created redis-master-v2-a39d43ef3eea2cdb6161cfa7cea99bc3

Scaling up redis-master-v2-a39d43ef3eea2cdb6161cfa7cea99bc3 from 0 to 1, scaling down redis-master-v2 from 1 to 0 (keep 1 pods available, don't exceed 2 pods)

Scaling redis-master-v2-a39d43ef3eea2cdb6161cfa7cea99bc3 up to 1

Scaling redis-master-v2 down to 0

Update succeeded. Deleting old controller: redis-master-v2

Renaming redis-master-v2-a39d43ef3eea2cdb6161cfa7cea99bc3 to redis-master-v2

replicationcontroller "redis-master-v2" rolling updated

可以看到,kubernetes 通过创建新版本 Pod ,停掉一个旧版本 Pod,逐步迭代来完成整个 RC 更新。

$ kubectl get rc -o wide

NAME              DESIRED   CURRENT   READY     AGE       CONTAINERS   IMAGES    SELECTOR

redis-master-v2   1         1         1         1m        master       redis:3   deployment=a39d43ef3eea2cdb6161cfa7cea99bc3,name=redis-master,version=v2

可以看到,kubeclt 给 RC 增加了一个 key 为 “deployment” 的 Label (这个 Key 的名字可以通过 --deployment-label-key 参数进行修改),Label 的值是 RC 的内容进行 Hash 计算后的值,相当于签名,这样就能很方便的比较 RC 里的 Image 名字以及其他信息是否发生了变化。

如果咋在如果在更新过程中发现配置有误,则可以终端更新操作,并通过执行下面命令完成 Pod 的回滚:

$ kubectl rolling-update redis-master-v2 --rollback

其他管理对象的更新策略

Kubernetes 从 v1.6 版本开始,对 DaemonSet 和 StatfulSet 的更新策略也开始引入类似于 Deployment 的滚动升级,通过不同的策略,自动完成应用的版本升级。

(1)DaemonSet 的更新策略

目前 DaemonSet 的升级策略包括两种:OnDelete 和 RollingUpdate

  • OnDelete:DaemonSet 的默认升级策略,与 v1.5 及之前版本的 Kubernetes 保持一致。当使用 OnDelete 作为升级策略时,在创建好新的 DaemonSet 配置后,新的 Pod 并不会被自动创建,直到用户手动删除旧版本的 Pod,才出发新建操作。
  • PollingUpdate:从 Kubernetes v1.6 版本开始引入。当使用 RollingUpdate 作为升级策略对 DaemonSet 进行更新时,旧版本的 Pod 将被自动杀掉,然后自动创建新版本的 DaemonSet Pod,整个过程与普通 Deployment 的滚动升级一样是可控的。不过有两点不同于普通 Pod 的滚动升级,一是目前 Kubernetes 还不支持查看和管理 DaemonSet 的更新历史记录;二是 DaemonSet 的回滚(Rollback)并不能如同 Deployment 一样直接通过命令来实现,而是必须通过再次提交旧版本配置的方式实现。

(2)StatefulSet 的更新策略

Kubernetes 从 v1.6 版本开始,针对 StatefulSet 的更新策略正逐渐向 Deployment 和 DaemonSet 的更新策略看起,也将实现 RollingUpdate、Paritioned 和 OnDelete 集中策略,目前是保证 StatefulSet 中各 Pod 有序地、逐个地更新,并且能够保留更新历史,也能回滚到某个历史版本。

回滚策略

模板如下:

apiVersion: apps/v1

kind: Deployment

metadata:

  name: uc-web-test

  namespace: tahoe-test

spec:

  replicas: 1

  minReadySeconds: 60       # 滚动升级时,当 Pod 启动 60 秒后则判断该 Pod 已经成功启动

  strategy:

    type: RollingUpdate     # 使用回滚升级策略,默认

    rollingUpdate:

      maxSurge: 1           # 最大滚动升级的 Pod 数量

      maxUnavailable: 1     # 当 Pod 升级时最大允许的 Unavailable 的数量

  selector:

    matchLabels:

      app: uc-web-test

      version: v1.0

  template:

    metadata:

      name: uc-web-test

      labels:

        app: uc-web-test

        version: v1.0

    spec:

      containers:

      - name: uc-web-test

        image: k8s.harbor/uc/web:v1.0.17

        ports:

        - name: http

          containerPort: 8088

        livenessProbe:

          tcpSocket:

            port: 8088

          initialDelaySeconds: 30

          timeoutSeconds: 10

        readinessProbe:

          tcpSocket:

            port: 8088

          initialDelaySeconds: 30

          timeoutSeconds: 10

      imagePullSecrets:

      - name: harbor-registry

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值