You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于ReplicaSet与StatefulSet的CreationTimestamp(AGE)变更场景及资源最近更新验证方法的技术问询

Understanding ReplicaSet/StatefulSet AGE and Detecting Recent Updates

First: What Changes the CreationTimestamp (AGE) of ReplicaSets and StatefulSets?

The CreationTimestamp field is set only once when the resource is first created. No subsequent modifications to the resource (whether to its spec, metadata, or status) will update this value. Here's how this plays out for each resource:

  • ReplicaSets:

    • A new ReplicaSet gets a fresh CreationTimestamp only when a Deployment triggers a rollout (e.g., changing container images, resource limits, pod template labels, or any other field that requires a new pod template).
    • When you roll back to an older Deployment revision, Kubernetes reuses the existing old ReplicaSet (setting its DESIRED replicas back to the target count) instead of creating a new one. That's why the old ReplicaSet's AGE stays the same.
    • Modifying an existing ReplicaSet directly (e.g., scaling it manually) won't change its CreationTimestamp.
  • StatefulSets:

    • Unlike Deployments, StatefulSets don't create multiple versions of themselves. All updates are applied directly to the existing StatefulSet resource.
    • This means the CreationTimestamp of a StatefulSet will never change unless you delete the StatefulSet and recreate it from scratch. Even rolling updates or template changes won't update this field.

Second: Best Ways to Verify Recent Updates for Deployments, ReplicaSets, and StatefulSets

Checking CreationTimestamp (AGE) isn't reliable because it doesn't reflect in-place updates or rollbacks. Instead, use these fields and annotations:

For ReplicaSets:

  • metadata.annotations["deployment.kubernetes.io/revision"]: Tracks the Deployment's revision number this ReplicaSet belongs to. A higher revision number means a more recent update.
  • metadata.generation vs status.observedGeneration: Every time you modify the ReplicaSet's spec, metadata.generation increments. When the controller finishes processing the change, status.observedGeneration matches it. A recent gap or match can indicate a recent update.
  • spec.template.metadata.annotations["kubectl.kubernetes.io/restartedAt"]: Added automatically when you run kubectl rollout restart deployment—this timestamp tells you when the pods were last restarted.
  • Check if the ReplicaSet is the active one for its Deployment (match deployment.status.currentReplicaSetName to the ReplicaSet's name) and then inspect its status conditions.

For StatefulSets:

  • metadata.generation vs status.observedGeneration: Same logic as ReplicaSets—an increment in generation followed by observedGeneration catching up indicates a recent spec change.
  • status.currentRevision vs status.updateRevision: If these differ, the StatefulSet is in the middle of an update. When the update completes, they'll match.
  • spec.template.metadata.annotations["kubectl.kubernetes.io/restartedAt"]: Same as ReplicaSets—tracks manual restarts.
  • status.conditions: Look for conditions like StatefulSetUpdated or StatefulSetReady and check their LastTransitionTime to see when the last update finished.

For Deployments:

  • metadata.annotations["deployment.kubernetes.io/revision"]: Increments with every rollout/rollback.
  • status.updatedReplicas: Should match status.replicas when an update is complete.
  • status.conditions: The Available or Progressing conditions have LastTransitionTime fields that mark recent updates.

Revising Your client-go Code

Here's how to adjust your functions to detect recent updates more accurately, moving away from relying on CreationTimestamp:

Updated StatefulSet Check

import (
    "context"
    "errors"
    "fmt"
    "log"
    "time"

    "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    appsv1 "k8s.io/api/apps/v1"
)

func statefulsetCheck(namespace string, clientset *kubernetes.Clientset) bool {
    statefulsets, err := clientset.AppsV1().StatefulSets(namespace).List(context.TODO(), v1.ListOptions{})
    if errors.IsNotFound(err) {
        log.Fatal("\nNo statefulsets in the namespace", err)
    } else if err != nil {
        log.Fatal("\nFailed to fetch statefulsets in the namespace: ", err)
    }
    var stsNames []string
    for _, sts := range statefulsets.Items {
        stsNames = append(stsNames, sts.Name)
    }
    fmt.Printf("\nStatefulsets in the namespace: %v", stsNames)

    // Check for recent updates using conditions and restart annotations
    for _, sts := range statefulsets.Items {
        // Check if the StatefulSet was recently updated via spec changes
        for _, cond := range sts.Status.Conditions {
            if cond.Type == appsv1.StatefulSetUpdated {
                lastUpdate := cond.LastTransitionTime.Time
                if time.Since(lastUpdate).Minutes() < 5 {
                    fmt.Printf("\nStatefulset %v had recent spec updates. Skipping...", sts.Name)
                    return true
                }
            }
        }

        // Check if pods were recently restarted via kubectl rollout restart
        restartedAtStr := sts.Spec.Template.ObjectMeta.Annotations["kubectl.kubernetes.io/restartedAt"]
        if restartedAtStr != "" {
            restartedAt, err := time.Parse(time.RFC3339, restartedAtStr)
            if err == nil && time.Since(restartedAt).Minutes() < 5 {
                fmt.Printf("\nStatefulset %v was recently restarted. Skipping...", sts.Name)
                return true
            }
        }
    }
    return false
}

Updated ReplicaSet Check

func replicasetCheck(namespace string, clientset *kubernetes.Clientset) bool {
    replicasets, err := clientset.AppsV1().ReplicaSets(namespace).List(context.TODO(), v1.ListOptions{})
    if errors.IsNotFound(err) {
        log.Fatal("\nNo replicasets in the namespace", err)
    } else if err != nil {
        log.Fatal("\nFailed to fetch replicasets in the namespace: ", err)
    }
    var rpsNames []string
    for _, rps := range replicasets.Items {
        rpsNames = append(rpsNames, rps.Name)
    }
    fmt.Printf("\nReplicasets in the namespace: %v", rpsNames)

    for _, rps := range replicasets.Items {
        // Check if this is the active ReplicaSet for its Deployment (focus on relevant RS)
        deploymentName := rps.ObjectMeta.Annotations["deployment.kubernetes.io/name"]
        if deploymentName != "" {
            deployment, err := clientset.AppsV1().Deployments(namespace).Get(context.TODO(), deploymentName, v1.GetOptions{})
            if err == nil && deployment.Status.CurrentReplicaSetName == rps.Name {
                // Check recent update via Ready condition
                for _, cond := range rps.Status.Conditions {
                    if cond.Type == appsv1.ReplicaSetReady {
                        lastReadyTime := cond.LastTransitionTime.Time
                        if time.Since(lastReadyTime).Minutes() < 5 {
                            fmt.Printf("\nActive ReplicaSet %v (for Deployment %v) had recent updates...", rps.Name, deploymentName)
                            return true
                        }
                    }
                }
            }
        }

        // Check for recent pod restarts
        restartedAtStr := rps.Spec.Template.ObjectMeta.Annotations["kubectl.kubernetes.io/restartedAt"]
        if restartedAtStr != "" {
            restartedAt, err := time.Parse(time.RFC3339, restartedAtStr)
            if err == nil && time.Since(restartedAt).Minutes() < 5 {
                fmt.Printf("\nReplicaSet %v was recently restarted...", rps.Name)
                return true
            }
        }
    }
    return false
}

内容的提问来源于stack exchange,提问作者Kaio H. Cunha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 17:03:14