resourceVersion和Generation之间有什么区别?

Lai*_*son 4 kubernetes

在Kubernetes对象元数据,存在的概念resourceVersiongeneration.我理解它的概念resourceVersion:它是一种乐观的并发控制机制 - 它会随着每次更新而改变.那么,是generation为了什么?

Jor*_*itt 11

resourceVersion在每次写入时都会更改,并用于乐观并发控制

在某些对象中,生成由服务器递增,作为持久写入影响spec对象的一部分.

某些对象的status字段有一个observedGeneration子域,供控制器持久保存上次执行的生成.

  • 不,这是控制器认识到规范中没有任何需要做出反应的更改的简单方法。如果没有它,控制器必须跟踪它最后执行的规范是什么样的(在内存中,在重新启动时失败,或者在某个地方持久存在,当添加新的默认字段时失败)。使用它,控制器读取对象,将生成与持久的 status.observedGeneration 进行比较,如果它们不同,则根据规范进行操作,并将结果记录在新观察到的生成的状态中。 (5认同)
  • 谢谢; 我可以请您详细说明一下第二句话吗?这是否像“检查点”(即“检查点”)一样,即控制器为了实现传入资源请求的状态,可能必须将其分为两个部分?例如,“好,我已经完成了第1阶段,但是我还没有真正完全改变`spec`”? (2认同)

Sta*_*lfi 11

在上下文中Deployment

简而言之

resourceVersion是 k8s 资源的版本,而generation是部署的版本,您可以使用kubectlcli 来撤消、暂停等操作。

源代码kubectl rollout: https: //github.com/kubernetes/kubectl/blob/master/pkg/cmd/rollout/rollout.go#L50

长版

资源版本

K8s 服务器保存对任何 k8s 资源的所有修改。每个修改都有一个称为 的版本resourceVersion

k8s 语言库提供了一种实时接收ADD任何资源事件DELETE的方法。MODIFY您也有BOOKMARK事件,但我们先把它放在一边。

在任何修改操作中,您都会收到带有更新的resourceVersion. 您可以使用它resourceVersion并从此开始启动监视resourceVersion,这样您就不会错过 k8s 服务器向您发送回第一个响应的时间之间的任何事件,直到监视启动为止。

  • K8s 不会永远保留每个资源的历史记录。我认为它会节省 5m,但我不确定。

resourceVersion对对象进行任何修改后都会发生变化。

它存在的原因是为了避免多个客户端尝试修改同一 k8s 资源的并发问题。这种模式在数据库中也很常见,您可以找到有关它的更多信息:


观察一代

您没有在问题中谈论它,但这是我们在继续讨论之前需要澄清的重要信息generation

它是此部署当前正在跟踪的副本集的版本。

当部署仍在第一次创建时,该值将不存在(可以在此处找到对此的良好讨论: https: //github.com/kubernetes/kubernetes/issues/47871)。

该值可以在以下位置找到status

....
apiVersion: apps/v1
kind: Deployment
.....
status:
  availableReplicas: 1
  conditions:
  - lastTransitionTime: "2021-02-07T19:04:17Z"
    lastUpdateTime: "2021-02-07T19:04:17Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  - lastTransitionTime: "2021-02-07T19:04:15Z"
    lastUpdateTime: "2021-02-07T19:17:09Z"
    message: ReplicaSet "deployment-bcb437a4-59bb9f6f69" has successfully progressed.
    reason: NewReplicaSetAvailable
    status: "True"
    type: Progressing
  observedGeneration: 3.    <<<--------------------
  readyReplicas: 1
  replicas: 1
  updatedReplicas: 1
Run Code Online (Sandbox Code Playgroud)

observedGeneration 等于deployment.kubernetes.io/revision 注释。这是被观察的一代。

它看起来是正确的,因为deployment.kubernetes.io/revision在首次创建部署且尚未准备就绪时不存在,并且它与observedGeneration更新部署时具有相同的值。


一代

它表示此部署应跟踪的“新”副本集的版本。

当第一次创建部署时,该值将等于 1。当将observedGeneration设置为1时,表示复制集已准备就绪(这个问题不是关于如何知道部署是否成功(或不)所以我不会讨论什么是“准备好”,这是我为此答案创建的一些术语 - 但请确保还有其他条件来检查部署是否成功)。

部署 k8s 资源中的任何更改都会触发重新部署,这也是如此。valuegeneration会加 1,然后需要一段时间才能observedGeneration等于generationvalue。

observedGeneration有关源代码generation的更多信息kuebctl rollout status(检查部署是否“完成”) :kubectl

https://github.com/kubernetes/kubectl/blob/a2d36ec6d62f756e72fb3a5f49ed0f720ad0fe83/pkg/polymorphichelpers/rollout_status.go#L75

if deployment.Generation <= deployment.Status.ObservedGeneration {
        cond := deploymentutil.GetDeploymentCondition(deployment.Status, appsv1.DeploymentProgressing)
        if cond != nil && cond.Reason == deploymentutil.TimedOutReason {
            return "", false, fmt.Errorf("deployment %q exceeded its progress deadline", deployment.Name)
        }
        if deployment.Spec.Replicas != nil && deployment.Status.UpdatedReplicas < *deployment.Spec.Replicas {
            return fmt.Sprintf("Waiting for deployment %q rollout to finish: %d out of %d new replicas have been updated...\n", deployment.Name, deployment.Status.UpdatedReplicas, *deployment.Spec.Replicas), false, nil
        }
        if deployment.Status.Replicas > deployment.Status.UpdatedReplicas {
            return fmt.Sprintf("Waiting for deployment %q rollout to finish: %d old replicas are pending termination...\n", deployment.Name, deployment.Status.Replicas-deployment.Status.UpdatedReplicas), false, nil
        }
        if deployment.Status.AvailableReplicas < deployment.Status.UpdatedReplicas {
            return fmt.Sprintf("Waiting for deployment %q rollout to finish: %d of %d updated replicas are available...\n", deployment.Name, deployment.Status.AvailableReplicas, deployment.Status.UpdatedReplicas), false, nil
        }
        return fmt.Sprintf("deployment %q successfully rolled out\n", deployment.Name), true, nil
    }
    return fmt.Sprintf("Waiting for deployment spec update to be observed...\n"), false, nil
Run Code Online (Sandbox Code Playgroud)

我必须说我不确定 a 何时observedGeneration可以高于generation。也许人们可以在评论中帮助我。


总而言之:这篇精彩文章的插图:https ://thenewstack.io/kubernetes-deployments-work/ 在此输入图像描述

更多信息: