我的 DevOps 之旅始于我开始开发 Datree,这是一个旨在帮助 DevOps 工程师防止 Kubernetes 错误配置进入生产环境的开源命令。一年后,寻求最佳实践和更多防止错误配置的方法成为了我的生活方式。
这就是为什么当我第一次了解到 Argo CD 时,在不了解其陷阱和复杂性的情况下使用 Argo 对我来说根本没有意义。毕竟,错误地配置它很可能很容易导致下一次生产中断。
在本文中,我将探讨我发现的一些 Argo 最佳实践,并向您展示如何根据这些最佳实践验证自定义资源。
禁止提供空的 retryStrategy
项目: Argo Workflows
最佳实践: 用户可以指定一个 retryStrategy
,用于指示工作流中错误和失败的重试方式。提供一个空的 retryStrategy (retryStrategy: {})
会导致容器重试直到完成,并最终导致内存不足 (OOM) 问题。
确保 Workflow Pod 未配置为使用默认服务帐户
项目: Argo Workflows
最佳实践: 工作流中的所有 Pod 都使用服务帐户运行,该服务帐户可以在 workflow.spec.serviceAccountName
中指定。 如果省略,Argo 将使用工作流命名空间的 default
服务帐户。这为工作流(Pod)提供了与 Kubernetes API 服务器交互的能力。这允许有权访问单个容器的攻击者通过使用 AutomountServiceAccountToken
来滥用 Kubernetes。如果万一禁用了 AutomountServiceAccountToken
选项,那么 Argo 使用的默认服务帐户将没有任何权限,并且工作流将失败。
建议创建具有适当角色的专用用户管理服务帐户。
在 ConfigMap 中设置标签 'part-of: argocd'
项目: Argo CD
在安装 Argo CD 时,其原子配置包含一些服务和 configMaps
。对于每种特定的 ConfigMap 和 Secret 资源,只有一个受支持的资源名称(如上表所示)。如果您需要合并内容,请在创建它们之前执行此操作。使用标签 app.kubernetes.io/part-of: argocd
注释您的 ConfigMap 资源非常重要,否则 Argo CD 将无法使用它们。
在 DAG 中禁用 'FailFast=false'
项目: Argo Workflows
最佳实践: 作为在 Workflow 中指定步骤序列的替代方案,您可以通过指定每个任务的依赖关系将工作流定义为有向无环图 (DAG)。DAG 逻辑具有内置的快速失败功能,以便在检测到其中一个 DAG 节点失败时停止调度新步骤。然后,它会等待所有 DAG 节点完成,然后 DAG 本身才失败。FailFast 标志默认为 true
。如果设置为 false
,则允许 DAG 运行 DAG 的所有分支直至完成(成功或失败),而与 DAG 中分支的失败结果无关。
确保 Rollout 暂停步骤配置了持续时间
项目: Argo Rollouts
最佳实践: 对于每个 Rollout,您可以定义一个步骤列表。每个步骤可以有两个字段之一:setWeight
和 pause
。setWeight
字段指示应发送到 Canary 的流量百分比,而 pause 字面意思是指示 rollout 暂停。
在底层,Argo 控制器使用这些步骤在 rollout 期间操作 ReplicaSet。当控制器到达 rollout 的 pause 步骤时,它会将 PauseCondition
结构添加到 .status.PauseConditions
字段。如果设置了 pause 结构中的 duration
字段,则 rollout 在等待 duration
字段的值之前不会进行到下一步。但是,如果省略了 duration
字段,则 rollout 可能会无限期地等待,直到删除添加的暂停条件。
指定 Rollout 的 revisionHistoryLimit
项目: Argo Rollouts
最佳实践: .spec.revisionHistoryLimit
是一个可选字段,指示应保留的旧 ReplicaSet 的数量,以便允许回滚。这些旧的 ReplicaSet 会消耗 etcd
中的资源,并使 kubectl get rs
的输出变得混乱。每个 Deployment 修订版本的配置都存储在其 ReplicaSet 中;因此,一旦旧的 ReplicaSet 被删除,您将失去回滚到该 Deployment 修订版本的能力。
默认情况下,保留 10 个旧的 ReplicaSet。但是,理想值取决于新 Deployment 的频率和稳定性。更具体地说,将此字段设置为零意味着所有副本数为 0 的旧 ReplicaSet 都将被删除。在这种情况下,新的 Deployment rollout 无法撤消,因为其修订历史记录已被删除。
将 scaleDownDelaySeconds 设置为 30 秒
项目: Argo Rollouts
最佳实践: 当 rollout 更改服务上的选择器时,在所有节点更新其 IP 表以将流量发送到新 Pod 而不是旧 Pod 之前,存在传播延迟。如果在延迟期间节点尚未更新,则流量将定向到旧 Pod。为了防止数据包被发送到已杀死旧 Pod 的节点,rollout 使用 scaleDownDelaySeconds
字段为节点提供足够的时间来广播 IP 表更改。如果省略,Rollout 将等待 30 秒,然后再缩减之前的 ReplicaSet。
建议将 scaleDownDelaySeconds
设置为至少 30 秒,以确保 IP 表在集群中的节点之间传播。原因是 Kubernetes 会等待一个指定的时间,称为终止宽限期。默认情况下,这是 30 秒。
确保在 Error 和 TransientError 上都重试
项目: Argo Workflows
最佳实践: retryStrategy
是 Workflow CRD 的一个可选字段,它为重试工作流步骤提供控制。retryStrategy
的字段之一是 _retryPolicy
,它定义要重试的 NodePhase 状态的策略(NodePhase 是节点在当前时间的状态)。retryPolicy
的选项可以是:Always
、OnError
或 OnTransientError
。此外,用户可以使用表达式来更多地控制重试。
有什么陷阱?
- retryPolicy=Always 太多了: 允许用户重试系统级错误(例如,节点死机或被抢占),但不重试用户级代码中发生的错误,因为这些故障表明存在错误。此外,此选项更适合长时间运行的容器,而不是作为作业的工作流。
- retryPolicy=OnError 不处理抢占:使用
retryPolicy=OnError
处理某些系统级错误,例如节点消失或 Pod 被删除。但是,在正常的 Pod 终止期间,kubelet 会为已终止的 Pod 分配Failed
状态和Shutdown
原因。因此,节点抢占会导致节点状态为Failure
而不是Error
,因此不会重试抢占。 - retryPolicy=OnError 不处理瞬时错误: 将抢占失败消息归类为瞬时错误是允许的。但是,这需要
retryPolicy=OnTransientError
。(另请参见TRANSIENT_ERROR_PATTERN
)。
我建议设置 retryPolicy: "Always"
并使用以下表达式
lastRetry.status == "Error" or (lastRetry.status == "Failed" and asInt(lastRetry.exitCode) not in [0])
确保progressDeadlineAbort 设置为 true
项目: Argo Rollouts
最佳实践: 用户可以设置 progressDeadlineSeconds
, 它声明 rollout 在更新期间必须取得进展的最长时间(以秒为单位),超过此时间则认为 rollout 失败。
如果 rollout Pod 卡在错误状态(例如,镜像拉取回退),则 rollout 会在超过进度截止时间后降级,但错误的 ReplicaSet 或 Pod 不会被缩减。Pod 将继续重试,最终 rollout 消息将显示 ProgressDeadlineExceeded: The replicaset has timed out progressing
。要中止 rollout,请同时设置 progressDeadlineSeconds
和 progressDeadlineAbort
,并将 progressDeadlineAbort: true
。
确保自定义资源与 ArgoCD 实例的命名空间匹配
项目: Argo CD
最佳实践: 在每个存储库中,所有 Application 和 AppProject 清单都应与相同的 metadata.namespace 匹配。如果您使用典型的部署方式部署了 Argo CD,则 Argo CD 会创建两个 ClusterRoles
和 ClusterRoleBinding
,默认情况下它们引用 argocd
命名空间。在这种情况下,建议不仅要确保所有 Argo CD 资源都与 Argo CD 实例的命名空间匹配,还要使用 argocd
命名空间。否则,您需要确保更新所有 Argo CD 内部资源中的命名空间引用。
但是,如果您为外部集群部署了 Argo CD(在命名空间隔离模式下),则 Argo 会在部署 Argo CD 的命名空间中创建 Roles
和关联的 RoleBindings
,而不是 ClusterRole
和 ClusterRoleBinding
。创建的服务帐户被授予有限级别的管理访问权限,因此为了使 Argo CD 能够按预期运行,必须显式授予对命名空间的访问权限。在这种情况下,您应确保所有资源(包括 Application
和 AppProject
)都使用 ArgoCD 实例的正确命名空间。
接下来做什么?
我是一名 GitOps 信徒,并且我认为每个 Kubernetes 资源都应该像您的源代码一样处理,特别是如果您正在使用 Helm 或 Kustomize。因此,在我看来,您应该在每次代码更改时自动检查您的资源。
您可以使用 Rego 或 JSONSchema 等语言编写策略,并使用 OPA ConfTest 或不同的验证器在每次更改时扫描和验证我们的资源。此外,如果您有一个 GitOps 存储库,那么 Argo 在为您提供集中式存储库以开发和版本控制您的策略方面发挥着重要作用。
[ 下载电子书: Getting GitOps:使用 OpenShift、Argo CD 和 Tekton 的实用平台 ]
Datree 的工作原理
Datree CLI 对给定路径中存在的每个资源运行自动检查。检查完成后,Datree 会显示它发现的任何违规或错误配置的详细输出,并提供有关如何修复它的指南
使用 Datree 扫描您的集群
$ kubectl datree test -- -n argocd
您可以使用 Datree kubectl 插件在部署后验证您的资源,为未来的版本升级做好准备,并监控集群的总体合规性。
在 CI 中扫描您的清单
通常,Datree 可以用于 CI、作为本地测试库,甚至作为 pre-commit hook。要使用 datree
,您首先需要在您的机器上安装该命令,然后使用以下命令执行它
$ datree test -.datree/k8s-demo.yaml >> File: .datree/k8s-demo.yaml
[V] YAML Validation
[V] Kubernetes schema validation
[X] Policy check
X Ensure each container image has a pinned (tag) version [1 occurrence]
- metadata.name: rss-site (kind: Deployment)
!! Incorrect value for key 'image' - specify an image version
X Ensure each container has a configured memory limit [1 occurrence]
- metadata.name: rss-site (kind: Deployment)
!! Missing property object 'limits.memory' - value should be within the accepter
X Ensure workload has valid Label values [1 occurrence]
- metadata.name: rss-site (kind: Deployment)
!! Incorrect value for key(s) under 'labels' - the vales syntax is not valid
X Ensure each container has a configured liveness probe [1 occurrence]
- metadata.name: rss-site (kind: Deployment)
!! Missing property object 'livenessProbe' - add a properly configured livenessP:
[...]
正如我上面提到的,CLI 的工作方式是对给定路径中存在的每个资源运行自动检查。每个自动检查包括三个步骤
- YAML 验证:验证文件是否为有效的 YAML 文件。
- Kubernetes 模式验证:验证文件是否为有效的 Kubernetes/Argo 资源。
- 策略检查:验证文件是否符合您的 Kubernetes 策略(默认情况下为 Datree 内置规则)。
总结
我认为,管理策略仅仅是实现 Kubernetes 集群的可靠性、安全性和稳定性的开始。我惊讶地发现,集中式策略管理也可能是解决 DevOps 和开发僵局的关键解决方案。
查看 Datree 开源项目。我强烈建议您查看代码并提交 PR,并且不要犹豫与我联系。
本文最初出现在 Datree 博客上,并已获得许可重新发布。
评论已关闭。