【问题标题】:Issue - Kubernetes Deployment with multiple active ReplicaSets问题 - 具有多个活动 ReplicaSet 的 Kubernetes 部署
【发布时间】:2022-03-10 07:29:51
【问题描述】:

我有一个 Kubernetes 部署,它是两个具有不同配置的 ACTIVE ReplicaSet 的 Owner/Parent。

此设置由 Helm 管理。

我尝试制作revisionHistory: 0。这不起作用,因为 ReplicaSet 不是非活动的。这个旧的 ReplicaSet 尝试启动一个 pod,但由于节点上的资源限制,它一直处于挂起状态。

我尝试更新 Deployment,但只更新了新的 ReplicaSet。旧的保持不变。

我也无法删除此 ReplicaSet。这给我带来了很多麻烦。

有人可以帮我解决这个问题吗?

Helm 部署模板 -

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: example
  replicas: 1
  template:
    metadata:
      labels:
        k8s-app: example
    spec:
      serviceAccountName: example
      nodeSelector:
        node-role: example-node
      containers:
      - name: example
        image: example-image:vX.X.X
        resources:
          requests:
            cpu: 100m
        ports:
        - name: example-port
          containerPort: XXXX
        - name: example-port-1
          containerPort: XXXX
        readinessProbe:
          httpGet:
            path: /example
            port: XXXX
          initialDelaySeconds: 5
          timeoutSeconds: 5
      - name: example-sidecar
        image: example-image-sidecar:vX.X.X
        resources:
          limits:
            memory: 400Mi
          requests:
            cpu: 100m
        env:
          - name: MY_POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: MY_POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
        command:
          - command
          - --container=example
          - --cpu=200m
          - --extra-cpu=10m
          - --memory=300Mi
          - --extra-memory=2Mi
          - --threshold=5
          - --deployment=example

堆栈:使用 Kops 和 Helm 2.13.1 部署在 AWS EC2 上的独立 K8

输出 -

kubectl get rs -o wide -n kube-system | grep example

NAME               DESIRED  CURRENT READY   AGE     CONTAINERS IMAGES SELECTOR
example-6d4f99bc54 0        0       0       12h     example,example-sidecar example-image:vX.X.X,example-image-sidecar:vX.X.X k8s-app=example,pod-template-hash=6d4f99bc54
example-59d46955b6 0        0       0       13h     example,example-sidecar example-image:vX.X.X,example-image-sidecar:vX.X.X k8s-app=example,pod-template-hash=59d46955b6
example-5855866cdb 0        0       0       18h     example,example-sidecar example-image:vX.X.X,example-image-sidecar:vX.X.X k8s-app=example,pod-template-hash=5855866cdb
example-ccc5cf5cd0 0        0       0       18h     example,example-sidecar example-image:vX.X.X,example-image-sidecar:vX.X.X k8s-app=example,pod-template-hash=ccc5cf5cd
example-66db79f578 1        1       0       19h     example,example-sidecar example-image:vX.X.X,example-image-sidecar:vX.X.X k8s-app=example,pod-template-hash=66db79f578
example-759469945f 1        1       1       19h     example,example-sidecar example-image:vX.X.X,example-image-sidecar:vX.X.X k8s-app=example,pod-template-hash=759469945f
example-ff8f986960 0        0       0       19h     example,example-sidecar example-image:vX.X.X,example-image-sidecar:vX.X.X k8s-app=example,pod-template-hash=ff8f98696

kubectl describe deployments example -n kube-system

Name:                   example
Namespace:              kube-system
CreationTimestamp:      Tue, 03 Mar 2020 00:48:18 +0530
Labels:                 k8s-app=example
Annotations:            deployment.kubernetes.io/revision: 27
Selector:               k8s-app=example
Replicas:               1 desired | 1 updated | 2 total | 1 available | 1 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:           k8s-app=example
  Service Account:  example
  Containers:
   example:
    Image:       example-image:vX.X.X
    Ports:       8080/TCP, 8081/TCP
    Host Ports:  0/TCP, 0/TCP
    Limits:
      cpu:     1630m
      memory:  586Mi
    Requests:
      cpu:        1630m
      memory:     586Mi
    Readiness:    http-get http://:8080/healthz delay=5s timeout=5s period=10s #success=1 #failure=3
    Environment:  <none>
    Mounts:       <none>
   example-sidecar:
    Image:      example-image-sidecar:vX.X.X
    Port:       <none>
    Host Port:  <none>
    Command:
      command
      --container=example
      --cpu=200m
      --extra-cpu=10m
      --memory=300Mi
      --extra-memory=2Mi
      --threshold=5
      --deployment=example
    Limits:
      memory:  400Mi
    Requests:
      cpu:  100m
    Environment:
      MY_POD_NAME:        (v1:metadata.name)
      MY_POD_NAMESPACE:   (v1:metadata.namespace)
    Mounts:              <none>
  Volumes:               <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
OldReplicaSets:  example-759469945f (1/1 replicas created)
NewReplicaSet:   example-66db79f578 (1/1 replicas created)
Events:          <none>
kubectl rollout history deployments example -n kube-system

deployment.extensions/example 
REVISION  CHANGE-CAUSE
1         <none>
16        <none>
17        <none>
21        <none>
24        <none>
26        <none>
27        <none>

【问题讨论】:

  • 当您尝试删除 ReplicaSet 时究竟会发生什么以及您尝试删除它的具体方式是什么?以及在kube-system命名空间中创建Deployment的原因是什么?
  • @Nick 当我删除 ReplicaSet 时,会立即启动一个具有相同名称/ID 的新副本。我使用kubectl -n kube-system delete rs example-rs-name。此外,该应用程序位于 kube-system 命名空间中,因为该应用程序与 kubernetes 管理相关而不与产品相关。我们在 K8s 中为产品应用程序提供了不同的命名空间。
  • 你使用的是 Helm 2 还是 Helm 3?
  • 另外,如果你已经通过 Helm 安装了那个 rs - 请尝试通过 helm 而不是通过 kubectl 删除它
  • @Nick 我正在使用 helm 2.13.1。我尝试删除整个 Helm Chart 并启动整个 Helm Chart。问题依然存在。

标签: kubernetes kubernetes-helm


【解决方案1】:

在您的情况下,明确指定部署update strategy 会有所帮助。
从您的部署描述中,我们可以看到您默认获得的选项:

StrategyType:           RollingUpdate
RollingUpdateStrategy:  25% max unavailable, 25% max surge

您可以使用以下命令查看完整的 YAML:
kubectl get deployment example -n kube-system -o yaml --export

注意kube-system 命名空间不是放置自定义部署的最佳位置。我建议使用使用 kubectl create ns namespace-namedefault 命名空间创建的自定义命名空间

有两种方法可以解决此问题。在创建新的 pod 之前,您应该强制部署摆脱旧的 pod:

方法之一。在这里我将更新类型设置为“重新创建”。更新后,Deployment 会立即杀死所有 pod,并启动具有相同数量副本的新版本 pod。即使副本数>1,服务也会出现一些停机时间。

strategy:
  type: Recreate

方式二:在下一个示例中,我将滚动更新选项设置为 maxSurge=0maxUnavailable=1 下一次更新后,Deployment 将首先杀死一个 pod,然后创建新版本的 pod 以保持总副本数等于规范中设置的数量。在新的 pod 准备就绪后,该过程将与下一个 pod 重复。如果您只有一个副本,则还需要一些停机时间。

strategy:
  rollingUpdate:
    maxSurge: 0
    maxUnavailable: 1
  type: RollingUpdate

更新类型说明:
k explain deployment.spec.strategy.type

Type of deployment. Can be "Recreate" or "RollingUpdate". Default is
 RollingUpdate.

选项说明:
kubectl explain deployment.spec.strategy.rollingUpdate

 maxSurge   <string>
   The maximum number of pods that can be scheduled above the desired number
   of pods. Value can be an absolute number (ex: 5) or a percentage of desired
   pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number
   is calculated from percentage by rounding up. By default, a value of 1 is
   used. Example: when this is set to 30%, the new RC can be scaled up
   immediately when the rolling update starts, such that the total number of
   old and new pods do not exceed 130% of desired pods. Once old pods have
   been killed, new RC can be scaled up further, ensuring that total number of
   pods running at any time during the update is at most 130% of desired pods.

 maxUnavailable <string>
   The maximum number of pods that can be unavailable during the update. Value
   can be an absolute number (ex: 5) or a percentage of desired pods (ex:
   10%). Absolute number is calculated from percentage by rounding down. This
   can not be 0 if MaxSurge is 0. By default, a fixed value of 1 is used.
   Example: when this is set to 30%, the old RC can be scaled down to 70% of
   desired pods immediately when the rolling update starts. Once new pods are
   ready, old RC can be scaled down further, followed by scaling up the new
   RC, ensuring that the total number of pods available at all times during
   the update is at least 70% of desired pods.

【讨论】:

  • 感谢您的回答。这也不行。我相信不知何故部署已损坏,无论我做什么,它都不会得到修复。到目前为止唯一有效的选择是让损坏的 ReplicaSet 运行它想要运行的 pod。在这种情况下,损坏的 ReplicaSet 优先,新的 ReplicaSet 被杀死。
  • 它不应该那样工作。我会检查节点上的 kubelet 日志( journalctl -u kubelet ),检查 pod 状态( kubectl get pods --all-namespaces ),检查处于 Pending 状态的 pod 的描述( kubectl describe pod pod_name ),以及失败的 pod ( kubectl logs pod_name [--previous] )。节点可用资源也将提供信息( kubectl top nodes ),( kubectl describe node node_name )。然后我建议在本地渲染 helm chart 并检查它是否存在重复的资源或不正确的设置(helm template ./chart_name > output.yaml)。
  • 什么是集群和kubectl版本? (kubectl 版本)
【解决方案2】:

我们在 Openshift 中遇到了类似的问题,即 2 个副本集属于同一部署。不幸的是,这个问题导致他们的 pod 大约每 100 秒频繁重启。这是因为 2 个副本使用不同的图像。 (我们经常升级镜像)

同一部署(Deployment/ua-operator)拥有 2 个副本集(ua-operator-776546f4ff、ua-operator-b6c858456)。我们可以看到 Pod 状态的“restartCount”参数始终为 0,但 Pod 只能存活 100 秒左右。它不是由应用程序问题引起的。它是 2 个副本集来执行滚动升级(但不是滚动升级)之类的操作。

查看 2 个副本集(ua-operator-776546f4ff、ua-operator-b6c858456),您可以看到它们不幸地使用了 2 个不同的图像。 replicasets / ua-operator-776546f4ff 正在使用 ua-operator:APM_202006202301 replicasets / ua-operator-b6c858456 正在使用 ua-operator:APM_202006212301

虽然部署 (Deployment/ua-operator) 仅指定较新的映像: 部署/ua-operator 正在使用 ua-operator:APM_202006212301

所以问题是: 有人创建了新的 Deployment/ua-operator 而没有完全删除旧的 Deployment/ua-operator,所以使用旧的 ua-operator:APM_202006202301 映像的旧副本集 / ua-operator-776546f4ff 没有被删除,现在仍然存在并且成为新的 Deployment/ua-operator 的子节点。不幸的是,这两个副本使用不同的图像。这就是总是重启 ua-operator pod 的原因。

我不确定这是 Kubernetes 还是 Openshift 缺陷。但是我们可以通过等待旧部署被完全删除然后创建新的 ua-operator 部署来避免它。

【讨论】:

    【解决方案3】:

    理论

    我尝试更新 Deployment,但只更新了新的 ReplicaSet。旧的保持不变。

    在这种情况下,问题在于您有 2 个不同的 Deployments。您正在编辑的一个(所以一个 rs 得到更新)和另一个(“旧”)以其他方式创建。

    通常,您不能轻易删除ReplicaSet,因为它是由另一个实体控制的。

    在 Kubernetes 中,可以通过以下方式删除 rs

    • kubectl get replicaset -n kube-system 查找“旧”rs 的名称。
    • 找到“旧”rs 控制的对象:kubectl describe &lt;rs-name&gt;
    • 删除该rs 的父对象。

    练习

    您观察到多个rs'es 的事实意味着您一直在尝试更新Deployment

    kubectl get rs -o wide -n kube-system | grep example
    
    NAME               DESIRED  CURRENT     READY   AGE     
    example-6d4f99bc54 0        0       0   12h 
    example-59d46955b6 0        0       0   13h 
    example-5855866cdb 0        0       0   18h 
    example-ccc5cf5cd0 0        0       0   18h 
    example-66db79f578 1        1       0   19h     
    example-759469945f 1        1       1   19h 
    example-ff8f986960 0        0       0   19h 
    

    从该输出中,我们可以看到 19 小时前创建的 example-759469945f 是活动的 (DESIRED/CURRENT/READY = 1/1/1)。之后尝试更新它,因此其他rs'es被更新过程一一创建。

    由于Deployment 的问题,所有这些尝试均未成功(我们稍后会讨论)。

    经过几次不成功的尝试后,您回滚到example-66db79f578,它也是用损坏的Deployment 创建的(这就是为什么最新的example-6d4f99bc540/0/0 而不是1/1/0

    损坏的Deployment根本原因,为什么您有 2 个具有 CURRENT=1 的副本集(example-759469945fexample-66db79f578 分别具有 1/1/11/1/0)。

    请注意,此Deployment 中使用了RollingUpdate 策略。

    StrategyType:           RollingUpdate
    MinReadySeconds:        0
    RollingUpdateStrategy:  25% max unavailable, 25% max surge
    

    这就是为什么旧的rs 没有退役而新的没有完全“启动并运行”(与DESIRED/CURRENT/READY 具有匹配值)

    一旦您修复 Deployment 并应用更改,您最终将只有一个 rs

    为了修复部署,需要检查 k8s 尝试为 example-66db79f578 创建 pod 时出了什么问题

    您可以通过以下方式进行:

    # check the pod name
    kubectl get pods -n kube-system | grep 66db79f578
    
    # describe pod. it shall give you the root cause in "Events:" section
    kubectl describe pod example-66db79f578-<somehash>
    
    # additionally you can try checking logs for the containers on that pod.
    
    kubectl logs example-66db79f578-<somehash>  example
    kubectl logs example-66db79f578-<somehash>  example-sidecar
    
    # fix :)
    # apply changes
    

    一旦你修复了损坏的Deployment,你就可以毫无问题地应用它。

    希望对您有所帮助。

    【讨论】:

    • 新旧 RS 是同一个 Deployment 的子节点。因此,如果我删除父级,则两个 RS 都消失了。这就是问题所在,一个 Deployment 有两个活动的 ReplicaSet。
    • 两个副本集的部署都和Parent一样?
    • 是的!!!!从一开始就是这个问题。两个 ReplicaSet 与 Parent 具有相同的 Deployment。
    • 我明天会尝试复制它。您使用的是 gke、eks、aks、独立 k8s 吗?
    • 我正在使用通过 Kops 和 Helm 部署在 AWS EC2 上的独立 K8s。
    猜你喜欢
    • 2023-01-04
    • 2019-03-31
    • 1970-01-01
    • 2020-04-28
    • 2019-09-15
    • 2023-03-09
    • 2019-10-01
    • 2021-04-21
    • 1970-01-01
    相关资源
    最近更新 更多