4. Argo CD Projects 深度解析:Project 角色、权限模型、Source/Destination 限制、Sync Windows
Argo CD Project 是多租户隔离的核心资源边界。每个 Project 定义了一组逻辑上的应用集合,并强制约束这些应用可以使用的 Git 仓库(Source)、目标集群与命名空间(Destination)、同步行为(Sync Windows)以及 RBAC 权限。理解 Project 的深度机制,是构建安全多租户架构的前提。
4.1 Project 角色与权限模型
Argo CD 的 RBAC 模型以 Project 为粒度,通过 argocd-rbac-cm ConfigMap 定义角色绑定。每个 Project 可以拥有独立的角色集合,控制用户或组对 Project 内应用的 CRUD 操作。
| 角色 | 权限范围 | 典型操作 |
|---|---|---|
| role:admin | Project 内所有资源 | 创建/更新/删除应用、管理 Project 设置、触发同步 |
| role:maintainer | Project 内应用 | 更新应用参数、触发同步、查看状态 |
| role:viewer | Project 内应用 | 只读查看应用状态、同步历史、事件 |
| 自定义角色 | 按需定义 | 通过 RBAC 策略精确匹配操作与资源 |
关键实践: 为每个租户创建独立的 Project,并绑定
role:admin 给租户管理员,role:viewer 给审计人员。避免使用全局 role:admin 跨 Project 操作。
RBAC 策略示例(argocd-rbac-cm):
data:
policy.csv: |
p, role:tenant-admin, projects, get, my-project, allow
p, role:tenant-admin, applications, *, my-project/*, allow
p, role:tenant-viewer, projects, get, my-project, allow
p, role:tenant-viewer, applications, get, my-project/*, allow
g, alice, role:tenant-admin
g, bob, role:tenant-viewer
4.2 Source 限制:控制代码来源
Source 限制定义了 Project 内的应用允许从哪些 Git 仓库或 Helm Chart 仓库拉取配置。这是防止恶意代码注入的第一道防线。
- 允许的仓库列表: 通过
sourceRepos字段指定,支持精确 URL 或通配符。 - 拒绝默认: 如果
sourceRepos为空,则 Project 内所有应用都无法创建,必须显式添加。 - 路径限制: 可以进一步限制仓库内的子路径,例如只允许
https://git.example.com/team-a/*。
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: team-a-project
spec:
sourceRepos:
- 'https://git.example.com/team-a/*'
- 'https://charts.example.com/team-a'
# 拒绝所有其他仓库
安全警告: 避免使用
'*' 通配符开放所有仓库。如果必须使用,请结合 sourceNamespaces 或 admission webhook 做二次校验。
4.3 Destination 限制:控制部署目标
Destination 限制定义了应用可以部署到哪些 Kubernetes 集群和命名空间。这是多租户隔离的第二个关键维度。
| 字段 | 说明 | 示例 |
|---|---|---|
destinations |
允许的目标集群与命名空间列表 | server: https://kubernetes.default.svcnamespace: team-a-* |
namespaceResourceWhitelist |
允许在目标命名空间内创建的 Kubernetes 资源类型 | Group: ''; Kind: 'Deployment' |
namespaceResourceBlacklist |
禁止在目标命名空间内创建的 Kubernetes 资源类型 | Group: 'rbac.authorization.k8s.io'; Kind: 'ClusterRole' |
spec:
destinations:
- namespace: 'team-a-*'
server: 'https://kubernetes.default.svc'
- namespace: 'team-a-*'
server: 'https://cluster-2.example.com'
namespaceResourceBlacklist:
- group: 'rbac.authorization.k8s.io'
kind: 'ClusterRole'
- group: 'rbac.authorization.k8s.io'
kind: 'ClusterRoleBinding'
最佳实践: 使用命名空间前缀(如
team-a-*)隔离租户,并利用 namespaceResourceBlacklist 禁止租户创建集群范围的资源(ClusterRole、ClusterRoleBinding、PersistentVolume 等)。
4.4 Sync Windows:控制同步时间窗口
Sync Windows 允许管理员定义 Project 内应用可以执行同步操作的时间段。这用于防止在业务高峰期或维护窗口外发生意外变更。
- 窗口类型:
allow(允许同步)或deny(拒绝同步)。 - 调度格式: 使用 cron 表达式或简单的时间范围(如
* * * * 1-5表示工作日)。 - 应用范围: 可以针对整个 Project 或特定应用(通过
applications列表)。 - 手动同步覆盖: 默认情况下,手动触发的同步也会受窗口限制,但可以通过
manualSync: true允许管理员绕过。
spec:
syncWindows:
- kind: deny
schedule: '* * * * 1-5'
duration: 8h
applications:
- 'production-*'
manualSync: false
- kind: allow
schedule: '* * * * 6,0'
duration: 24h
applications:
- '*'
典型场景: 生产环境 Project 配置
deny 窗口在工作日 9:00-17:00 禁止自动同步,仅允许紧急手动同步(需审批)。开发环境 Project 不设窗口,允许随时同步。
4.5 综合架构:Project 资源边界
以下 SVG 图展示了单个 Project 如何通过 Source、Destination、Sync Windows 和 RBAC 构建完整的资源边界。
4.6 多 Project 隔离策略对比
| 策略 | 隔离粒度 | 管理复杂度 | 推荐场景 |
|---|---|---|---|
| 单 Project 多命名空间 | 命名空间级别 | 低 | 开发环境、信任度高的团队 |
| 每租户独立 Project | Project 级别 | 中 | 多租户生产环境、合规要求 |
| 每应用独立 Project | 应用级别 | 高 | 高安全环境、独立审计需求 |
推荐: 对于大多数多租户场景,采用“每租户独立 Project”策略,结合命名空间前缀隔离和资源黑名单,在安全性与运维成本之间取得平衡。
4.7 常见配置陷阱与修复
- 陷阱:
sourceRepos使用'*'导致任意仓库可部署。
修复: 明确列出允许的仓库 URL,并使用路径通配符限制子路径。 - 陷阱:
destinations未限制命名空间,导致跨租户命名空间部署。
修复: 使用命名空间前缀白名单,如namespace: 'tenant-a-*'。 - 陷阱: Sync Windows 未设置
manualSync: false,导致管理员可绕过窗口。
修复: 对生产环境 Project 设置manualSync: false,强制所有同步受窗口约束。 - 陷阱: RBAC 策略中
projects, get未限制 Project 名称,导致用户可查看所有 Project。
修复: 在策略中明确指定 Project 名称,如p, role:tenant-admin, projects, get, my-project, allow。
审计建议: 定期使用
argocd proj list 和 argocd proj get <project> 检查每个 Project 的 Source/Destination 限制是否仍然符合安全基线。任何宽泛规则(如 '*' 通配符)都应触发告警。