从 k8s 和 helm 漂移中恢复

the*_*rex 5 kubernetes kubernetes-helm

我们使用 helm 来管理 k8s 集群中的所有资源。最近我们发生了一个事件,在 helm 之外修改了一些 k8s 资源(有关根本原因的详细信息,请参见下文)。

然而,最终结果是,我们的集群中有一些 k8s 资源与发布的舵图中指定的资源不匹配。

例子:

我们有一个包含HorizontalPodAutoscaler. 如果我做这样的事情:

helm get myservice-release
Run Code Online (Sandbox Code Playgroud)

我会看到这样的事情:

---
# Source: myservice/charts/default-deployment/templates/default_deployment.yaml
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: myservice-autoscaler
  labels:     
    app: myservice
spec:
  minReplicas: 2
  maxReplicas: 10
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myservice-deployment
  metrics:
  - type: Resource
    resource:
      name: cpu
      targetAverageUtilization: 85
Run Code Online (Sandbox Code Playgroud)

但是,如果我这样做:

kubectl get hpa myservice-autoscaler -o yaml
Run Code Online (Sandbox Code Playgroud)

spec.{max,min}Replicas不匹配的图表:

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  annotations:
    autoscaling.alpha.kubernetes.io/conditions: '{REDACTED}'
    autoscaling.alpha.kubernetes.io/current-metrics: '{REDACTED}'
  creationTimestamp: "{REDACTED}"
  labels:
    app: myservice
  name: myservice-autoscaler
  namespace: default
  resourceVersion: "174526833"
  selfLink: /apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/myservice-autoscaler
  uid: {REDACTED}
spec:
  maxReplicas: 1
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myservice-deployment
  targetCPUUtilizationPercentage: 85
status:
  currentCPUUtilizationPercentage: 9
  currentReplicas: 1
  desiredReplicas: 1
  lastScaleTime: "{REACTED}"
Run Code Online (Sandbox Code Playgroud)

我怀疑,k8s 资源中发生的漂移不止这一次。

  • 如何验证哪些资源发生了漂移?
  • 我如何通知 helm 那个漂移,以便下一次部署可以在应用发布差异时考虑它?

编辑:

对于那些感兴趣的人,这是由于helm管理相同资源(自动缩放)的两个图表都设置了不同的值造成的。

发生这种情况是因为用于不同命名空间的两个 helm 版本最终在同一个版本中,并且更新为--force.

the*_*rex 4

我们找到了一种以可扩展的方式做到这一点的方法。请注意,此解决方案需要 Kubernetes 1.13 才能支持kubectl diff.

总体思路是获取 helm 状态并应用它kubectl以再次同步两者。这在您的集群上可能不安全,请使用 验证更改kubectl diff

  1. 从 helm 获取状态:helm get manifest {service}-release > {service}-release.yaml

  2. 检查 k8s 对象是否存在差异:kubectl diff -f {service}-release.yaml

  3. 用 helm 状态覆盖 k8s 状态:kubectl apply -f {service}-release.yaml