【CN】Argo 持续集成和交付(一)

1.简介

Argo 英 [ˈɑ:ɡəu] 美 [ˈɑrˌɡo]

Kubernetes 原生工具,用于运行工作流程、管理集群以及正确执行 GitOps。

Argo 于 2020 年 3 月 26 日被 CNCF 接受为孵化成熟度级别,然后于 2022 年 12 月 6 日转移到毕业成熟度级别。

manifest 清单
UK /ˈmæn.ɪ.fest/
US /ˈmæn.ə.fest/

2.什么是Argo CD

Argo CD 是针对 Kubernetes 的声明式 GitOps 持续交付工具。

2.1.为什么选择 Argo CD?

  • 应用程序定义、配置和环境应该是声明性的和版本控制的。
  • 应用程序部署和生命周期管理应该是自动化、可审计且易于理解的。

2.2.演示示例

3.概要

3.1.快速开始

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

3.2.工作原理

Argo CD 遵循 GitOps 模式,使用 Git 存储库作为定义所需应用程序状态的真实来源。Kubernetes 清单(manifests)可以通过多种方式指定:

  • kustomize applications
  • helm charts
  • jsonnet files
  • YAML/json 清单(manifests) 普通目录
  • 任何配置为配置管理插件的自定义配置管理工具

Argo CD 可自动在指定的目标环境中部署所需的应用程序状态。应用程序部署可以跟踪 Git 提交时对分支、标签或固定到特定版本清单的更新。有关可用的不同跟踪策略的更多详细信息,请参阅跟踪策略

3.3.架构

Argo架构
Argo CD 被实现为 Kubernetes 控制器,它持续监控正在运行的应用程序并将当前实时状态与所需目标状态(如 Git 存储库中指定)进行比较。如果已部署应用程序的实时状态与目标状态有偏差,则视为 OutOfSync。Argo CD 报告并可视化差异,同时提供将实时状态自动或手动同步回所需目标状态的功能。对 Git 存储库中所需目标状态所做的任何修改都可以自动应用并反映在指定的目标环境中。

3.4.特征

  • 自动将应用程序部署到指定的目标环境
  • 支持多种配置管理/模板工具(Kustomize、Helm、Jsonnet、plain-YAML)
  • 能够管理和部署到多个集群
  • SSO 集成(OIDC、OAuth2、LDAP、SAML 2.0、GitHub、GitLab、Microsoft、LinkedIn)
  • 多租户和 RBAC 授权策略
  • 回滚/随处回滚至 Git 存储库中提交的任何应用程序配置
  • 应用资源健康状态分析
  • 自动配置漂移检测和可视化
  • 自动或手动同步应用程序至所需状态
  • Web UI 提供应用程序活动的实时视图
  • 用于自动化和 CI 集成的 CLI
  • Webhook 集成(GitHub、BitBucket、GitLab)
  • 自动化访问令牌
  • PreSync、Sync、PostSync 挂钩支持复杂的应用程序推出(例如蓝/绿和金丝雀升级)
  • 应用程序事件和 API 调用的审计跟踪
  • Prometheus 指标
  • 用于覆盖 Git 中的 helm 参数的参数覆盖

3.5.发布版本

4.基本原理

在有效使用 Argo CD 之前,有必要了解该平台所基于的底层技术。还需要了解提供给您的功能及其使用方法。以下部分提供了一些有用的链接来帮助您加深这种理解。

5.核心概念

以下是一些特定于 Argo CD 的概念。

  • 应用程序:清单(manifest)定义的一组 Kubernetes 资源。这是一个自定义资源定义 (CRD)。
  • 应用程序源类型:用于构建应用程序的工具。
  • 目标状态:应用程序的所需状态,以 Git 存储库中的文件表示。
  • 实时状态:该应用程序的实时状态。部署了哪些 pod 等。
  • 同步状态:实时状态是否与目标状态匹配。部署的应用程序是否与 Git 所说的一致?
  • 同步:使应用程序移动到其目标状态的过程。例如,通过将更改应用于 Kubernetes 集群。
  • 同步操作状态:同步是否成功。
  • 刷新:将 Git 中的最新代码与实时状态进行比较。找出不同之处。
  • 健康:应用程序的健康状况,是否正常运行? 是否可以处理请求?
  • 工具:从文件目录创建清单(manifest)的工具。例如 Kustomize。请参阅应用程序源类型。
  • 配置管理工具:请参阅工具。
  • 配置管理插件:自定义工具。

6.入门

6.1.前提条件

  • 已安装 kubectl 命令行工具
  • 有一个 kubeconfig 文件(默认位置是 ~/.kube/config
  • CoreDNS:通过 microk8s enable dns && microk8s stop && microk8s start 启用

1.安装 Argo CD

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

这将创建一个新的命名空间 argocd,Argo CD 服务和应用程序资源将驻留在其中。

安装清单包括引用 argocd 命名空间的 ClusterRoleBinding 资源。如果您要将 Argo CD 安装到其他命名空间,请确保更新命名空间引用。

如果您对 UI、SSO 和多集群功能不感兴趣,那么您可以只安装核心 Argo CD 组件。

此默认安装将具有自签名证书,如果不进行额外工作则无法访问。请执行以下任一操作:

  • 按照说明配置证书(并确保客户端操作系统信任它)。
  • 配置客户端操作系统以信任自签名证书。
  • 在本指南的所有 Argo CD CLI 操作中使用 --insecure 标志。

kubectl config 的默认命名空间必须设置为 argocd。这仅适用于以下命令,因为前面的命令已经有 -n argocdkubectl config set-context --current --namespace=argocd

使用 argocd login --core 配置 CLI 访问并跳过步骤 3-5。

Redis 的默认安装使用密码验证。Redis 密码存储在安装 Argo CD 的命名空间中的 Kubernetes 机密 argocd-redis 中,密钥为 auth

2.下载 Argo CD CLI

下载 最新的 Argo CD 版本。可以通过 CLI 安装文档 找到更详细的安装说明。

也可在 Mac、Linux 和 WSL Homebrew 中使用:

brew install argocd

3.访问 Argo CD API 服务器

默认情况下,Argo CD API 服务器不会通过外部 IP 公开。要访问 API 服务器,请选择以下技术之一来公开 Argo CD API 服务器:

服务类型负载均衡器

argocd-server服务类型更改为LoadBalancer

kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
Ingress 容器注册表

按照入口文档 了解如何使用入口配置 Argo CD。

转发端口

Kubectl 端口转发也可用于连接 API 服务器而无需公开服务。

kubectl port-forward svc/argocd-server -n argocd 8080:443

然后可以使用 https://localhost:8080 访问 API 服务器

4.使用 CLI 登录

admin帐户的初始密码是自动生成的,并以明文形式存储在 Argo CD 安装命名空间中名为 argocd-initial-admin-secret 的机密中的password字段中。您可以使用 argocd CLI 轻松检索此密码:

argocd admin initial-password -n argocd

更改密码后,您应该从 Argo CD 命名空间中删除 argocd-initial-admin-secret。该密钥除了以明文形式存储最初生成的密码外,没有其他用途,并且可以随时安全地删除。如果必须重新生成新的管理员密码,Argo CD 将根据需要重新创建它。

使用上面的用户名admin 和密码登录 Argo CD 的 IP 或主机名:

argocd login <ARGOCD_SERVER>

CLI 环境必须能够与 Argo CD API 服务器通信。如果无法按照上述步骤 3 中的说明直接访问,您可以通过以下机制之一告诉 CLI 使用端口转发来访问它:

  1. 向每个 CLI 命令添加 --port-forward-namespace argocd 标志;
    或 2) 设置 ARGOCD_OPTS 环境变量:export ARGOCD_OPTS='--port-forward-namespace argocd'

使用以下命令更改密码:

argocd account update-password

5.注册集群以部署应用程序(可选)

此步骤将集群的凭据注册到 Argo CD,并且仅在部署到外部集群时才需要。在内部部署时(部署到 Argo CD 正在运行的同一集群),应使用 https://kubernetes.default.svc 作为应用程序的 K8s API 服务器地址。

首先列出当前 kubeconfig 中的所有集群上下文:

kubectl config get-contexts -o name

从列表中选择一个上下文名称并将其提供给 argocd cluster add CONTEXTNAME。例如,对于 docker-desktop 上下文,运行:

argocd cluster add docker-desktop

上述命令将 ServiceAccount (argocd-manager) 安装到该 kubectl 上下文的 kube-system 命名空间中,并将服务帐户绑定到管理员级别的 ClusterRole。Argo CD 使用此服务帐户令牌执行其管理任务(即部署/监控)。

argocd-manager-role 角色的规则可以修改,使其仅对有限的命名空间、组和种类具有create, update, patch, delete权限。但是,在集群范围内,get, list, watch权限是 Argo CD 正常运行所必需的。

6.从 Git 存储库创建应用程序

包含留言簿应用程序的示例存储库可在 https://github.com/argoproj/argocd-example-apps.git 上找到,以演示 Argo CD 的工作原理。

通过 CLI 创建应用程序

首先,我们需要运行以下命令将当前命名空间设置为 argocd:

kubectl config set-context --current --namespace=argocd

使用以下命令创建示例留言簿应用程序:

argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-server https://kubernetes.default.svc --dest-namespace default
通过 UI 创建应用程序

打开浏览器进入 Argo CD 外部 UI,通过访问浏览器中的 IP/主机名并使用步骤 4 中设置的凭据登录。
登录后,点击+ New App按钮,如下图:
在这里插入图片描述
将您的应用命名为 guestbook,使用项目默认值,并将同步策略保留为手动:
在这里插入图片描述
通过将存储库 URL 设置为 github 存储库 URL,将 https://github.com/argoproj/argocd-example-apps.git 存储库连接到 Argo CD,将修订保留为 HEAD,并将路径设置为 guestbook
在这里插入图片描述
对于目标,将集群 URL 设置为 https://kubernetes.default.svc(或集群名称为集群内)并将命名空间设置为默认值:
在这里插入图片描述
填写完以上信息后,点击UI顶部的Create,创建留言簿应用:
在这里插入图片描述

7.同步(部署)应用程序

通过 CLI 同步

一旦创建了留言簿应用程序,您现在可以查看其状态:

$ argocd app get guestbook
Name:               guestbook
Server:             https://kubernetes.default.svc
Namespace:          default
URL:                https://10.97.164.88/applications/guestbook
Repo:               https://github.com/argoproj/argocd-example-apps.git
Target:
Path:               guestbook
Sync Policy:        <none>
Sync Status:        OutOfSync from  (1ff8a67)
Health Status:      Missing

GROUP  KIND        NAMESPACE  NAME          STATUS     HEALTH
apps   Deployment  default    guestbook-ui  OutOfSync  Missing
       Service     default    guestbook-ui  OutOfSync  Missing

应用程序状态最初处于 OutOfSync 状态,因为应用程序尚未部署,并且尚未创建任何 Kubernetes 资源。要同步(部署)应用程序,请运行:

argocd app sync guestbook

此命令从存储库检索清单并执行清单的 kubectl apply。留言簿应用现已运行,您现在可以查看其资源组件、日志、事件和评估的健康状况。

通过 UI 同步

在这里插入图片描述
在这里插入图片描述

7.操作手册

本指南适用于想要为其他开发人员安装和配置 Argo CD 的管理员和操作员。

请确保您已完成入门指南。

7.1.架构概述

在这里插入图片描述

7.2.组件

API Server

API 服务器是一个 gRPC/REST 服务器,用于公开 Web UICLICI/CD 系统使用的 API。它具有以下职责:

  • 应用程序管理和状态报告
  • 调用应用程序操作(例如同步、回滚、用户定义的操作)
  • 存储库和集群凭证管理(存储为 K8s 密钥)
  • 身份验证和授权委托给外部身份提供商
  • RBAC 实施
  • Git webhook 事件的监听器/转发器

Repository Server

存储库服务器是一项内部服务,它维护保存应用程序清单的 Git 存储库的本地缓存。它负责在提供以下输入时生成并返回 Kubernetes 清单:

  • repository URL
  • revision (commit, tag, branch)
  • 应用程序路径
  • 模板特定设置:参数、helm values.yaml

Application Controller

应用程序控制器是一个 Kubernetes 控制器,它持续监控正在运行的应用程序,并将当前实时状态与所需的目标状态(如存储库中指定)进行比较。它检测 OutOfSync 应用程序状态并选择性地采取纠正措施。它负责调用任何用户定义的生命周期事件钩子(PreSync、Sync、PostSync)

7.3.安装

Argo CD 有两种安装类型:多租户和核心。

多租户(Multi-Tenant)

多租户安装是安装 Argo CD 最常见的方式。这种安装类型通常用于为组织中的多个应用程序开发团队提供服务,并由平台团队维护。

最终用户可以使用 Web UI 或 argocd CLI 通过 API 服务器访问 Argo CD。必须使用 argocd login <server-host> 命令配置 argocd CLI(在此处了解更多信息)。

提供了两种类型的安装清单:

非高可用性

不建议用于生产用途。此类安装通常在评估期间用于演示和测试。

  • install.yaml : 具有集群管理员访问权限的标准 Argo CD 安装。如果您计划使用 Argo CD 在 Argo CD 运行的同一集群中部署应用程序(即 kubernetes.svc.default),请使用此清单集。它仍将能够使用输入的凭据部署到外部集群。
  • namespace-install.yaml : 安装 Argo CD 仅需要命名空间级别权限(不需要集群角色)。如果您不需要 Argo CD 在 Argo CD 运行的同一集群中部署应用程序,请使用此清单集,并且将仅依赖于输入的集群凭据。使用此清单集的一个示例是,如果您为不同的团队运行多个 Argo CD 实例,其中每个实例都将将应用程序部署到外部集群。仍然可以使用输入的凭据(即 argocd cluster add <CONTEXT> --in-cluster --namespace <YOUR NAMESPACE>)部署到同一集群(kubernetes.svc.default)。

注意:Argo CD CRD 不包含在 namespace-install.yaml 中,必须单独安装。CRD 清单位于 manifests/crds 目录中。使用以下命令安装它们:kubectl apply -k https://github.com/argoproj/argo-cd/manifests/crds\?ref\=stable

高可用性

建议在生产中使用高可用性安装。此软件包包含相同的组件,但针对高可用性和弹性进行了调整。

核心(Core)

Argo CD Core 安装主要用于以无头模式部署 Argo CD。这种安装类型最适合独立使用 Argo CD 且不需要多租户功能的集群管理员。此安装包含的组件较少​​,设置起来也更简单。该软件包不包含 API 服务器或 UI,并安装每个组件的轻量级(非 HA)版本。

安装清单可在 core-install.yaml 中找到。

有关 Argo CD Core 的更多详细信息,请参阅官方文档

Kustomize

UK /ˈkʌs.tə.maɪzd/
US /ˈkʌs.tə.maɪzd/

Argo CD 清单也可以使用 Kustomize 安装。建议将清单作为远程资源包含在内,并使用 Kustomize 补丁应用其他自定义功能。

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: argocd
resources:
- https://raw.githubusercontent.com/argoproj/argo-cd/v2.7.2/manifests/install.yaml

有关示例,请参阅用于部署 Argoproj CI/CD 基础设施的 kustomization.yaml

Helm

UK US /helm/

可以使用 Helm 安装 Argo CD。Helm 图表目前由社区维护,可在 argo-helm/charts/argo-cd 上找到。

支持的版本

下表显示了使用每个版本的 Argo CD 测试的 Kubernetes 版本。

Argo CD versionKubernetes versions
2.11v1.29, v1.28, v1.27, v1.26, v1.25
2.10v1.28, v1.27, v1.26, v1.25
2.9v1.28, v1.27, v1.26, v1.25

7.4.Argo CD 核心

介绍

Argo CD Core 是一个不同的安装,它以无头模式运行 Argo CD。通过此安装,您将拥有一个功能齐全的 GitOps 引擎,能够从 Git 存储库获取所需状态并将其应用于 Kubernetes。

以下功能组在此安装中不可用:

  • Argo CD RBAC 模型
  • Argo CD API
  • OIDC 基于身份验证

以下功能将部分可用:

  • Argo CD Web UI
  • Argo CD CLI
  • Multi-tenancy (严格基于 git push 权限的 GitOps)

运行 Argo CD Core 的一些用例包括:

  • 作为集群管理员,我只想依赖 Kubernetes RBAC。
  • 作为一名 DevOps 工程师,我不想学习新的 API 或依赖其他 CLI 来自动化部署。我只想依赖 Kubernetes API。
  • 作为集群管理员,我不想向开发人员提供 Argo CD UI 或 Argo CD CLI。

架构

由于 Argo CD 在设计时就考虑到了基于组件的架构,因此可以实现更简约的安装。在这种情况下,安装的组件较少​​,但主要的 GitOps 功能仍可正常运行。

下图中的核心框显示了选择 Argo CD Core 时将安装的组件:
在这里插入图片描述

请注意,即使 Argo CD 控制器可以在没有 Redis 的情况下运行,也不建议这样做。Argo CD 控制器使用 Redis 作为重要的缓存机制,以减少 Kube API 和 Git 中的负载。因此,此安装方法中也包含 Redis。

安装

可以通过应用包含所有必需资源的单个清单文件来安装 Argo CD Core。

举例:

export ARGOCD_VERSION=<desired argo cd release version (e.g. v2.7.0)>
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/$ARGOCD_VERSION/manifests/core-install.yaml

使用

安装 Argo CD Core 后,用户将能够通过 GitOps 与其进行交互。可用的 Kubernetes 资源将是ApplicationApplicationSet CRD。通过使用这些资源,用户将能够在 Kubernetes 中部署和管理应用程序。

即使在运行 Argo CD Core 时,仍然可以使用 Argo CD CLI。在这种情况下,CLI 将生成一个本地 API 服务器进程,用于处理 CLI 命令。命令结束后,本地 API 服务器进程也将终止。这对于用户来说是透明的,无需其他命令。请注意,Argo CD Core 将仅依赖 Kubernetes RBAC,并且调用 CLI 的用户(或进程)需要具有在ApplicationApplicationSet 资源中执行给定命令的适当权限才能访问 Argo CD 命名空间。

举例:

kubectl config set-context --current --namespace=argocd # change current kube context to argocd namespace
argocd login --core

同样,如果用户喜欢使用此方法与 Argo CD 交互,他们也可以在本地运行 Web UI。可以通过运行以下命令在本地启动 Web UI:

argocd admin dashboard -n argocd

Argo CD Web UI 将在 http://localhost:8080 上提供

7.5.声明式启动

可以使用 Kubernetes 清单(manifests)以声明方式定义 Argo CD 应用程序、项目和设置。可以使用 kubectl apply 更新这些内容,而无需接触 argocd 命令行工具。

快速参考

所有资源,包括ApplicationAppProject 规范,都必须安装在 Argo CD 命名空间中(默认为 argocd)。

原子配置
示例文件资源名称种类(Kind)描述
argocd-cm.yamlargocd-cmConfigMap通用 Argo CD 配置
argocd-repositories.yamlmy-private-repo / istio-helm-repo / private-helm-repo / private-repoSecrets示例存储库连接详细信息
argocd-repo-creds.yamlargoproj-https-creds / argoproj-ssh-creds / github-creds / github-enterprise-credsSecrets示例存储库凭证模板
argocd-cmd-params-cm.yamlargocd-cmd-params-cmConfigMapArgo CD 环境变量配置
argocd-secret.yamlargocd-secretSecret用户密码、证书(已弃用)、签名密钥、Dex 机密、Webhook 机密
argocd-rbac-cm.yamlargocd-rbac-cmConfigMapRBAC 配置
argocd-tls-certs-cm.yamlargocd-tls-certs-cmConfigMap用于通过 HTTPS 连接 Git 存储库的自定义 TLS 证书(v1.2 及更高版本)
argocd-ssh-known-hosts-cm.yamlargocd-ssh-known-hosts-cmConfigMap通过 SSH 连接 Git 存储库的 SSH 已知主机数据(v1.2 及更高版本)

对于每种特定类型的 ConfigMap 和 Secret 资源,只有一个受支持的资源名称(如上表所列)——如果您需要合并,则需要在创建它们之前进行合并。

请务必使用标签 app.kubernetes.io/part-of: argocd 注释您的 ConfigMap 资源,否则 Argo CD 将无法使用它们。

多个配置对象
示例文件种类(Kind)描述
application.yamlApplication应用程序规范示例
project.yamlAppProject项目规格示例
-Secret存储库凭据

对于ApplicationAppProject 资源,资源的名称等于 Argo CD 中应用程序或项目的名称。这也意味着应用程序和项目名称在给定的 Argo CD 安装中是唯一的 - 两个不同的应用程序不能使用相同的应用程序名称。

Applications

应用程序 CRD 是代表环境中已部署的应用程序实例的 Kubernetes 资源对象。它由两条关键信息定义:

  • source 引用 Git 中所需的状态(repository, revision, path, environment)
  • destination 引用目标集群和命名空间。对于集群,可以使用服务器或名称之一,但不能同时使用(这将导致错误)。当服务器缺失时,它会根据名称进行计算并用于任何操作。

最小应用程序规范如下:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
    path: guestbook
  destination:
    server: https://kubernetes.default.svc
    namespace: guestbook

请参阅 application.yaml 以了解其他字段。只要您已完成入门的第一步,就可以使用 kubectl apply -n argocd -f application.yaml 应用此文件,然后 Argo CD 将开始部署留言簿应用程序。

命名空间必须与您的 Argo CD 实例的命名空间相匹配 - 通常是 argocd

从 Helm 存储库创建应用程序时,必须指定 chart属性,而不是 spec.source 中的 path 属性。

spec:
  source:
    repoURL: https://argoproj.github.io/argo-helm
    chart: argo

如果没有 resources-finalizer.argocd.argoproj.io 终结器,删除应用程序不会删除其管理的资源。要执行级联删除,您必须添加终结器。请参阅应用程序删除

metadata:
  finalizers:
    - resources-finalizer.argocd.argoproj.io
应用程序的应用程序

您可以创建一个应用来创建其他应用,而这些应用又可以创建其他应用。这样就可以声明性地管理一组可以同时部署和配置的应用。

参见集群引导

Projects

AppProject CRD 是代表应用程序逻辑分组的 Kubernetes 资源对象。它由以下关键信息定义:

  • sourceRepos 项目内的应用程序可以从中提取清单的存储库。
  • destinations 项目内的应用程序可以部署到的集群和命名空间。
  • roles 角色列表,其中定义了它们对项目内资源的访问权限。

如果项目的目标配置允许部署到安装了 Argo CD 的命名空间,则该项目下的应用程序具有管理员级访问权限。应严格限制对管理员级项目的 RBAC access,并且对允许的 sourceRepos 的推送访问权限应仅限于管理员。

示例规范如下:

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: my-project
  namespace: argocd
  # Finalizer that ensures that project is not deleted until it is not referenced by any application
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  description: Example Project
  # Allow manifests to deploy from any Git repos
  sourceRepos:
  - '*'
  # Only permit applications to deploy to the guestbook namespace in the same cluster
  destinations:
  - namespace: guestbook
    server: https://kubernetes.default.svc
  # Deny all cluster-scoped resources from being created, except for Namespace
  clusterResourceWhitelist:
  - group: ''
    kind: Namespace
  # Allow all namespaced-scoped resources to be created, except for ResourceQuota, LimitRange, NetworkPolicy
  namespaceResourceBlacklist:
  - group: ''
    kind: ResourceQuota
  - group: ''
    kind: LimitRange
  - group: ''
    kind: NetworkPolicy
  # Deny all namespaced-scoped resources from being created, except for Deployment and StatefulSet
  namespaceResourceWhitelist:
  - group: 'apps'
    kind: Deployment
  - group: 'apps'
    kind: StatefulSet
  roles:
  # A role which provides read-only access to all applications in the project
  - name: read-only
    description: Read-only privileges to my-project
    policies:
    - p, proj:my-project:read-only, applications, get, my-project/*, allow
    groups:
    - my-oidc-group
  # A role which provides sync privileges to only the guestbook-dev application, e.g. to provide
  # sync privileges to a CI system
  - name: ci-role
    description: Sync privileges for guestbook-dev
    policies:
    - p, proj:my-project:ci-role, applications, sync, my-project/guestbook-dev, allow
    # NOTE: JWT tokens can only be generated by the API server and the token is not persisted
    # anywhere by Argo CD. It can be prematurely revoked by removing the entry from this list.
    jwtTokens:
    - iat: 1535390316

Repositories

一些 Git 托管商(尤其是 GitLab 以及可能还有本地 GitLab 实例)要求您在存储库 URL 中指定 .git 后缀,否则它们将向以 .git 为后缀的存储库 URL 发送 HTTP 301 重定向。Argo CD 不会遵循这些重定向,因此您必须调整存储库 URL 以使其以 .git 为后缀。

存储库详细信息存储在密钥中。要配置存储库,请创建包含存储库详细信息的密钥。考虑使用 bitnami-labs/sealed-secrets 将加密的密钥定义存储为 Kubernetes 清单。每个存储库都必须有一个 url 字段,并且根据使用 HTTPS、SSH 还是 GitHub App 进行连接,必须有usernamepassword(对于 HTTPS)、sshPrivateKey(对于 SSH)或 githubAppPrivateKey(对于 GitHub App)。

使用bitnami-labs/sealed-secrets 时,标签将被删除,并且必须按照此处所述重新添加:https://github.com/bitnami-labs/sealed-secrets#sealedsecrets-as-templates-for-secrets

HTTPS 示例:

apiVersion: v1
kind: Secret
metadata:
  name: private-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: https://github.com/argoproj/private-repo
  password: my-password
  username: my-username

SSH 示例:

apiVersion: v1
kind: Secret
metadata:
  name: private-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: git@github.com:argoproj/my-private-repository.git
  sshPrivateKey: |
    -----BEGIN OPENSSH PRIVATE KEY-----
    ...
    -----END OPENSSH PRIVATE KEY-----

GitHub 应用程序示例:

apiVersion: v1
kind: Secret
metadata:
  name: github-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: https://github.com/argoproj/my-private-repository
  githubAppID: 1
  githubAppInstallationID: 2
  githubAppPrivateKey: |
    -----BEGIN OPENSSH PRIVATE KEY-----
    ...
    -----END OPENSSH PRIVATE KEY-----
---
apiVersion: v1
kind: Secret
metadata:
  name: github-enterprise-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: https://ghe.example.com/argoproj/my-private-repository
  githubAppID: 1
  githubAppInstallationID: 2
  githubAppEnterpriseBaseUrl: https://ghe.example.com/api/v3
  githubAppPrivateKey: |
    -----BEGIN OPENSSH PRIVATE KEY-----
    ...
    -----END OPENSSH PRIVATE KEY-----

Google Cloud Source 存储库示例:

kind: Secret
metadata:
  name: github-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: https://source.developers.google.com/p/my-google-project/r/my-repo
  gcpServiceAccountKey: |
    {
      "type": "service_account",
      "project_id": "my-google-project",
      "private_key_id": "REDACTED",
      "private_key": "-----BEGIN PRIVATE KEY-----\nREDACTED\n-----END PRIVATE KEY-----\n",
      "client_email": "argocd-service-account@my-google-project.iam.gserviceaccount.com",
      "client_id": "REDACTED",
      "auth_uri": "https://accounts.google.com/o/oauth2/auth",
      "token_uri": "https://oauth2.googleapis.com/token",
      "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
      "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/argocd-service-account%40my-google-project.iam.gserviceaccount.com"
    }

Kubernetes 文档中有关于创建包含私钥的密钥的说明

存储库凭证

如果您想要对多个存储库使用相同的凭证,可以配置凭证模板。凭证模板可以携带与存储库相同的凭证信息。

apiVersion: v1
kind: Secret
metadata:
  name: first-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: https://github.com/argoproj/private-repo
---
apiVersion: v1
kind: Secret
metadata:
  name: second-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: https://github.com/argoproj/other-private-repo
---
apiVersion: v1
kind: Secret
metadata:
  name: private-repo-creds
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repo-creds
stringData:
  type: git
  url: https://github.com/argoproj
  password: my-password
  username: my-username

在上面的例子中,每个通过 HTTPS 访问的存储库(其 URL 以 https://github.com/argoproj 为前缀)都会使用存储在键 username 中的用户名和存储在密钥 private-repo-creds 的键 password 中的密码来连接到 Git。

为了让 Argo CD 使用任何给定存储库的凭证模板,必须满足以下条件:

  • 存储库必须完全未配置,或者如果已配置,则不能包含任何凭证信息(即不包含 sshPrivateKey, username, password
  • 为凭证模板配置的 URL(例如 https://github.com/argoproj)必须与存储库 URL 的前缀匹配(例如 https://github.com/argoproj/argocd-example-apps)。

匹配凭证模板 URL 前缀是根据最佳匹配结果进行的,因此最长(最佳)匹配将优先。与 v1.4 之前的配置不同,定义的顺序并不重要。

以下密钥可以有效引用凭证密钥:

  • SSH repositories
    • sshPrivateKey 用于访问存储库的 SSH 私钥
  • HTTPS repositories
    • usernamepassword指的是访问存储库的用户名和密码
    • tlsClientCertDatatlsClientCertKey 指的是存储用于访问存储库的 TLS 客户端证书 (tlsClientCertData) 和相应私钥 tlsClientCertKey
  • GitHub App repositories
    • githubAppPrivateKey 指的是用于访问存储库的 GitHub App 私钥
    • githubAppID 指的是创建的应用程序的 GitHub 应用程序 ID。
    • githubAppInstallationID 指的是创建并安装的 GitHub 应用程序的安装 ID。
    • githubAppEnterpriseBaseUrl 指的是 GitHub Enterprise 的基本 api URL(例如 https://ghe.example.com/api/v3
    • tlsClientCertDatatlsClientCertKey 指的是存储 TLS 客户端证书(tlsClientCertData)和相应的私钥 tlsClientCertKey,用于在使用自定义证书的情况下访问 GitHub Enterprise。
使用自签名 TLS 证书的存储库(或由自定义 CA 签名)

在名为 argocd-tls-certs-cm 的 ConfigMap 对象中管理用于验证存储库服务器真实性的 TLS 证书。数据部分应包含一个映射,其中存储库服务器的主机名部分(不是完整的 URL)作为密钥,PEM 格式的证书作为数据。因此,如果您连接到 URL 为 https://server.example.com/repos/my-repo 的存储库,则应使用 server.example.com 作为密钥。证书数据应该是服务器的证书(如果是自签名证书)或用于签署服务器证书的 CA 的证书。可以为每个服务器配置多个证书,例如,如果计划进行证书轮换。

如果没有为存储库服务器配置专用证书,则系统默认的信任存储将用于验证服务器的存储库。对于大多数(如果不是全部)公共 Git 存储库服务(例如 GitLab、GitHub 和 Bitbucket)以及大多数使用知名 CA 颁发的证书(包括 Let’s Encrypt 证书)的私人托管站点来说,这应该足够了。

ConfigMap 对象示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-tls-certs-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-cm
    app.kubernetes.io/part-of: argocd
data:
  server.example.com: |
    -----BEGIN CERTIFICATE-----
    MIIF1zCCA7+gAwIBAgIUQdTcSHY2Sxd3Tq/v1eIEZPCNbOowDQYJKoZIhvcNAQEL
    BQAwezELMAkGA1UEBhMCREUxFTATBgNVBAgMDExvd2VyIFNheG9ueTEQMA4GA1UE
    BwwHSGFub3ZlcjEVMBMGA1UECgwMVGVzdGluZyBDb3JwMRIwEAYDVQQLDAlUZXN0
    c3VpdGUxGDAWBgNVBAMMD2Jhci5leGFtcGxlLmNvbTAeFw0xOTA3MDgxMzU2MTda
    Fw0yMDA3MDcxMzU2MTdaMHsxCzAJBgNVBAYTAkRFMRUwEwYDVQQIDAxMb3dlciBT
    YXhvbnkxEDAOBgNVBAcMB0hhbm92ZXIxFTATBgNVBAoMDFRlc3RpbmcgQ29ycDES
    MBAGA1UECwwJVGVzdHN1aXRlMRgwFgYDVQQDDA9iYXIuZXhhbXBsZS5jb20wggIi
    MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCv4mHMdVUcafmaSHVpUM0zZWp5
    NFXfboxA4inuOkE8kZlbGSe7wiG9WqLirdr39Ts+WSAFA6oANvbzlu3JrEQ2CHPc
    CNQm6diPREFwcDPFCe/eMawbwkQAPVSHPts0UoRxnpZox5pn69ghncBR+jtvx+/u
    P6HdwW0qqTvfJnfAF1hBJ4oIk2AXiip5kkIznsAh9W6WRy6nTVCeetmIepDOGe0G
    ZJIRn/OfSz7NzKylfDCat2z3EAutyeT/5oXZoWOmGg/8T7pn/pR588GoYYKRQnp+
    YilqCPFX+az09EqqK/iHXnkdZ/Z2fCuU+9M/Zhrnlwlygl3RuVBI6xhm/ZsXtL2E
    Gxa61lNy6pyx5+hSxHEFEJshXLtioRd702VdLKxEOuYSXKeJDs1x9o6cJ75S6hko
    Ml1L4zCU+xEsMcvb1iQ2n7PZdacqhkFRUVVVmJ56th8aYyX7KNX6M9CD+kMpNm6J
    kKC1li/Iy+RI138bAvaFplajMF551kt44dSvIoJIbTr1LigudzWPqk31QaZXV/4u
    kD1n4p/XMc9HYU/was/CmQBFqmIZedTLTtK7clkuFN6wbwzdo1wmUNgnySQuMacO
    gxhHxxzRWxd24uLyk9Px+9U3BfVPaRLiOPaPoC58lyVOykjSgfpgbus7JS69fCq7
    bEH4Jatp/10zkco+UQIDAQABo1MwUTAdBgNVHQ4EFgQUjXH6PHi92y4C4hQpey86
    r6+x1ewwHwYDVR0jBBgwFoAUjXH6PHi92y4C4hQpey86r6+x1ewwDwYDVR0TAQH/
    BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAFE4SdKsX9UsLy+Z0xuHSxhTd0jfn
    Iih5mtzb8CDNO5oTw4z0aMeAvpsUvjJ/XjgxnkiRACXh7K9hsG2r+ageRWGevyvx
    CaRXFbherV1kTnZw4Y9/pgZTYVWs9jlqFOppz5sStkfjsDQ5lmPJGDii/StENAz2
    XmtiPOgfG9Upb0GAJBCuKnrU9bIcT4L20gd2F4Y14ccyjlf8UiUi192IX6yM9OjT
    +TuXwZgqnTOq6piVgr+FTSa24qSvaXb5z/mJDLlk23npecTouLg83TNSn3R6fYQr
    d/Y9eXuUJ8U7/qTh2Ulz071AO9KzPOmleYPTx4Xty4xAtWi1QE5NHW9/Ajlv5OtO
    OnMNWIs7ssDJBsB7VFC8hcwf79jz7kC0xmQqDfw51Xhhk04kla+v+HZcFW2AO9so
    6ZdVHHQnIbJa7yQJKZ+hK49IOoBR6JgdB5kymoplLLiuqZSYTcwSBZ72FYTm3iAr
    jzvt1hxpxVDmXvRnkhRrIRhK4QgJL0jRmirBjDY+PYYd7bdRIjN7WNZLFsgplnS8
    9w6CwG32pRlm0c8kkiQ7FXA6BYCqOsDI8f1VGQv331OpR2Ck+FTv+L7DAmg6l37W
    +LB9LGh4OAp68ImTjqf6ioGKG0RBSznwME+r4nXtT1S/qLR6ASWUS4ViWRhbRlNK
    XWyb96wrUlv+E8I=
    -----END CERTIFICATE-----

argocd-tls-certs-cm ConfigMap 将作为卷(volume)挂载在 argocd-serverargocd-repo-server 的 pod 中的挂载路径 /app/config/tls 上。它将在挂载路径目录中为每个数据密钥创建文件,因此上述示例将保留文件 /app/config/tls/server.example.com,其中包含证书数据。ConfigMap 中的更改可能需要一段时间才能反映在 pod 中,具体取决于 Kubernetes 配置。

SSH 已知主机公钥

如果您正在配置存储库以使用 SSH,Argo CD 将需要知道它们的 SSH 公钥。为了让 Argo CD 通过 SSH 连接,必须在 Argo CD 中预先配置每个存储库服务器的公钥(与 TLS 配置不同),否则与存储库的连接将失败。

可以在 argocd-ssh-known-hosts-cm ConfigMap 中管理 SSH 已知主机数据。此 ConfigMap 包含单个条目 ssh_known_hosts,其值为 SSH 服务器的公钥。该值可以从任何现有的 ssh_known_hosts 文件中填写,也可以从 ssh-keyscan 实用程序(它是 OpenSSH 客户端包的一部分)的输出中填写。基本格式为 <server_name> <keytype> <base64-encoded_key>,每行一个条目。

以下是运行 ssh-keyscan 的示例:

$ for host in bitbucket.org github.com gitlab.com ssh.dev.azure.com vs-ssh.visualstudio.com ; do ssh-keyscan $host 2> /dev/null ; done
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H

下面是使用上面的 ssh-keyscan 输出的示例 ConfigMap 对象:

apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app.kubernetes.io/name: argocd-ssh-known-hosts-cm
    app.kubernetes.io/part-of: argocd
  name: argocd-ssh-known-hosts-cm
data:
  ssh_known_hosts: |
    # This file was automatically generated by hack/update-ssh-known-hosts.sh. DO NOT EDIT
    [ssh.github.com]:443 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
    [ssh.github.com]:443 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
    [ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
    bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE=
    bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO
    bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
    github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
    github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
    github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
    gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
    gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
    gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
    ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
    vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H

argocd-ssh-known-hosts-cm ConfigMap 将作为卷(volume)安装在 argocd-serverargocd-repo-server 的 pod 中的安装路径 /app/config/ssh 上。它将在该目录中创建一个文件 ssh_known_hosts,其中包含 Argo CD 用于通过 SSH 连接到 Git 存储库的 SSH 已知主机数据。ConfigMap 中的更改可能需要一段时间才能反映在您的 pod 中,具体取决于您的 Kubernetes 配置。

使用代理配置存储库

可以在存储库密钥的代理字段中指定存储库的代理以及其他存储库配置。Argo CD 使用此代理访问存储库。如果自定义代理不存在,Argo CD 会在存储库服务器中查找标准代理环境变量。

带有代理的示例存储库:

apiVersion: v1
kind: Secret
metadata:
  name: private-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: https://github.com/argoproj/private-repo
  proxy: https://proxy-server-url:8888
  password: my-password
  username: my-username
遗留行为

在 Argo CD 2.0 及更早版本中,存储库作为 argocd-cm 配置图的一部分进行存储。为了向后兼容,Argo CD 仍将遵循配置图中的存储库,但这种存储库配置样式已被弃用,并且将在未来版本中移除对它的支持。

apiVersion: v1
kind: ConfigMap
data:
  repositories: |
    - url: https://github.com/argoproj/my-private-repository
      passwordSecret:
        name: my-secret
        key: password
      usernameSecret:
        name: my-secret
        key: username
  repository.credentials: |
    - url: https://github.com/argoproj
      passwordSecret:
        name: my-secret
        key: password
      usernameSecret:
        name: my-secret
        key: username
---
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
  namespace: argocd
stringData:
  password: my-password
  username: my-username

集群(Clusters)

集群凭证存储在与存储库或存储库凭证相同的机密中。每个机密都必须具有标签 argocd.argoproj.io/secret-type: cluster

密钥数据必须包含以下字段:

  • name 群集名称
  • server 集群 API 服务器 URL
  • namespaces 可选的以逗号分隔的命名空间列表,这些命名空间在该集群中可访问。如果命名空间列表不为空,则集群级别资源将被忽​​略。
  • clusterResources 可选布尔字符串(“true”或“false”)确定 Argo CD 是否可以管理此集群上的集群级资源。仅当管理命名空间列表不为空时才使用此设置。
  • project 可选字符串,用于将其指定为项目范围的集群。
  • config 以下数据结构的 JSON 表示:
# Basic authentication settings
username: string
password: string
# Bearer authentication settings
bearerToken: string
# IAM authentication configuration
awsAuthConfig:
    clusterName: string
    roleARN: string
    profile: string
# Configure external command to supply client credentials
# See https://godoc.org/k8s.io/client-go/tools/clientcmd/api#ExecConfig
execProviderConfig:
    command: string
    args: [
      string
    ]
    env: {
      key: value
    }
    apiVersion: string
    installHint: string
# Transport layer security configuration settings
tlsClientConfig:
    # Base64 encoded PEM-encoded bytes (typically read from a client certificate file).
    caData: string
    # Base64 encoded PEM-encoded bytes (typically read from a client certificate file).
    certData: string
    # Server should be accessed without verifying the TLS certificate
    insecure: boolean
    # Base64 encoded PEM-encoded bytes (typically read from a client certificate key file).
    keyData: string
    # ServerName is passed to the server for SNI and is used in the client to check server
    # certificates against. If ServerName is empty, the hostname used to contact the
    # server is used.
    serverName: string

集群凭证存储在与存储库或存储库凭证相同的密钥中。每个机密都必须具有标签 argocd.argoproj.io/secret-type: cluster

密钥数据必须包含以下字段:

  • name 集群 API 服务器 URL
  • server 集群 API 服务器 URL
  • namespaces 可选的以逗号分隔的命名空间列表,这些命名空间在该集群中可访问。如果命名空间列表不为空,则集群级别资源将被忽​​略。
  • clusterResources 可选布尔字符串(truefalse)确定 Argo CD 是否可以管理此集群上的集群级资源。仅当管理命名空间列表不为空时才使用此设置。
  • project 可选字符串,用于将其指定为项目范围的集群。
  • config 以下数据结构的 JSON 表示:
# Basic authentication settings
username: string
password: string
# Bearer authentication settings
bearerToken: string
# IAM authentication configuration
awsAuthConfig:
    clusterName: string
    roleARN: string
    profile: string
# Configure external command to supply client credentials
# See https://godoc.org/k8s.io/client-go/tools/clientcmd/api#ExecConfig
execProviderConfig:
    command: string
    args: [
      string
    ]
    env: {
      key: value
    }
    apiVersion: string
    installHint: string
# Transport layer security configuration settings
tlsClientConfig:
    # Base64 encoded PEM-encoded bytes (typically read from a client certificate file).
    caData: string
    # Base64 encoded PEM-encoded bytes (typically read from a client certificate file).
    certData: string
    # Server should be accessed without verifying the TLS certificate
    insecure: boolean
    # Base64 encoded PEM-encoded bytes (typically read from a client certificate key file).
    keyData: string
    # ServerName is passed to the server for SNI and is used in the client to check server
    # certificates against. If ServerName is empty, the hostname used to contact the
    # server is used.
    serverName: string

请注意,如果指定在 execProviderConfig 下运行的命令,则该命令必须在 Argo CD 映像中可用。请参阅 BYOI(构建您自己的映像)

集群密钥示例:

apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: mycluster.example.com
  server: https://mycluster.example.com
  config: |
    {
      "bearerToken": "<authentication token>",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }
    }
EKS

使用 argocd-k8s-auth 和 IRSA 的 EKS 集群密钥示例:

apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: "mycluster.example.com"
  server: "https://mycluster.example.com"
  config: |
    {
      "awsAuthConfig": {
        "clusterName": "my-eks-cluster-name",
        "roleARN": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<IAM_ROLE_NAME>"
      },
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }        
    }

请注意,应该在 EKS 集群上启用 IRSA,创建一个适当的 IAM 角色,允许它承担其他 IAM 角色(Argo CD 需要承担的任何角色 ARN),并有一个承担角色策略,允许 argocd-application-controller 和 argocd-server pod 通过 OIDC 承担上述角色。

<arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ARGO_CD_MANAGEMENT_IAM_ROLE_NAME> 的信任关系配置示例,这是 Argo CD 通过 IAM 执行操作所必需的。确保集群已为其配置 IAM OIDC 提供程序

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/oidc.eks.<AWS_REGION>.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "oidc.eks.<AWS_REGION>.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": ["system:serviceaccount:argocd:argocd-application-controller", "system:serviceaccount:argocd:argocd-server"],
                    "oidc.eks.<AWS_REGION>.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"
                }
            }
        }
    ]
}

Argo CD 管理角色还需要被允许承担其他角色,在本例中,我们希望它承担 arn:aws:iam::<AWS_ACCOUNT_ID>:role/<IAM_ROLE_NAME>,以便它可以管理映射到该角色的集群。这可以扩展为允许承担多个角色,可以作为角色 ARN 的显式数组,也可以在适当的情况下使用 *

{
    "Version" : "2012-10-17",
    "Statement" : {
      "Effect" : "Allow",
      "Action" : "sts:AssumeRole",
      "Resource" : [
        "<arn:aws:iam::<AWS_ACCOUNT_ID>:role/<IAM_ROLE_NAME>"
      ]
    }
  }

argocd-application-controller 和 argocd-server 的示例服务帐户配置。

一旦在服务账户上设置了注释,就需要重新启动应用程序控制器和服务器容器。

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: "<arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ARGO_CD_MANAGEMENT_IAM_ROLE_NAME>"
  name: argocd-application-controller
---
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: "<arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ARGO_CD_MANAGEMENT_IAM_ROLE_NAME>"
  name: argocd-server

反过来,每个托管集群的 roleARN 都需要添加到每个相应集群的 aws-auth 配置映射中(请参阅启用对集群的 IAM 主体访问),并且具有允许它由 Argo CD pod 角色承担的承担角色策略。

假设由 Argo CD 管理的集群的角色策略示例:

{
    "Version" : "2012-10-17",
    "Statement" : {
      "Effect" : "Allow",
      "Action" : "sts:AssumeRole",
      "Principal" : {
        "AWS" : "<arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ARGO_CD_MANAGEMENT_IAM_ROLE_NAME>"
      }
    }
  }

由 Argo CD 管理的集群的示例 kube-system/aws-auth 配置映射:

apiVersion: v1
data:
  # Other groups and accounts omitted for brevity. Ensure that no other rolearns and/or groups are inadvertently removed, 
  # or you risk borking access to your cluster.
  #
  # The group name is a RoleBinding which you use to map to a [Cluster]Role. See https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-binding-examples  
  mapRoles: |
    - "groups":
      - "<GROUP-NAME-IN-K8S-RBAC>"
      "rolearn": "<arn:aws:iam::<AWS_ACCOUNT_ID>:role/<IAM_ROLE_NAME>"
      "username": "<some-username>"
替代的 EKS 身份验证方法

在某些情况下,可能无法使用 IRSA,例如当 Argo CD 集群在不同云提供商的平台上运行时。在这种情况下,有两个选项:

  1. 使用 execProviderConfig 调用 AWS 身份验证机制,该机制允许注入环境变量以提供凭据
  2. 利用 Argo CD 版本 2.10 中提供的新 AWS 配置文件选项

这两个选项都需要涉及 IAM 和 aws-auth 配置映射(如上所述)的步骤,以便为主体提供对集群的访问权限。

  1. 使用 EXECPROVIDERCONFIG 与环境变量
---
apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: mycluster
  server: https://mycluster.example.com
  namespaces: "my,managed,namespaces"
  clusterResources: "true"
  config: |
    {
      "execProviderConfig": {
        "command": "argocd-k8s-auth",
        "args": ["aws", "--cluster-name", "my-eks-cluster"],
        "apiVersion": "client.authentication.k8s.io/v1beta1",
        "env": {
          "AWS_REGION": "xx-east-1",
          "AWS_ACCESS_KEY_ID": "{{ .aws_key_id }}",
          "AWS_SECRET_ACCESS_KEY": "{{ .aws_key_secret }}",
          "AWS_SESSION_TOKEN": "{{ .aws_token }}"
        }
      },
      "tlsClientConfig": {
        "insecure": false,
        "caData": "{{ .cluster_cert }}"
      }
    }

此示例假定角色附加到已提供的凭证,如果不是这种情况,则可以将角色附加到 args 部分,如下所示:

...
    "args": ["aws", "--cluster-name", "my-eks-cluster", "--roleARN", "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<IAM_ROLE_NAME>"],
...

该构造可与外部密钥操作员之类的东西结合使用,以避免以纯文本形式存储密钥,并且有助于为密钥轮换提供基础。

  1. 使用 AWS 配置文件进行身份验证
    在版本 2.10 中添加的使用配置文件的选项提供了一种提供凭证的方法,同时仍然使用标准 Argo CD EKS 集群声明以及指向 AWS 凭证文件的附加命令标志:
apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: "mycluster.com"
  server: "https://mycluster.com"
  config: |
    {
      "awsAuthConfig": {
        "clusterName": "my-eks-cluster-name",
        "roleARN": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<IAM_ROLE_NAME>",
        "profile": "/mount/path/to/my-profile-file"
      },
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }        
    }

这将指示 ArgoCD 读取所提供路径的文件并使用其中定义的凭据向 AWS 进行身份验证。必须安装配置文件才能使其正常工作。例如,可以在基于 Helm 的 ArgoCD 部署中定义以下值:

controller:
  extraVolumes:
    - name: my-profile-volume
      secret:
        secretName: my-aws-profile
        items:
          - key: my-profile-file
            path: my-profile-file
  extraVolumeMounts:
    - name: my-profile-mount
      mountPath: /mount/path/to
      readOnly: true

server:
  extraVolumes:
    - name: my-profile-volume
      secret:
        secretName: my-aws-profile
        items:
          - key: my-profile-file
            path: my-profile-file
  extraVolumeMounts:
    - name: my-profile-mount
      mountPath: /mount/path/to
      readOnly: true

其中 secret 定义如下:

apiVersion: v1
kind: Secret
metadata:
  name: my-aws-profile
type: Opaque
stringData:
  my-profile-file: |
    [default]
    region = <aws_region>
    aws_access_key_id = <aws_access_key_id>
    aws_secret_access_key = <aws_secret_access_key>
    aws_session_token = <aws_session_token>

密钥挂载会按间隔更新,而不是实时更新。如果需要轮换,请确保令牌的生命周期超过挂载更新间隔,并且轮换过程不会立即使现有令牌失效

GKE

使用 argocd-k8s-auth 和 Workload Identity 的 GKE 集群密钥示例:

apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: mycluster.example.com
  server: https://mycluster.example.com
  config: |
    {
      "execProviderConfig": {
        "command": "argocd-k8s-auth",
        "args": ["gcp"],
        "apiVersion": "client.authentication.k8s.io/v1beta1"
      },
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }
    }

请注意,必须在 GKE 集群上启用 Workload Identity,创建具有适当 IAM 角色的 GCP 服务帐户,并将其绑定到 argocd-application-controller 和 argocd-server 的 Kubernetes 服务帐户(在 UI 上显示 Pod 日志)。请参阅使用 Workload Identity 和向 Kubernetes API 服务器进行身份验证

AKS

使用 argocd-k8s-auth 和 kubelogin 的 Azure 群集密钥示例。argocd-k8s-auth execProviderConfig 的选项 azure 封装了 kubelogin 的 get-token 命令。根据所需的身份验证流程(devicecode、spn、ropc、msi、azurecli、workloadidentity),使用此值设置环境变量 AAD_LOGIN_METHOD。根据所需的身份验证流程设置其他适当的环境变量。

Variable NameDescription
AAD_LOGIN_METHODOne of devicecode, spn, ropc, msi, azurecli, or workloadidentity
AAD_SERVICE_PRINCIPAL_CLIENT_CERTIFICATEAAD client cert in pfx. Used in spn login
AAD_SERVICE_PRINCIPAL_CLIENT_IDAAD client application ID
AAD_SERVICE_PRINCIPAL_CLIENT_SECRETAAD client application secret
AAD_USER_PRINCIPAL_NAMEUsed in the ropc flow
AAD_USER_PRINCIPAL_PASSWORDUsed in the ropc flow
AZURE_TENANT_IDThe AAD tenant ID.
AZURE_AUTHORITY_HOSTUsed in the WorkloadIdentityLogin flow
AZURE_FEDERATED_TOKEN_FILEUsed in the WorkloadIdentityLogin flow
AZURE_CLIENT_IDUsed in the WorkloadIdentityLogin flow

除了上述环境变量外,argocd-k8s-auth 还接受两个额外的环境变量来设置 AAD 环境,以及设置 AAD 服务器应用程序 ID。如果未指定,AAD 服务器应用程序 ID 将默认为 6dae42f8-4368-4678-94ff-3960e28e3630。详情请参阅此处

Variable NameDescription
AAD_ENVIRONMENT_NAMEThe azure environment to use, default of AzurePublicCloud
AAD_SERVER_APPLICATION_IDThe optional AAD server application ID, defaults to 6dae42f8-4368-4678-94ff-3960e28e3630

这是使用联合工作负载登录流程的示例。联合令牌文件需要作为密钥挂载到 argoCD 中,以便可以在流程中使用。令牌文件的位置需要在环境变量 AZURE_FEDERATED_TOKEN_FILE 中设置。

如果你的 AKS 集群使用 Azure Workload Identity 项目中的 Mutating Admission Webhook,请按照以下步骤启用 argocd-application-controllerargocd-server pods 以使用联合标识:

  1. 给 Pod 贴上标签:将 azure.workload.identity/use: "true" 标签添加到 argocd-application-controllerargocd-server Pods。
  2. 创建联合身份凭证:为 argocd-application-controllerargocd-server 服务帐户生成 Azure 联合身份凭据。有关详细说明,请参阅联合身份凭据文档
  3. 设置 AZURE_CLIENT_ID:更新集群密钥中的 AZURE_CLIENT_ID 以匹配新创建的联合身份凭证的客户端 ID。
apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: mycluster.example.com
  server: https://mycluster.example.com
  config: |
    {
      "execProviderConfig": {
        "command": "argocd-k8s-auth",
        "env": {
          "AAD_ENVIRONMENT_NAME": "AzurePublicCloud",
          "AZURE_CLIENT_ID": "fill in client id",
          "AZURE_TENANT_ID": "fill in tenant id", # optional, injected by workload identity mutating admission webhook if enabled
          "AZURE_FEDERATED_TOKEN_FILE": "/opt/path/to/federated_file.json", # optional, injected by workload identity mutating admission webhook if enabled
          "AZURE_AUTHORITY_HOST": "https://login.microsoftonline.com/", # optional, injected by workload identity mutating admission webhook if enabled
          "AAD_LOGIN_METHOD": "workloadidentity"
        },
        "args": ["azure"],
        "apiVersion": "client.authentication.k8s.io/v1beta1"
      },
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }
    }

这是使用 spn(服务主体名称)流的示例。

apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: mycluster.example.com
  server: https://mycluster.example.com
  config: |
    {
      "execProviderConfig": {
        "command": "argocd-k8s-auth",
        "env": {
          "AAD_ENVIRONMENT_NAME": "AzurePublicCloud",
          "AAD_SERVICE_PRINCIPAL_CLIENT_SECRET": "fill in your service principal client secret",
          "AZURE_TENANT_ID": "fill in tenant id",
          "AAD_SERVICE_PRINCIPAL_CLIENT_ID": "fill in your service principal client id",
          "AAD_LOGIN_METHOD": "spn"
        },
        "args": ["azure"],
        "apiVersion": "client.authentication.k8s.io/v1beta1"
      },
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }
    }

Helm Chart 存储库

非标准 Helm Chart 存储库必须明确注册。每个存储库必须具有 url、typename 字段。对于私有 Helm 存储库,可能需要使用 usernamepasswordtlsClientCertDatatlsClientCertKey 字段配置访问凭据和 HTTPS 设置。

例子:

apiVersion: v1
kind: Secret
metadata:
  name: istio
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  name: istio.io
  url: https://storage.googleapis.com/istio-prerelease/daily-build/master-latest-daily/charts
  type: helm
---
apiVersion: v1
kind: Secret
metadata:
  name: argo-helm
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  name: argo
  url: https://argoproj.github.io/argo-helm
  type: helm
  username: my-username
  password: my-password
  tlsClientCertData: ...
  tlsClientCertKey: ...
资源排除/包含

可以将资源排除在发现和同步之外,这样 Argo CD 就无法识别它们。例如,apiGroup/kind events.k8s.io/*metrics.k8s.io/*coordination.k8s.io/Lease""/Endpoints 始终被排除在外。用例:

  • 遇到临时问题,并且希望排除有问题的资源。
  • 有很多种资源会影响 Argo CD 的性能。
  • 限制 Argo CD 对某些资源(例如密钥)的访问。请参阅 security.md#cluster-rbac

要配置此功能,请编辑 argocd-cm 配置图:

kubectl edit configmap argocd-cm -n argocd

添加 resource.exclusions,例如:

apiVersion: v1
data:
  resource.exclusions: |
    - apiGroups:
      - "*"
      kinds:
      - "*"
      clusters:
      - https://192.168.0.20
kind: ConfigMap

resource.exclusions 节点是对象列表。每个对象可以具有:

  • apiGroups 与 API 组匹配的全局列表
  • kinds 要匹配的种类列表。可以使用*来匹配所有
  • clusters 与集群匹配的全局列表

如果三者全部匹配,则忽略该资源。

除了排除之外,您还可以使用 resource.inclusions 设置配置包含的资源列表。默认情况下,包含所有资源group/kindsresource.inclusions 设置允许自定义包含的group/kinds列表:

apiVersion: v1
data:
  resource.inclusions: |
    - apiGroups:
      - "*"
      kinds:
      - Deployment
      clusters:
      - https://192.168.0.20
kind: ConfigMap

resource.inclusionsresource.exclusions 可以一起使用。最终的资源列表包括 resource.inclusions 中指定的group/kinds减去 resource.exclusions 设置中指定的group/kinds

笔记:

  • 在 YAML 中引用全局变量以避免解析错误。
  • 无效的全局变量会导致整个规则被忽略。
  • 如果添加与现有资源匹配的规则,这些资源将在界面中显示为 OutOfSync
控制器自动限制RBAC

可以仅使用控制器 RBAC 来限制 Argocd 控制器发现/同步特定资源,而无需手动配置资源排除。可以通过在 argocd cm 中设置 resource.respectRBAC 键来启用此功能,设置后,控制器将自动停止监视它无权列出/访问的资源。
resource.respectRBAC 的可能值包括:

  • strict:此设置检查控制器发出的列表调用是否被禁止/未经授权,如果是,它将通过对资源进行 SelfSubjectAccessReview 调用来交叉检查权限。
  • normal:这将仅检查列表调用响应是否被禁止/未经授权,并跳过 SelfSubjectAccessReview 调用,以尽量减少任何额外的 api 服务器调用。
  • unset/empty(默认):这将禁用该功能,控制器将继续监视所有资源。

可以接受增加 kube api-server 调用次数的用户可以选择strict选项,而担心更高 api 调用次数并愿意在准确性上做出妥协的用户可以选择normal选项。

笔记:

  • 当设置为使用strict模式时,控制器必须具有 RBAC 权限才能创建 SelfSubjectAccessReview 资源
  • elfSubjectAccessReview 请求仅针对list动词进行,假定如果允许列出资源,则控制器也可以使用所有其他权限。

resource.respectRBAC 设置为 strict 的示例 argocd cm

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
data:
  resource.respectRBAC: "strict"
资源自定义标签

使用 resource.customLabels(逗号分隔的字符串)配置的自定义标签将显示在 UI 中(对于定义它们的任何资源)。

SSO & RBAC
  • SSO 配置详细信息:SSO
  • RBAC 配置详情:RBAC
使用 Argo CD 管理 Argo CD

Argo CD 能够自我管理,因为所有设置都由 Kubernetes 清单表示。建议的方法是创建基于 Kustomize 的应用程序,该应用程序使用来自 https://github.com/argoproj/argo-cd 的基本 Argo CD 清单(manifests),并在其上应用所需的更改。

kustomization.yaml 示例:

# additional resources like ingress rules, cluster and repository secrets.
resources:
- github.com/argoproj/argo-cd//manifests/cluster-install?ref=stable
- clusters-secrets.yaml
- repos-secrets.yaml

# changes to config maps
patches:
- path: overlays/argo-cd-cm.yaml

自我管理的 Argo CD 配置的实时示例可在 https://cd.apps.argoproj.io 上找到,配置存储在 argoproj/argoproj-deployments 中。

需要使用 GitHub 帐户登录才能访问 https://cd.apps.argoproj.io

7.6.任意名称空间中的应用程序

启用此功能前请仔细阅读本文档。配置错误可能会导致潜在的安全问题。

介绍

从 2.5 版开始,Argo CD 支持在控制平面命名空间(通常是 argocd)以外的命名空间中管理Application资源,但必须明确启用并适当配置此功能。
Argo CD 管理员可以定义一组特定的命名空间,可以在其中创建、更新和协调Application资源。但是,这些附加命名空间中的应用程序将只被允许使用 Argo CD 管理员配置的某些 AppProject。这允许普通 Argo CD 用户(例如应用程序团队)使用诸如声明式管理应用程序资源、实现 app-of-apps 等模式,而不会因使用超出授予应用程序团队的权限的其他 AppProjects 而面临特权升级的风险。

为了启用此功能,Argo CD 管理员需要执行一些手动步骤。

在任何命名空间中采用应用程序的另一个优点是允许最终用户在 Argo CD 应用程序正在运行的命名空间中为其 Argo CD 应用程序配置通知。有关更多信息,请参阅基于通知命名空间的配置页面

先决条件

群集范围内的 Argo CD 安装

仅当 Argo CD 作为集群范围实例安装时,才能启用和使用此功能,因此它有权列出和操作集群范围内的资源。它不适用于以命名空间范围模式安装的 Argo CD。

选择机资源跟踪方法

此外,虽然从技术上来说没有必要,但强烈建议您将应用程序跟踪方法从默认label设置切换为annotationannotation+label。这样做的原因是,应用程序名称将是命名空间名称和Application名称的组合,这很容易超过对标签值施加的 63 个字符的长度限制。注释的长度限制明显更大。
要启用基于注释的资源跟踪,请参阅有关资源跟踪方法的文档

实现细节

概述

为了在 Argo CD 的控制平面命名空间之外管理和协调应用程序,必须满足两个先决条件:

  1. 必须使用 --application-namespaces 参数为 argocd-application-controllerargocd-server 工作负载明确启用应用程序的命名空间。此参数控制 Argo CD 被允许从全局获取应用程序资源的命名空间列表。任何未在此处配置的命名空间都不能从任何 AppProject 使用。

  2. Application.spec.project 字段引用的 AppProject 必须在其 .spec.sourceNamespaces 字段中列出命名空间。此设置将决定应用程序是否可以使用某个 AppProject。如果应用程序指定了不允许的 AppProject,Argo CD 将拒绝处理此应用程序。如上所述,在 .spec.sourceNamespaces 字段中配置的任何命名空间也必须全局启用。

可以像以前 argocd 命名空间中的任何其他Application一样创建和管理不同命名空间中的Applications,可以通过声明方式或通过 Argo CD API(例如使用 CLI、Web UI、REST API 等)进行创建和管理。

重新配置 Argo CD 以允许某些命名空间

1) 更改工作负载启动参数
为了启用此功能,Argo CD 管理员必须重新配置 argocd-serverargocd-application-controller 工作负载,以将 --application-namespaces 参数添加到容器的启动命令中。
--application-namespaces 参数采用逗号分隔的命名空间列表,允许应用程序进入这些命名空间。列表中的每个条目都支持 shell 样式的通配符,例如 *,因此例如条目 app-team-* 将匹配 app-team-oneapp-team-two。要启用运行 Argo CD 的集群上的所有命名空间,只需指定 *,即 --application-namespaces=*
还可以通过指定 argocd-cmd-params-cm ConfigMap 中的 application.namespaces 设置来方便地设置 argocd-serverargocd-application-controller 的启动参数并保持同步,而无需更改相应工作负载的清单。例如:

data:
  application.namespaces: app-team-one, app-team-two

将允许 app-team-oneapp-team-two 命名空间管理应用程序资源。更改 argocd-cmd-params-cm 命名空间后,需要重新启动相应的工作负载:

kubectl rollout restart -n argocd deployment argocd-server
kubectl rollout restart -n argocd statefulset argocd-application-controller

2) 调整 Kubernetes RBAC
我们决定暂时不默认扩展 argocd-server 工作负载的 Kubernetes RBAC。如果希望其他命名空间中的应用程序由 Argo CD API(即 CLI 和 UI)管理,则需要扩展 argocd-server ServiceAccount 的 Kubernetes 权限。

我们在 examples/k8s-rbac/argocd-server-applications 目录中提供了适合此目的的 ClusterRole 和 ClusterRoleBinding。对于默认的 Argo CD 安装(即安装到 argocd 命名空间),可以按原样应用它们:

kubectl apply -k examples/k8s-rbac/argocd-server-applications/

argocd-notifications-controller-rbac-clusterrole.yamlargocd-notifications-controller-rbac-clusterrolebinding.yaml 用于支持通知控制器通知所有命名空间中的应用程序。

在稍后的某个时间点,我们可能会将此集群角色作为默认安装清单的一部分。

允许 AppProject 中的其他命名空间

任何具有 Kubernetes 访问 Argo CD 控制平面命名空间(argocd)的用户,尤其是那些有权以声明方式创建或更新应用程序的用户,都被视为 Argo CD 管理员。

这可以防止非特权 Argo CD 用户在过去以声明方式创建或管理应用程序。 这些用户被限制使用 API,但要遵守 Argo CD RBAC,确保只创建允许的 AppProject 中的应用程序。

对于在 argocd 命名空间之外创建的应用程序,应用程序的 .spec.project 字段中引用的 AppProject 必须在其 .spec.sourceNamespaces 字段中包含应用程序的命名空间。

例如,考虑以下两个(不完整的)AppProject 规范:

kind: AppProject
apiVersion: argoproj.io/v1alpha1
metadata:
  name: project-one
  namespace: argocd
spec:
  sourceNamespaces:
  - namespace-one

kind: AppProject
apiVersion: argoproj.io/v1alpha1
metadata:
  name: project-two
  namespace: argocd
spec:
  sourceNamespaces:
  - namespace-two

为了让应用程序将 .spec.project 设置为 project-one,必须在命名空间 namespace-oneargocd 中创建它。同样,为了让应用程序将 .spec.project 设置为 project-two``,必须在命名空间 namespace-twoargocd` 中创建它。

如果namespace-two中的应用程序将其 .spec.project 设置为 project-one,或者namespace-one中的应用程序将其 .spec.project 设置为 project-two,则 Argo CD 会将此视为权限违规并拒绝协调该应用程序。

此外,无论 Argo CD RBAC 权限如何,Argo CD API 都会强制执行这些约束。

AppProject.spec.sourceNamespaces 字段是一个可以包含任意数量的命名空间的列表,每个条目都支持 shell 样式的通配符,以便您可以允许具有 team-one-* 等模式的命名空间。

不要在任何特权 AppProject(如默认项目)的 .spec.sourceNamespaces 字段中添加用户控制的命名空间。始终确保 AppProject 遵循授予最少所需权限的原则。切勿授予对 AppProjectargocd 命名空间的访问权限。

为了向后兼容,Argo CD 控制平面的命名空间(argocd)中的应用程序可以设置其 .spec.project 字段以引用任何 AppProject,而不管 AppProject.spec.sourceNamespaces 字段所施加的限制。

应用程序名称

对于 CLI 和 UI,应用程序现在以 <namespace>/<name> 格式引用和显示。
为了向后兼容,如果应用程序的命名空间是控制平面的命名空间(即 argocd),则在引用应用程序名称时可以省略 <namespace>。例如,应用程序名称 argocd/someappsomeapp 在语义上相同,并且在 CLI 和 UI 中引用的是同一个应用程序。

应用程序 RBAC

应用程序对象的 RBAC 语法已从 <project>/<application> 更改为 <project>/<namespace>/<application>,以适应根据要管理的应用程序的源命名空间限制访问的需要。

为了向后兼容,argocd 命名空间中的应用程序在 RBAC 策略规则中仍然可以被称为 <project>/<application>

通配符目前还不区分项目和应用程序命名空间。例如,以下 RBAC 规则将匹配属于项目 foo 的任何应用程序,无论它是在哪个命名空间中创建的:

p, somerole, applications, get, foo/*, allow

如果想要限制仅向命名空间 bar 内的项目 foo 中的应用程序授予访问权限,则需要对规则进行如下调整:

p, somerole, applications, get, foo/bar/*, allow

管理其他命名空间中的应用程序

声明式

对于应用程序的声明式管理,只需在所需的命名空间中从 YAMLJSON 清单创建应用程序即可。确保 .spec.project 字段引用允许此命名空间的 AppProject。例如,以下(不完整的)应用程序清单在命名空间 some-namespace 中创建一个应用程序:

kind: Application
apiVersion: argoproj.io/v1alpha1
metadata:
  name: some-app
  namespace: some-namespace
spec:
  project: some-project
  # ...

然后,项目 some-project 将需要在允许的源命名空间列表中指定 some-namespace,例如

kind: AppProject
apiVersion: argoproj.io/v1alpha1
metadata:
    name: some-project
    namespace: argocd
spec:
    sourceNamespaces:
    - some-namespace
使用 CLI

可以使用所有现有的 Argo CD CLI 命令来管理其他命名空间中的应用程序,就像使用 CLI 管理控制平面命名空间中的应用程序一样。
例如,要检索命名空间 bar 中名为 fooApplication,您可以使用以下 CLI 命令:

argocd app get foo/bar

同样,要管理此Application,请继续将其称为 foo/bar

# Create an application
argocd app create foo/bar ...
# Sync the application
argocd app sync foo/bar
# Delete the application
argocd app delete foo/bar
# Retrieve application's manifest
argocd app manifests foo/bar

如前所述,对于 Argo CD 的控制平面命名空间中的应用程序,可以从应用程序名称中省略命名空间。

使用 UI

与 CLI 类似,您可以在 UI 中将应用程序引用为 foo/bar

例如,要在 Web UI 中的命名空间 foo 中创建名为 bar 的应用程序,请在创建对话框的应用程序名称字段中将应用程序名称设置为 foo/bar。如果省略命名空间,则将使用控制平面的命名空间。

使用 REST API

如果使用的是 REST API,则无法将 Application 的命名空间指定为应用程序名称,而需要使用可选的 appNamespace 查询参数指定资源。例如,要使用命名空间 bar 中名为 fooApplication 资源,请求应如下所示:

GET /api/v1/applications/foo?appNamespace=bar

对于 POSTPUT 等其他操作,appNamespace 参数必须是请求的一部分。

对于控制平面命名空间中的应用程序资源,可以省略此参数。

7.7.Ingress配置

Argo CD API 服务器同时运行 gRPC 服务器(由 CLI 使用)和 HTTP/HTTPS 服务器(由 UI 使用)。这两种协议均由 argocd-server 服务对象在以下端口上公开:

  • 443 - gRPC/HTTPS
  • 80 - HTTP (redirects to HTTPS)

有多种方式可以配置 Ingress。

Ambassador

UK /æmˈbæs.ə.dər/
US /æmˈbæs.ə.dɚ/

Ambassador Edge Stack 可用作 Kubernetes 入口控制器,具有适用于 CLI 和 UI 的自动 TLS 终止和路由功能。

API 服务器应在禁用 TLS 的情况下运行。编辑 argocd-server 部署以将 --insecure 标志添加到 argocd-server 命令,或者只需在 argocd-cmd-params-cm ConfigMap 中设置 server.insecure: "true",如此处所述。鉴于 argocd CLI 在请求host标头中包含端口号,因此需要 2 个映射。

选项 1:映射 CRD 以进行基于Host的路由
apiVersion: getambassador.io/v2
kind: Mapping
metadata:
  name: argocd-server-ui
  namespace: argocd
spec:
  host: argocd.example.com
  prefix: /
  service: argocd-server:443
---
apiVersion: getambassador.io/v2
kind: Mapping
metadata:
  name: argocd-server-cli
  namespace: argocd
spec:
  # NOTE: the port must be ignored if you have strip_matching_host_port enabled on envoy
  host: argocd.example.com:443
  prefix: /
  service: argocd-server:80
  regex_headers:
    Content-Type: "^application/grpc.*$"
  grpc: true

使用 argocd CLI 登录:

argocd login <host>
选项 2:映射 CRD 以进行基于Path的路由

API 服务器必须配置为在非根路径下可用(例如 /argo-cd)。编辑 argocd-server 部署以将 --rootpath=/argo-cd 标志添加到 argocd-server 命令。

apiVersion: getambassador.io/v2
kind: Mapping
metadata:
  name: argocd-server
  namespace: argocd
spec:
  prefix: /argo-cd
  rewrite: /argo-cd
  service: argocd-server:443

对于非根路径,使用额外的 --grpc-web-root-path 标志通过 argocd CLI 登录。

argocd login <host>:<port> --grpc-web-root-path /argo-cd

Contour

UK /ˈkɒn.tɔːr/
US /ˈkɑːn.tʊr/

Contour 入口控制器可以在边缘终止 TLS 入口流量。

Argo CD API 服务器应在禁用 TLS 的情况下运行。编辑 argocd-server 部署以将 --insecure 标志添加到 argocd-server 容器命令,或者只需在 argocd-cmd-params-cm ConfigMap 中设置 server.insecure: "true",如此处所述。

还可以通过部署两个 Contour 实例来提供仅限内部的入口路径和仅限外部的入口路径:一个位于私有子网 LoadBalancer 服务后面,另一个位于公共子网 LoadBalancer 服务后面。私有 Contour 部署将拾取带有 kubernetes.io/ingress.class: contour-internal 注释的入口,而公共 Contour 部署将拾取带有 kubernetes.io/ingress.class: contour-external 注释的入口。

这提供了私下部署 Argo CD UI 的机会,但仍允许 SSO 回调成功。

具有多个Ingress对象和 BYO 证书的个人 Argo CD UI

由于 Contour Ingress 每个 Ingress 对象仅支持一种协议,因此请定义三个 Ingress 对象。一个用于私有 HTTP/HTTPS,一个用于私有 gRPC,一个用于公共 HTTPS SSO 回调。

内部 HTTP/HTTPS Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-http
  annotations:
    kubernetes.io/ingress.class: contour-internal
    ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  rules:
  - host: internal.path.to.argocd.io
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: http
  tls:
  - hosts:
    - internal.path.to.argocd.io
    secretName: your-certificate-name

内部 gRPC Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-grpc
  annotations:
    kubernetes.io/ingress.class: contour-internal
spec:
  rules:
  - host: grpc-internal.path.to.argocd.io
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https
  tls:
  - hosts:
    - grpc-internal.path.to.argocd.io
    secretName: your-certificate-name

外部 HTTPS SSO 回调Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-external-callback-http
  annotations:
    kubernetes.io/ingress.class: contour-external
    ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  rules:
  - host: external.path.to.argocd.io
    http:
      paths:
      - path: /api/dex/callback
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: http
  tls:
  - hosts:
    - external.path.to.argocd.io
    secretName: your-certificate-name

argocd-server 服务需要标注 projectcontour.io/upstream-protocol.h2c: "https,443" 来连接 gRPC 协议代理。

然后应在禁用 TLS 的情况下运行 API 服务器。编辑 argocd-server 部署以将 --insecure 标志添加到 argocd-server 命令,或者只需在 argocd-cmd-params-cm ConfigMap 中设置 server.insecure: "true",如此处所述。

Contour httpproxy CRD:
使用Contour httpproxy CRD 允许您对 GRPC 和 REST api 使用相同的主机名。

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: argocd-server
  namespace: argocd
spec:
  ingressClassName: contour
  virtualhost:
    fqdn: path.to.argocd.io
    tls:
      secretName: wildcard-tls
  routes:
    - conditions:
        - prefix: /
        - header:
            name: Content-Type
            contains: application/grpc
      services:
        - name: argocd-server
          port: 80
          protocol: h2c # allows for unencrypted http2 connections
      timeoutPolicy:
        response: 1h
        idle: 600s
        idleConnection: 600s
    - conditions:
        - prefix: /
      services:
        - name: argocd-server
          port: 80

kubernetes/ingress-nginx

选项 1:SSL 直通

Argo CD 在同一端口(443)上提供多种协议(gRPC/HTTPS),这在尝试为 argocd-service 定义单个 nginx ingress 对象和规则时带来了挑战,因为 nginx.ingress.kubernetes.io/backend-protocol 标注仅接受后端协议的单个值(例如 HTTP、HTTPS、GRPC、GRPCS)。

为了使用单个入口规则和主机名公开 Argo CD API 服务器,必须使用 nginx.ingress.kubernetes.io/ssl-passthrough 标注来传递 TLS 连接并在 Argo CD API 服务器上终止 TLS。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: argocd.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https

上述规则在 Argo CD API 服务器上终止 TLS,该服务器检测正在使用的协议并做出适当的响应。请注意,nginx.ingress.kubernetes.io/ssl-passthrough 注释要求将 --enable-ssl-passthrough 标志添加到 nginx-ingress-controller 的命令行参数中。

SSL-Passthrough with cert-manager and Let’s Encrypt

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    # If you encounter a redirect loop or are getting a 307 response code
    # then you need to force the nginx ingress to connect to the backend using HTTPS.
    #
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  ingressClassName: nginx
  rules:
  - host: argocd.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https
  tls:
  - hosts:
    - argocd.example.com
    secretName: argocd-server-tls # as expected by argocd-server
选项 2:Ingress控制器上的 SSL 终止

另一种方法是在 Ingress 处执行 SSL 终止。由于 ingress-nginx Ingress 每个 Ingress 对象仅支持一种协议,因此需要使用 nginx.ingress.kubernetes.io/backend-protocol 标注定义两个 Ingress 对象,一个用于 HTTP/HTTPS,另一个用于 gRPC

每个Ingress将用于不同的域(argocd.example.comgrpc.argocd.example.com)。这要求Ingress资源使用不同的 TLS secretName 以避免意外行为。

HTTP/HTTPS Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-http-ingress
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: http
    host: argocd.example.com
  tls:
  - hosts:
    - argocd.example.com
    secretName: argocd-ingress-http

gRPC Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-grpc-ingress
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https
    host: grpc.argocd.example.com
  tls:
  - hosts:
    - grpc.argocd.example.com
    secretName: argocd-ingress-grpc

然后应在禁用 TLS 的情况下运行 API 服务器。编辑 argocd-server 部署以将 --insecure 标志添加到 argocd-server 命令,或者只需在 argocd-cmd-params-cm ConfigMap 中设置 server.insecure: "true",如此处所述。

这种方法的明显缺点是,该技术需要为 API 服务器提供两个单独的主机名 - 一个用于 gRPC,另一个用于 HTTP/HTTPS。但是,它允许在入口控制器处进行 TLS 终止。

Traefik (v2.2)

UK /ˈtræf.ɪk/
US /ˈtræf.ɪk/

Traefik 可用作边缘路由器并在同一部署中提供 TLS 终止。

目前,它比 NGINX 具有优势,因为它可以终止同一端口上的 TCP 和 HTTP 连接,这意味着您不需要多个主机或路径。

API 服务器应在禁用 TLS 的情况下运行。编辑 argocd-server 部署以将 --insecure 标志添加到 argocd-server 命令或按照此处所述在 argocd-cmd-params-cm ConfigMap 中设置 server.insecure: "true"

IngressRoute CRD
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: argocd-server
  namespace: argocd
spec:
  entryPoints:
    - websecure
  routes:
    - kind: Rule
      match: Host(`argocd.example.com`)
      priority: 10
      services:
        - name: argocd-server
          port: 80
    - kind: Rule
      match: Host(`argocd.example.com`) && Headers(`Content-Type`, `application/grpc`)
      priority: 11
      services:
        - name: argocd-server
          port: 80
          scheme: h2c
  tls:
    certResolver: default

AWS 应用程序负载均衡器 (ALB) 和经典 ELB (HTTP 模式)

AWS ALB 可用作 UI 和 gRPC 流量的 L7 负载均衡器,而 Classic ELB 和 NLB 可用作两者的 L4 负载均衡器。

使用 ALB 时,需要为 argocd-server 创建第二个服务。这是必要的,因为我们需要告诉 ALB 将 GRPC 流量发送到与 UI 流量不同的目标组,因为后端协议是 HTTP2 而不是 HTTP1

apiVersion: v1
kind: Service
metadata:
  annotations:
    alb.ingress.kubernetes.io/backend-protocol-version: HTTP2 #This tells AWS to send traffic from the ALB using HTTP2. Can use GRPC as well if you want to leverage GRPC specific features
  labels:
    app: argogrpc
  name: argogrpc
  namespace: argocd
spec:
  ports:
  - name: "443"
    port: 443
    protocol: TCP
    targetPort: 8080
  selector:
    app.kubernetes.io/name: argocd-server
  sessionAffinity: None
  type: NodePort

创建此服务后,可以使用 alb.ingress.kubernetes.io/conditions 标注配置 Ingress,以有条件地将所有 application/grpc 流量路由到新的 HTTP2 后端,如下所示。注意:条件标注中 . 后面的值必须与希望的流量路由到的服务名称相同 - 并且将应用于具有匹配 serviceName 的任何路径。

  apiVersion: networking.k8s.io/v1
  kind: Ingress
  metadata:
    annotations:
      alb.ingress.kubernetes.io/backend-protocol: HTTPS
      # Use this annotation (which must match a service name) to route traffic to HTTP2 backends.
      alb.ingress.kubernetes.io/conditions.argogrpc: |
        [{"field":"http-header","httpHeaderConfig":{"httpHeaderName": "Content-Type", "values":["application/grpc"]}}]
      alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
    name: argocd
    namespace: argocd
  spec:
    rules:
    - host: argocd.argoproj.io
      http:
        paths:
        - path: /
          backend:
            service:
              name: argogrpc
              port:
                number: 443
          pathType: Prefix
        - path: /
          backend:
            service:
              name: argocd-server
              port:
                number: 443
          pathType: Prefix
    tls:
    - hosts:
      - argocd.argoproj.io

Istio

UK US /iːst’iəʊ/

可以使用以下配置将 Argo CD 置于 Istio 后面。在这里,我们将实现在 istio 后面提供 Argo CD 并在 Istio 上使用子路径

首先,我们需要确保可以使用子路径(即 /argocd)运行 Argo CD。为此,我们按原样使用了 argocd 项目中的 install.yaml

curl -kLs -o install.yaml https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

将以下文件保存为 kustomization.yml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./install.yaml

patches:
- path: ./patch.yml

并将以下行作为 patch.yml

# Use --insecure so Ingress can send traffic with HTTP
# --bashref /argocd is the subpath like https://IP/argocd
# env was added because of https://github.com/argoproj/argo-cd/issues/3572 error
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: argocd-server
spec:
 template:
   spec:
     containers:
     - args:
       - /usr/local/bin/argocd-server
       - --staticassets
       - /shared/app
       - --redis
       - argocd-redis-ha-haproxy:6379
       - --insecure
       - --basehref
       - /argocd
       - --rootpath
       - /argocd
       name: argocd-server
       env:
       - name: ARGOCD_MAX_CONCURRENT_LOGIN_REQUESTS_COUNT
         value: "0"

之后安装 Argo CD(当前目录中应该只有上面定义的 3 个 yml 文件)

kubectl apply -k ./ -n argocd --wait=true

确保为 Isito 创建 secret(在我们的例子中 secretname 是 argocd 命名空间上的 argocd-server-tls)。之后我们创建 Istio 资源

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: argocd-gateway
  namespace: argocd
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
    tls:
     httpsRedirect: true
  - port:
      number: 443
      name: https
      protocol: HTTPS
    hosts:
    - "*"
    tls:
      credentialName: argocd-server-tls
      maxProtocolVersion: TLSV1_3
      minProtocolVersion: TLSV1_2
      mode: SIMPLE
      cipherSuites:
        - ECDHE-ECDSA-AES128-GCM-SHA256
        - ECDHE-RSA-AES128-GCM-SHA256
        - ECDHE-ECDSA-AES128-SHA
        - AES128-GCM-SHA256
        - AES128-SHA
        - ECDHE-ECDSA-AES256-GCM-SHA384
        - ECDHE-RSA-AES256-GCM-SHA384
        - ECDHE-ECDSA-AES256-SHA
        - AES256-GCM-SHA384
        - AES256-SHA
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: argocd-virtualservice
  namespace: argocd
spec:
  hosts:
  - "*"
  gateways:
  - argocd-gateway
  http:
  - match:
    - uri:
        prefix: /argocd
    route:
    - destination:
        host: argocd-server
        port:
          number: 80

现在我们可以浏览 http://{{ IP }}/argocd(它将被重写为 https://{{ IP }}/argocd

带有 Kubernetes Ingress 的 Google Cloud 负载均衡器

可以利用 GKE 与 Google Cloud 的集成来仅使用 Kubernetes 对象部署负载均衡器。

为此,我们需要以下五个对象:

  • Service
  • BackendConfig
  • FrontendConfig
  • 带有 SSL 证书的密钥
  • GKE 的 Ingress

如果你需要了解这些 Google 集成的所有可用选项的详细信息,你可以查看有关配置 Ingress 功能的 Google 文档

此处忽略…

通过多层身份验证反向代理进行身份验证

Argo CD 端点可能受到一个或多个反向代理层的保护,在这种情况下,您可以通过 argocd CLI --header 参数提供额外的标头来通过这些层进行身份验证。

$ argocd login <host>:<port> --header 'x-token1:foo' --header 'x-token2:bar' # can be repeated multiple times
$ argocd login <host>:<port> --header 'x-token1:foo,x-token2:bar' # headers can also be comma separated

ArgoCD 服务器和 UI 根路径 (v1.5.3)

Argo CD 服务器和 UI 可以配置为在非根路径下可用(例如 /argo-cd)。为此,请在 argocd-server 部署命令中添加 --rootpath 标志:

spec:
  template:
    spec:
      name: argocd-server
      containers:
      - command:
        - /argocd-server
        - --repo-server
        - argocd-repo-server:8081
        - --rootpath
        - /argo-cd

注意:标志 --rootpath 会更改 API 服务器和 UI 基本 URL。示例 nginx.conf

worker_processes 1;

events { worker_connections 1024; }

http {

    sendfile on;

    server {
        listen 443;

        location /argo-cd/ {
            proxy_pass         https://localhost:8080/argo-cd/;
            proxy_redirect     off;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Host $server_name;
            # buffering should be disabled for api/v1/stream/applications to support chunked response
            proxy_buffering off;
        }
    }
}

标志 --grpc-web-root-path 用于提供非根路径(例如 /argo-cd

$ argocd login <host>:<port> --grpc-web-root-path /argo-cd
UI 基本路径

如果 Argo CD UI 在非根路径下可用(例如 /argo-cd 而不是 /),则应在 API 服务器中配置 UI 路径。要配置 UI 路径,请将 --basehref 标志添加到 argocd-server 部署命令中:

spec:
  template:
    spec:
      name: argocd-server
      containers:
      - command:
        - /argocd-server
        - --repo-server
        - argocd-repo-server:8081
        - --basehref
        - /argo-cd

注意:标志 --basehref 仅更改 UI 基本 URL。API 服务器将继续使用 / 路径,因此您需要向代理配置添加 URL 重写规则。带有 URL 重写的 nginx.conf 示例:

worker_processes 1;

events { worker_connections 1024; }

http {

    sendfile on;

    server {
        listen 443;

        location /argo-cd {
            rewrite /argo-cd/(.*) /$1  break;
            proxy_pass         https://localhost:8080;
            proxy_redirect     off;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Host $server_name;
            # buffering should be disabled for api/v1/stream/applications to support chunked response
            proxy_buffering off;
        }
    }
}

7.8.高可用性

Argo CD 基本上是无状态的。所有数据都以 Kubernetes 对象的形式保存,而这些对象又存储在 Kubernetes 的 etcd 中。Redis 仅用作一次性缓存,可能会丢失。丢失后,它将重建而不会造成服务损失。

对于希望以高可用性方式运行 Argo CD 的用户,我们提供了一组 HA 清单。这将运行更多容器,并以 HA 模式运行 Redis。

注意:由于规范中的 pod 反亲和性角色,HA 安装将需要至少三个不同的节点。此外,不支持仅 IPv6 集群。

扩展

argocd-repo-server

设置:
argocd-repo-server 负责克隆 Git 存储库、保持其更新并使用适当的工具生成清单。

  • argocd-repo-server fork/exec 配置管理工具用于生成清单。由于内存不足或操作系统线程数受限,fork 可能会失败。--parallelismlimit 标志控制同时运行的清单生成数量,并有助于避免 OOM 终止。
  • argocd-repo-server 确保在清单生成期间使用配置管理工具(例如 KustomizeHelm 或自定义插件)时存储库处于干净状态。因此,具有多个应用程序的 Git 存储库可能会影响存储库服务器性能。有关更多信息,请阅读 Monorepo 扩展注意事项
  • argocd-repo-server 将存储库克隆到 /tmp(或 TMPDIR 环境变量中指定的路径)。如果 Pod 中的存储库过多或存储库中包含大量文件,则 Pod 可能会耗尽磁盘空间。为避免此问题,请挂载持久卷。
  • argocd-repo-server 使用 git ls-remote 来解析不明确的修订版本,例如 HEAD、分支或标签名称。此操作经常发生,并且可能会失败。为避免同步失败,请使用 ARGOCD_GIT_ATTEMPTS_COUNT 环境变量重试失败的请求。
  • argocd-repo-server 每 3 分钟(默认情况下)Argo CD 检查一次应用清单的更改。Argo CD 默认假定清单仅在存储库更改时更改,因此它会缓存生成的清单(默认情况下为 24 小时)。使用 Kustomize 远程基础,或者如果 Helm 图表发生更改而未改变其版本号,则即使存储库未更改,预期的清单也可能会更改。通过减少缓存时间,您无需等待 24 小时即可获得更改。使用 --repo-cache-expiration 持续时间,我们建议在低容量环境中尝试“1h”。请记住,如果设置得太低,这将抵消缓存的好处。
  • argocd-repo-server 执行配置管理工具(例如 helmkustomize)并强制执行 90 秒超时。可以使用 ARGOCD_EXEC_TIMEOUT 环境变量更改此超时。该值应采用 Go 时间持续时间字符串格式,例如 2m30s。

指标:

  • argocd_git_request_total git 请求数。此指标提供两个标签:
    • repo :Git repo URL
    • request_typels-remotefetch
argocd-application-controller

设置:
argocd-application-controller 使用 argocd-repo-server 来获取生成的清单,并使用 Kubernetes API 服务器来获取实际的集群状态。

  • 每个控制器副本使用两个单独的队列来处理应用程序协调(毫秒)和应用程序同步(秒)。每个队列的队列处理器数量由 --status-processors(默认为 20)和 --operation-processors(默认为 10)标志控制。如果 Argo CD 实例管理的应用程序太多,请增加处理器数量。对于 1000 个应用程序,对 --status-processors 使用 50 个,对 --operation-processors 使用 25 个
  • 清单生成通常在协调期间花费最多时间。清单生成的持续时间受到限制,以确保控制器刷新队列不会溢出。如果清单生成花费的时间过长,则应用程序协调会失败,并出现上下文截止时间超出错误。作为解决方法,请增加 --repo-server-timeout-seconds 的值并考虑扩大 argocd-repo-server 部署。
  • 控制器使用 Kubernetes watch API 来维护轻量级 Kubernetes 集群缓存。这样可以避免在应用程序协调期间查询 Kubernetes,并显著提高性能。出于性能原因,控制器仅监视和缓存资源的首选版本。在协调期间,控制器可能必须将缓存的资源从首选版本转换为存储在 Git 中的资源版本。如果 kubectl convert 由于不支持转换而失败,则控制器将回退到 Kubernetes API 查询,这会减慢协调速度。在这种情况下,我们建议在 Git 中使用首选资源版本。
  • 控制器默认每 3 分钟轮询一次 Git。您可以使用 argocd-cm ConfigMap 中的 timeout.reconciliationtimeout.reconciliation.jitter 设置更改此持续时间。字段的值是持续时间字符串,例如 60 秒、1 分钟、1 小时或 1 天
  • 如果控制器管理的集群过多且占用过多内存,则可以跨多个控制器副本对集群进行分片。要启用分片,请增加 argocd-application-controller StatefulSet 中的副本数量,并在 ARGOCD_CONTROLLER_REPLICAS 环境变量中重复副本数量。下面的战略合并补丁演示了配置两个控制器副本所需的更改。
  • 默认情况下,控制器会每 10 秒更新一次集群信息,如果你的集群网络环境有问题导致更新时间过长,可以尝试修改环境变量 ARGO_CD_UPDATE_CLUSTER_INFO_TIMEOUT 增加超时时间(单位为秒)。
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: argocd-application-controller
spec:
  replicas: 2
  template:
    spec:
      containers:
      - name: argocd-application-controller
        env:
        - name: ARGOCD_CONTROLLER_REPLICAS
          value: "2"
  • 为了手动设置集群的分片数,请在创建集群时指定可选的分片属性。如果未指定,它将由应用程序控制器动态计算。
  • argocd-application-controller 的分片分布算法可以通过 --sharding-method 参数设置。支持的分片方法有:[legacy(默认)、round-robin]
    • legacy 模式使用基于 uid 的分布(非均匀)。
    • round-robin 在所有分片中使用均等分布。
    • 还可以通过在 argocd-cmd-params-cm configMap 中设置键 controller.sharding.algorithm(最好)或通过设置 ARGOCD_CONTROLLER_SHARDING_ALGORITHM 环境变量并指定相同的可能值来覆盖 --sharding-method 参数。

循环分片分布算法是一项实验性功能。已知在删除集群的某些情况下会发生重新洗牌。如果删除等级为 0 的集群,则会跨分片重新洗牌所有集群,并且可能会暂时对性能产生负面影响。

  • 可以通过修补集群密钥中的分片字段以包含分片编号来手动分配集群并强制分片,例如
apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  shard: 1
  name: mycluster.example.com
  server: https://mycluster.example.com
  config: |
    {
      "bearerToken": "<authentication token>",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }
    }
  • ARGOCD_ENABLE_GRPC_TIME_HISTOGRAM - 启用收集 RPC 性能指标的环境变量。如果需要解决性能问题,请启用它。注意:此指标的查询和存储成本都很昂贵!
  • ARGOCD_CLUSTER_CACHE_LIST_PAGE_BUFFER_SIZE - 环境变量,用于控制在同步集群缓存时针对 K8s api 服务器执行列表操作时控制器在内存中缓冲的页面数量。当集群包含大量资源且集群同步时间超过默认 etcd 压缩间隔超时时,此功能非常有用。在这种情况下,当尝试同步集群缓存时,应用程序控制器可能会抛出错误,即 continue 参数太旧而无法显示一致的列表结果。为此环境变量设置更高的值会为控制器配置更大的缓冲区,以存储异步处理的预取页面,从而增加在 etcd 压缩间隔超时到期之前提取所有页面的可能性。在最极端的情况下,操作员可以设置此值,使得 ARGOCD_CLUSTER_CACHE_LIST_PAGE_SIZE * ARGOCD_CLUSTER_CACHE_LIST_PAGE_BUFFER_SIZE 超过最大资源数量(按 k8s api 版本分组,列表操作的并行度粒度)。在这种情况下,所有资源都将缓冲在内存中 - 不会有任何 api 服务器请求被处理阻止。

指标

  • argocd_app_reconcile - 报告应用程序协调持续时间。可用于构建协调持续时间热图,以获取高级协调性能图。
  • argocd_app_k8s_request_total - 每个应用程序的 k8s 请求数。回退 Kubernetes API 查询的数量 - 有助于识别哪个应用程序具有非首选版本的资源并导致性能问题。
argocd-server

argocd-server 是无状态的,可能是最不可能引起问题的。为确保升级期间不会停机,请考虑将副本数增加到 3 个或更多,并在 ARGOCD_API_SERVER_REPLICAS 环境变量中重复该数字。下面的战略合并补丁演示了这一点。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: argocd-server
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: argocd-server
        env:
        - name: ARGOCD_API_SERVER_REPLICAS
          value: "3"

设置:

  • ARGOCD_API_SERVER_REPLICAS 环境变量用于在每个副本之间划分并发登录请求的限制(ARGOCD_MAX_CONCURRENT_LOGIN_REQUESTS_COUNT
  • ARGOCD_GRPC_MAX_SIZE_MB 环境变量允许指定服务器响应消息的最大大小(以兆字节为单位)。默认值为 200。对于管理 3000 多个应用程序的 Argo CD 实例,您可能需要增加此值。
argocd-dex-server, argocd-redis

argocd-dex-server 使用内存数据库,两个或多个实例可能会出现数据不一致的情况。argocd-redis 预先配置了仅理解总共三个 redis servers/sentinels。

Monorepo 扩展注意事项

Argo CD 存储库服务器在本地维护一个存储库克隆并将其用于应用程序清单生成。如果清单生成需要更改本地存储库克隆中的文件,则每个服务器实例只允许生成一个并发清单。如果 mono 存储库包含多个应用程序(50 个以上),此限制可能会显著降低 Argo CD 的速度。

启用并发处理

Argo CD 根据配置管理工具和应用程序设置确定清单生成是否会更改本地存储库克隆中的本地文件。如果清单生成没有副作用,则请求将并行处理而不会影响性能。以下是可能导致速度缓慢的已知情况及其解决方法:

  • 多个基于 Helm 的应用程序指向一个 Git 存储库中的同一目录:由于历史原因,Argo CD 按顺序生成 Helm 清单。要启用并行生成,请将 ARGOCD_HELM_ALLOW_CONCURRENCY=true 设置为 argocd-repo-server 部署或创建 .argocd-allow-concurrency 文件。Argo CD 的未来版本将默认启用此功能。
  • 多个基于自定义插件的应用程序:避免在清单生成期间创建临时文件,并在应用程序目录中创建 .argocd-allow-concurrency 文件,或者使用 sidecar 插件选项,该选项使用存储库的临时副本处理每个应用程序。
  • 同一存储库中的多个 Kustomize 应用程序具有参数覆盖:抱歉,目前没有解决方法。
清单路径标注

Argo CD 积极缓存生成的清单并使用存储库提交 SHA 作为缓存键。对 Git 存储库的新提交会使存储库中配置的所有应用程序的缓存失效。这可能会对具有多个应用程序的存储库产生负面影响。可以使用 webhookargocd.argoproj.io/manifest-generate-paths 应用程序 CRD 标注来解决此问题并提高性能。

argocd.argoproj.io/manifest-generate-paths 标注包含 Git 存储库中以分号分隔的路径列表,这些路径在清单生成期间使用。它将使用标注中指定的路径将上次缓存的修订与最新提交进行比较。如果没有修改的文件与 argocd.argoproj.io/manifest-generate-paths 中指定的路径匹配,则不会触发应用程序协调,现有缓存将被视为对新提交有效。

对每个应用程序使用不同存储库的安装不受此行为的影响,并且可能不会从使用这些标注中受益。

对于 webhook,比较是使用 webhook 事件负载中指定的文件进行的。

应用程序清单路径标注对 webhook 的支持取决于应用程序使用的 git 提供程序。目前仅支持基于 GitHub、GitLab 和 Gogs 的存储库。

  • 相对路径标注可能包含相对路径。在这种情况下,路径被视为相对于应用程序源中指定的路径:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
  annotations:
    # resolves to the 'guestbook' directory
    argocd.argoproj.io/manifest-generate-paths: .
spec:
  source:
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
    path: guestbook
# ...
  • 绝对路径注释值可能是以/开头的绝对路径。在这种情况下,路径被视为 Git 存储库内的绝对路径:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  annotations:
    argocd.argoproj.io/manifest-generate-paths: /guestbook
spec:
  source:
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
    path: guestbook
# ...
  • 多条路径 可以将多条路径放入注释中。路径之间必须用分号 (;) 分隔:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  annotations:
    # resolves to 'my-application' and 'shared'
    argocd.argoproj.io/manifest-generate-paths: .;../shared
spec:
  source:
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
    path: my-application
# ...
应用程序同步超时和抖动(Jitter)

Jitter 抖动
UK /ˈdʒɪt.ər/
US /ˈdʒɪt̬.ɚ/

Argo CD 对应用程序同步设置了超时时间。超时到期后,它会定期触发每个应用程序的刷新。如果应用程序数量很多,这会导致刷新队列出现峰值,并可能导致 repo-server 组件出现峰值。为了避免这种情况,您可以为同步超时设置抖动,这将分散刷新时间,并让 repo-server有时间跟上。

抖动是可以添加到同步超时的最大持续时间,因此如果同步超时为 5 分钟而抖动为 1 分钟,则实际超时将在 5 到 6 分钟之间。

要配置抖动,可以设置以下环境变量:

  • ARGOCD_RECONCILIATION_JITTER - 应用于同步超时的抖动。当值为 0 时禁用。默认为 0。

速率限制应用程序协调

为了防止由于应用程序行为不当或其他环境特定因素导致控制器资源使用率过高或同步循环,我们可以在应用程序控制器使用的工作队列上配置速率限制。可以配置两种类型的速率限制:

  • 全局速率限制
  • 每项费率限制

最终的速率限制器使用两者的组合,并将最终的退避计算为max(globalBackoff, perItemBackoff)

全局速率限制

默认情况下,此功能处于禁用状态,它是一个简单的基于存储桶的速率限制器,用于限制每秒可以排队的项目数量。这对于防止大量应用程序同时排队很有用。

要配置存储桶限制器,可以设置以下环境变量:

  • WORKQUEUE_BUCKET_SIZE - 一次突发中可以排队的项目数。默认为 500
  • WORKQUEUE_BUCKET_QPS - 每秒可排队的项目数。默认为 MaxFloat64,禁用限制器。
每项费率限制

默认情况下,这将返回固定的基本延迟/退避值(delay/backoff),但可以配置为返回指数值。每个项目速率限制器限制特定项目可以排队的次数。这是基于指数退避的,如果项目在短时间内多次排队,则项目的退避时间会不断呈指数增加,但如果自上次将项目排队以来已过了配置的冷却期,则退避会自动重置。

要配置每个项目限制器,可以设置以下环境变量:

  • WORKQUEUE_FAILURE_COOLDOWN_NS:冷却时间(以纳秒为单位),一旦某个项目的冷却时间过去,退避就会重置。如果设置为 0(默认值),则禁用指数退避,例如值:10 * 10^9 (=10s)
  • WORKQUEUE_BASE_DELAY_NS :基本延迟(以纳秒为单位),这是指数退避公式中使用的初始退避。默认为 1000(=1μs)
  • WORKQUEUE_MAX_DELAY_NS :最大延迟(以纳秒为单位),这是最大退避限制。默认为 3 * 10^9(=3 秒)
  • WORKQUEUE_BACKOFF_FACTOR :退避因子,这是每次重试增加退避的因子。默认为 1.5

用于计算项目退避时间的公式,其中 numRequeue 是该项目已排队的次数,lastRequeueTime 是该项目上次排队的时间:

  • WORKQUEUE_FAILURE_COOLDOWN_NS != 0 时:
backoff = time.Since(lastRequeueTime) >= WORKQUEUE_FAILURE_COOLDOWN_NS ?
          WORKQUEUE_BASE_DELAY_NS :
          min(
              WORKQUEUE_MAX_DELAY_NS,
              WORKQUEUE_BASE_DELAY_NS * WORKQUEUE_BACKOFF_FACTOR ^ (numRequeue)
              )
  • WORKQUEUE_FAILURE_COOLDOWN_NS == 0 时:
backoff = WORKQUEUE_BASE_DELAY_NS

HTTP 请求重试策略

在网络不稳定或服务器出现瞬时错误的情况下,重试策略通过自动重新发送失败的请求来确保 HTTP 通信的稳健性。它结合使用最大重试次数和退避间隔来防止服务器过载或网络崩溃。

配置重试

可以使用以下环境变量来微调重试逻辑:

  • ARGOCD_K8SCLIENT_RETRY_MAX - 每个请求的最大重试次数。达到此次数后,请求将被丢弃。默认为 0(不重试)。
  • ARGOCD_K8SCLIENT_RETRY_BASE_BACKOFF - 第一次重试的初始退避延迟(以毫秒为单位)。后续重试将使此退避时间加倍,直至达到最大阈值。默认为 100 毫秒
退避策略

所采用的退避策略是简单的无抖动指数退避。退避时间随着每次重试而呈指数增加,直到达到最大退避持续时间。
退避时间的计算公式为:

backoff = min(retryWaitMax, baseRetryBackoff * (2 ^ retryAttempt))

其中 retryAttempt 从 0 开始,每次后续重试增加 1。

最长等待时间

退避时间存在上限,以防止重试之间等待时间过长。此上限定义为:

  • retryWaitMax - 重试前等待的最大时长。这可确保重试在合理的时间范围内进行。默认为 10 秒
不可重审的条件

并非所有 HTTP 响应都符合重试条件。以下情况不会触发重试:

  • 响应状态代码表示客户端错误(4xx),但 429 请求过多除外。
  • 状态代码为 501 未实施的响应。

动态集群分布

目前状态:Alpha(自 v2.9.0 起)

默认情况下,集群会无限期地分配给分片。对于使用默认的基于哈希的分片算法的用户来说,这种静态分配是可以的:分片将始终通过基于哈希的算法大致平衡。但对于使用循环或其他自定义分片分配算法的用户来说,这种静态分配可能会导致在添加或删除副本时分片不平衡。

从 v2.9 开始,Argo CD 支持动态集群分布功能。添加或删除副本时,将重新运行分片算法,以确保集群按照算法进行分布。如果算法均衡,如循环,则分片也将均衡。

以前,分片数量是通过 ARGOCD_CONTROLLER_REPLICAS 环境变量设置的。更改环境变量会强制重新启动所有应用程序控制器 pod。现在,分片数量是通过部署的replicas字段设置的,不需要重新启动应用程序控制器 pod

实现集群的动态分布

此功能处于 alpha 阶段时默认处于禁用状态。为了利用此功能,清单 manifests/ha/base/controller-deployment/ 可以作为 Kustomize 覆盖应用。此覆盖将 StatefulSet 副本设置为 0,并将应用程序控制器部署为 Deployment。此外,在将应用程序控制器作为部署运行时,必须将环境 ARGOCD_ENABLE_DYNAMIC_CLUSTER_DISTRIBUTION 设置为 true

使用 Deployment 而不是 StatefulSet 是一个实现细节,此功能的未来版本可能会发生变化。因此,Kustomize 覆盖的目录名称也可能会发生变化。请关注发行说明以避免出现问题。

注意引入了新的环境变量 ARGOCD_CONTROLLER_HEARTBEAT_TIME。环境变量在动态分布心跳过程的工作原理中进行了说明

动态分布的工作原理

为了完成集群的运行时分布,应用程序控制器使用 ConfigMap 将控制器 pod 与分片号和心跳关联起来,以确保控制器 pod 仍然活跃并且处理它们的分片,实际上是它们的工作份额。

应用程序控制器将创建一个名为 argocd-app-controller-shard-cm 的新 ConfigMap 来存储Controller <-> Shard映射。每个分片的映射如下所示:

ShardNumber    : 0
ControllerName : "argocd-application-controller-hydrxyt"
HeartbeatTime  : "2009-11-17 20:34:58.651387237 +0000 UTC"
  • ControllerName:存储应用程序控制器 pod 的主机名
  • ShardNumber :存储控制器 pod 管理的分片编号
  • HeartbeatTime:存储上次更新此心跳的时间

控制器分片映射在 ConfigMap 中更新,每次检查 pod 的就绪探测时更新一次,即每 10 秒更新一次(否则按配置)。控制器将在每次迭代就绪探测检查期间获取分片,并尝试使用 HeartbeatTime 更新 ConfigMap。默认 HeartbeatDuration 为 10 秒,在此之后应更新心跳。如果任何控制器 pod 的 ConfigMap 未更新超过 3 * HeartbeatDuration,则应用程序 pod 的就绪探测将被标记为不健康。要增加默认 HeartbeatDuration,可以将环境变量 ARGOCD_CONTROLLER_HEARTBEAT_TIME 设置为所需值。

新的分片机制不再监控环境变量ARGOCD_CONTROLLER_REPLICAS,而是直接从Application Controller Deployment中读取副本数,Controller通过对比Application Controller Deployment中的副本数和argocd-app-controller-shard-cm ConfigMap中的映射数来判断副本数的变化。

在应用程序控制器副本数量增加的情况下,会在 argocd-app-controller-shard-cm ConfigMap 中的映射列表中添加新条目,并触发集群分发以重新分配集群。

在应用程序控制器副本数量减少的情况下,argocd-app-controller-shard-cm ConfigMap 中的映射将被重置,并且每个控制器都会再次获取分片,从而触发集群的重新分配。

7.9.用户管理

安装后,Argo CD 会有一个内置管理员用户,该用户对系统具有完全访问权限。建议仅在初始配置时使用管理员用户,然后切换到本地用户或配置 SSO 集成。

概述

本地用户/帐户

本地用户/帐户功能主要有两个用途:

  • 用于 Argo CD 管理自动化的身份验证令牌。可以配置具有有限权限的 API 帐户并生成身份验证令牌。此类令牌可用于自动创建应用程序、项目等。
  • 对于非常小的团队来说,使用 SSO 集成可能被认为是过度的。本地用户不提供群组、登录历史记录等高级功能。因此,如果需要此类功能,强烈建议使用 SSO。

当创建本地用户时,每个用户都需要设置额外的 RBAC 规则,否则将恢复到 argocd-rbac-cm ConfigMap 的 policy.default 字段指定的默认策略。

本地帐户的用户名最大长度为 32。

创建新用户

新用户应该在 argocd-cm ConfigMap 中定义:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-cm
    app.kubernetes.io/part-of: argocd
data:
  # add an additional local user with apiKey and login capabilities
  #   apiKey - allows generating API keys
  #   login - allows to login using UI
  accounts.alice: apiKey, login
  # disables user. User is enabled by default
  accounts.alice.enabled: "false"

每个用户可能有两种能力:

  • apiKey - 允许生成用于 API 访问的身份验证令牌
  • login - 允许使用 UI 登录
删除用户

为了删除用户,必须删除 argocd-cm ConfigMap 中定义的相应条目:
例子:

kubectl patch -n argocd cm argocd-cm --type='json' -p='[{"op": "remove", "path": "/data/accounts.alice"}]'

建议还删除 argocd-secret Secret 中的密码条目:
例子:

kubectl patch -n argocd secrets argocd-secret --type='json' -p='[{"op": "remove", "path": "/data/accounts.alice.password"}]'
禁用管理员用户

一旦创建了其他用户,建议禁用管理员用户:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-cm
    app.kubernetes.io/part-of: argocd
data:
  admin.enabled: "false"
管理用户

Argo CD CLI 提供了一组命令来设置用户密码和生成令牌。

  • 获取完整用户列表
argocd account list
  • 获取特定用户的详细信息
argocd account get --account <username>
  • 设置用户密码
# if you are managing users as the admin user, <current-user-password> should be the current admin password.
argocd account update-password \
  --account <name> \
  --current-password <current-user-password> \
  --new-password <new-user-password>
  • 生成身份验证令牌
# if flag --account is omitted then Argo CD generates token for current user
argocd account generate-token --account <username>
限制登录失败率

为了防止密码暴力破解,Argo CD 会在登录尝试失败次数过多后拒绝登录尝试。以下环境变量可用于控制限制设置:

  • ARGOCD_SESSION_FAILURE_MAX_FAIL_COUNT:Argo CD 开始拒绝登录尝试之前的最大登录失败次数。默认值:5
  • ARGOCD_SESSION_FAILURE_WINDOW_SECONDS:失败窗口的秒数。默认值:300(5 分钟)。如果设置为 0,则禁用失败窗口,并且连续 10 次登录失败后,登录尝试将被拒绝,无论发生的时间范围如何。
  • ARGOCD_SESSION_MAX_CACHE_SIZE:缓存中允许的最大条目数。默认值:1000
  • ARGOCD_MAX_CONCURRENT_LOGIN_REQUESTS_COUNT:限制最大并发登录请求数。如果设置为 0,则限制被禁用。默认值:50
SSO

有两种方法可以配置 SSO:

  • 捆绑 Dex OIDC 提供商 - 如果当前的提供商不支持 OIDC(例如 SAML、LDAP)或者希望利用 Dex 的任何连接器功能(例如将 GitHub 组织和团队映射到 OIDC 组声明的能力),请使用此选项。Dex 还直接支持 OIDC,并且可以在组无法包含在 IDToken 中时从身份提供商处获取用户信息。
  • 现有的 OIDC 提供商 - 如果已经有正在使用的 OIDC 提供商(例如 OktaOneLoginAuth0MicrosoftKeycloakGoogle(G Suite)),可以使用此选项来管理您的用户、群组和会员资格。
Dex

Argo CD 将 Dex 嵌入并捆绑在其安装中,目的是将身份验证委托给外部身份提供者。支持多种类型的身份提供者(OIDC、SAML、LDAP、GitHub 等)。Argo CD 的 SSO 配置需要使用 Dex 连接器设置编辑 argocd-cm ConfigMap。

本文档以 GitHub(OAuth2)为例介绍了如何配置 Argo CD SSO,但对于其他身份提供者,步骤应该类似。

1. 在身份提供者中注册应用程序

在 GitHub 中注册一个新应用程序。回调地址应该是 Argo CD URL 的 /api/dex/callback 端点(例如 https://argocd.example.com/api/dex/callback)。
在这里插入图片描述
注册应用程序后,将收到一个 OAuth2 客户端 ID 和密钥。这些值将输入到 Argo CD 配置映射中。
在这里插入图片描述

2. 配置 Argo CD 进行 SSO

编辑 argocd-cm 配置映射:

kubectl edit configmap argocd-cm -n argocd
  • url 键中,输入 Argo CD 的基本 URL。在此示例中,它是 https://argocd.example.com
  • dex.config 键中,将 GitHub 连接器添加到connectors子字段。请参阅 Dex 的 GitHub 连接器文档以了解字段的说明。最小配置应填充步骤 1 中生成的 clientID、clientSecret。
  • 很可能希望将登录限制到一个或多个 GitHub 组织。在connectors.config.orgs列表中,添加一个或多个 GitHub 组织。然后,该组织的任何成员都可以登录 Argo CD 执行管理任务。
data:
  url: https://argocd.example.com

  dex.config: |
    connectors:
      # GitHub example
      - type: github
        id: github
        name: GitHub
        config:
          clientID: aabbccddeeff00112233
          clientSecret: $dex.github.clientSecret # Alternatively $<some_K8S_secret>:dex.github.clientSecret
          orgs:
          - name: your-github-org

      # GitHub enterprise example
      - type: github
        id: acme-github
        name: Acme GitHub
        config:
          hostName: github.acme.example.com
          clientID: abcdefghijklmnopqrst
          clientSecret: $dex.acme.clientSecret  # Alternatively $<some_K8S_secret>:dex.acme.clientSecret
          orgs:
          - name: your-github-org

保存后,更改将自动生效。

笔记:

  • 无需在 connectors.config 中设置 redirectURI,如 dex 文档中所示。Argo CD 将自动为任何 OAuth2 连接器使用正确的 redirectURI,以匹配正确的外部回调 URL(例如 https://argocd.example.com/api/dex/callback
  • 当使用自定义密钥(例如上面的 some_K8S_secret)时,它必须具有标签 app.kubernetes.io/part-of: argocd
使用 DEX 的 OIDC 配置

Dex 可直接用于 OIDC 身份验证,而不是 ArgoCD。这提供了一组单独的功能,例如从UserInfo 端点和联合令牌获取信息

配置:
argocd-cm ConfigMap 中,将 OIDC 连接器添加到 dex.config 内的连接器子字段。请参阅 Dex 的 OIDC 连接文档,了解其他哪些配置选项可能有用。我们将在这里使用最小配置。

发行者 URL 应该是 Dex 与 OIDC 提供商对话的地方。此 URL 下通常会有一个 .well-known/openid-configuration,其中包含有关提供商支持的内容的信息。例如 https://accounts.google.com/.well-known/openid-configuration

data:
  url: "https://argocd.example.com"
  dex.config: |
    connectors:
      # OIDC
      - type: oidc
        id: oidc
        name: OIDC
        config:
          issuer: https://example-OIDC-provider.example.com
          clientID: aaaabbbbccccddddeee
          clientSecret: $dex.oidc.clientSecret
请求其他 ID 令牌声明

默认情况下,Dex 仅检索个人资料和电子邮件范围。为了检索更多声明,可以在 Dex 配置中的范围条目下添加它们。要通过 Dex 启用组声明,还需要启用 insecureEnableGroups。组信息目前仅在身份验证时刷新,可以在此处跟踪更动态地刷新组信息的支持:dexidp/dex#1065

data:
  url: "https://argocd.example.com"
  dex.config: |
    connectors:
      # OIDC
      - type: OIDC
        id: oidc
        name: OIDC
        config:
          issuer: https://example-OIDC-provider.example.com
          clientID: aaaabbbbccccddddeee
          clientSecret: $dex.oidc.clientSecret
          insecureEnableGroups: true
          scopes:
          - profile
          - email
          - groups

由于组信息仅在身份验证时刷新,因此仅向组中添加或删除帐户不会改变用户的成员身份,直到用户重新进行身份验证为止。根据您组织的需求,这可能是一个安全风险,可以通过更改身份验证令牌的生命周期来缓解。

检索不在令牌中的声明

当 Idp 不支持或无法支持 IDToken 中的某些声明时,可以使用 UserInfo 端点单独检索这些声明。Dex 使用 getUserInfo 端点支持此功能。IDToken 中不支持的最常见声明之一是groups声明,并且 getUserInfoinsecureEnableGroups 都必须设置为 true

data:
  url: "https://argocd.example.com"
  dex.config: |
    connectors:
      # OIDC
      - type: OIDC
        id: oidc
        name: OIDC
        config:
          issuer: https://example-OIDC-provider.example.com
          clientID: aaaabbbbccccddddeee
          clientSecret: $dex.oidc.clientSecret
          insecureEnableGroups: true
          scopes:
          - profile
          - email
          - groups
          getUserInfo: true
现有的 OIDC 提供商

要配置 Argo CD 以将身份验证委托给现有的 OIDC 提供商,请将 OAuth2 配置添加到 oidc.config 键下的 argocd-cm ConfigMap 中:

data:
  url: https://argocd.example.com

  oidc.config: |
    name: Okta
    issuer: https://dev-123456.oktapreview.com
    clientID: aaaabbbbccccddddeee
    clientSecret: $oidc.okta.clientSecret

    # Optional list of allowed aud claims. If omitted or empty, defaults to the clientID value above (and the 
    # cliClientID, if that is also specified). If you specify a list and want the clientID to be allowed, you must 
    # explicitly include it in the list.
    # Token verification will pass if any of the token's audiences matches any of the audiences in this list.
    allowedAudiences:
    - aaaabbbbccccddddeee
    - qqqqwwwweeeerrrrttt

    # Optional. If false, tokens without an audience will always fail validation. If true, tokens without an audience 
    # will always pass validation.
    # Defaults to true for Argo CD < 2.6.0. Defaults to false for Argo CD >= 2.6.0.
    skipAudienceCheckWhenTokenHasNoAudience: true

    # Optional set of OIDC scopes to request. If omitted, defaults to: ["openid", "profile", "email", "groups"]
    requestedScopes: ["openid", "profile", "email", "groups"]

    # Optional set of OIDC claims to request on the ID token.
    requestedIDTokenClaims: {"groups": {"essential": true}}

    # Some OIDC providers require a separate clientID for different callback URLs.
    # For example, if configuring Argo CD with self-hosted Dex, you will need a separate client ID
    # for the 'localhost' (CLI) client to Dex. This field is optional. If omitted, the CLI will
    # use the same clientID as the Argo CD server
    cliClientID: vvvvwwwwxxxxyyyyzzzz

    # PKCE authentication flow processes authorization flow from browser only - default false
    # uses the clientID
    # make sure the Identity Provider (IdP) is public and doesn't need clientSecret
    # make sure the Identity Provider (IdP) has this redirect URI registered: https://argocd.example.com/pkce/verify
    enablePKCEAuthentication: true

回调地址应该是 Argo CD URL 的/auth/callback端点(例如 https://argocd.example.com/auth/callback)。

请求其他 ID 令牌声明

并非所有 OIDC 提供商都支持特殊组范围。例如,Okta、OneLogin 和 Microsoft 都支持特殊groups范围,并将使用默认的 requestedScopes 返回groups成员身份。

如果明确要求,其他 OIDC 提供商可能能够返回具有组成员身份的声明。可以使用 requestedIDTokenClaims 请求单个声明,有关详细信息,请参阅 OpenID Connect 声明参数。Argo CD 的声明配置如下:

  oidc.config: |
    requestedIDTokenClaims:
      email:
        essential: true
      groups:
        essential: true
        value: org:myorg
      acr:
        essential: true
        values:
        - urn:mace:incommon:iap:silver
        - urn:mace:incommon:iap:bronze

对于简单情况,这可以是:

  oidc.config: |
    requestedIDTokenClaims: {"groups": {"essential": true}}
检索不在令牌中的组声明

某些 OIDC 提供商不会在 ID 令牌中返回用户的组信息,即使使用 equestedIDTokenClaims 设置明确请求(例如 Okta)。它们改为在用户信息端点上提供组。使用以下配置,Argo CD 在登录期间查询用户信息端点以获取用户的组信息:

oidc.config: |
    enableUserInfoGroups: true
    userInfoPath: /userinfo
    userInfoCacheExpiration: "5m"

注意:如果省略 userInfoCacheExpiration 设置或者它大于 ID 令牌的有效期,则只要 ID 令牌有效,argocd-server 就会缓存组信息!

为 OIDC 提供商配置自定义注销 URL

如果 OIDC 提供商公开了注销 API,这样可以配置自定义注销 URL 以便在注销后使任何活动会话无效,按如下方式指定它:

  oidc.config: |
    name: example-OIDC-provider
    issuer: https://example-OIDC-provider.example.com
    clientID: xxxxxxxxx
    clientSecret: xxxxxxxxx
    requestedScopes: ["openid", "profile", "email", "groups"]
    requestedIDTokenClaims: {"groups": {"essential": true}}
    logoutURL: https://example-OIDC-provider.example.com/logout?id_token_hint={{token}}

默认情况下,这会在用户注销后将用户带到其 OIDC 提供商的登录页面。如果在用户注销后将用户重定向回 Argo CD,您可以按如下方式指定注销 URL:

...
    logoutURL: https://example-OIDC-provider.example.com/logout?id_token_hint={{token}}&post_logout_redirect_uri={{logoutRedirectURL}}

不需要指定 logoutRedirectURL,因为它是由 ArgoCD 自动生成的,作为基本 ArgoCD url + Rootpath

注销后重定向 URI 可能需要根据您的 OIDC 提供商的 ArgoCD 客户端设置列入白名单。

配置自定义根 CA 证书以便与 OIDC 提供商进行通信

如果 OIDC 提供商设置的证书不是由知名证书颁发机构签名的,可以提供一个自定义证书,该证书将在与 OIDC 提供商通信时用于验证其 TLS 证书。

将包含 PEM 编码根证书的 rootCA 添加到 oidc.config 中:

  oidc.config: |
    ...
    rootCA: |
      -----BEGIN CERTIFICATE-----
      ... encoded certificate data here ...
      -----END CERTIFICATE-----
SSO 延伸阅读
敏感数据和 SSO 客户端机密

argocd-secret 可用于存储可被 ArgoCD 引用的敏感数据。configmap 中以 $ 开头的值解释如下:

  • 如果值的形式为:$<secret>:a.key.in.k8s.secret,则查找名为 <secret>(减去 $)的 k8s secret,并读取其值。
  • 否则,在名为 argocd-secret 的 k8s 密钥中查找密钥。

例子
因此,SSO clientSecret 可以作为 Kubernetes 密钥存储,具体清单如下
argocd-secret:

apiVersion: v1
kind: Secret
metadata:
  name: argocd-secret
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-secret
    app.kubernetes.io/part-of: argocd
type: Opaque
data:
  ...
  # The secret value must be base64 encoded **once** 
  # this value corresponds to: `printf "hello-world" | base64`
  oidc.auth0.clientSecret: "aGVsbG8td29ybGQ="
  ...

argocd-cm:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-cm
    app.kubernetes.io/part-of: argocd
data:
  ...
  oidc.config: |
    name: Auth0
    clientID: aabbccddeeff00112233

    # Reference key in argocd-secret
    clientSecret: $oidc.auth0.clientSecret
  ...

选择
如果你想将敏感数据存储在另一个 Kubernetes Secret 中,而不是 argocd-secret 中。每当 configmap 或 secret 中的值以 $ 开头时,ArgoCD 就会检查 Kubernetes Secret 中数据下的键以查找相应的键,然后是 Kubernetes Secret 名称和 :(冒号)。

语法:$<k8s_secret_name>:<a_key_in_that_k8s_secret>

注意:Secret 必须有标签 app.kubernetes.io/part-of: argocd

例子
another-secret:

apiVersion: v1
kind: Secret
metadata:
  name: another-secret
  namespace: argocd
  labels:
    app.kubernetes.io/part-of: argocd
type: Opaque
data:
  ...
  # Store client secret like below.
  # Ensure the secret is base64 encoded
  oidc.auth0.clientSecret: <client-secret-base64-encoded>
  ...

argocd-cm:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-cm
    app.kubernetes.io/part-of: argocd
data:
  ...
  oidc.config: |
    name: Auth0
    clientID: aabbccddeeff00112233
    # Reference key in another-secret (and not argocd-secret)
    clientSecret: $another-secret:oidc.auth0.clientSecret  # Mind the ':'
  ...
跳过 OIDC 提供商连接上的证书验证

默认情况下,API 服务器与 OIDC 提供商(外部提供商或捆绑的 Dex 实例)建立的所有连接都必须通过证书验证。这些连接在获取 OIDC 提供商的已知配置、获取 OIDC 提供商的密钥以及在 OIDC 登录流程中交换授权码或验证 ID 令牌时发生。

如果出现以下情况,禁用证书验证可能是有意义的:

  • * 你正在使用捆绑的 Dex 实例,并且您的 Argo CD 实例已使用自签名证书配置了 TLS,并且您了解并接受跳过 OIDC 提供商证书验证的风险。
  • * 你正在使用外部 OIDC 提供商,并且该提供商使用无效证书,并且您无法通过设置 oidcConfig.rootCA 来解决问题,并且了解并接受跳过 OIDC 提供商证书验证的风险。

如果上述两种情况之一适用,那么可以通过在 argocd-cm ConfigMap 中将 oidc.tls.insecure.skip.verify 设置为“true”来禁用 OIDC 提供商证书验证。

Auth0

用户定义

Auth0 中的用户定义超出了本指南的范围。直接在 Auth0 数据库中添加它们,使用企业注册表或“social login”。注意:所有用户都可以访问所有 Auth0 定义的应用程序,除非通过配置限制访问 - 如果 argo 在互联网上公开,请记住这一点,否则任何人都可以登录。

使用 Auth0 注册应用程序

按照注册应用程序说明在 Auth0 中创建 argocd 应用程序。在应用程序定义中:

  • 记下 clientIdclientSecret 值。
  • 注册登录网址为 https://your.argoingress.address/login
  • 将允许的回调 URL 设置为 https://your.argoingress.address/auth/callback
  • 在连接下,选择想要与 argo 一起使用的用户注册表。

任何其他设置对于身份验证工作来说都是不必要的。

向 Auth0 添加授权规则

按照 Auth0 授权指南设置授权。这里要注意的重要部分是,组成员身份是非标准声明,因此需要放在 FQDN 声明名称下,例如 http://your.domain/groups

配置 argo
为 ArgoCD 配置 OIDC
kubectl edit configmap argocd-cm
...
data:
  application.instanceLabelKey: argocd.argoproj.io/instance
  url: https://your.argoingress.address
  oidc.config: |
    name: Auth0
    issuer: https://<yourtenant>.<eu|us>.auth0.com/
    clientID: <theClientId>
    clientSecret: <theClientSecret>
    requestedScopes:
    - openid
    - profile
    - email
    # not strictly necessary - but good practice:
    - 'http://your.domain/groups'
...
为 ArgoCD 配置 RBAC
kubectl edit configmap argocd-rbac-cm

(或者使用 helm 值)。

...
data:
  policy.csv: |
    # let members with group someProjectGroup handle apps in someProject
    # this can also be defined in the UI in the group-definition to avoid doing it there in the configmap
    p, someProjectGroup, applications, *, someProject/*, allow
    # let the group membership argocd-admins from OIDC become role:admin - needs to go into the configmap
    g, argocd-global-admins, role:admin
  policy.default: role:readonly
  # essential to get argo to use groups for RBAC:
  scopes: '[http://your.domain/groups, email]' 
...

有关安全正确地存储客户端机密的详细信息,请参阅用户管理概述页面

microsoft

此处忽略…,具体参考

Okta

此处忽略…,具体参考

OneLogin

此处忽略…,具体参考

Keycloak

此处忽略…,具体参考

OpenUnison

此处忽略…,具体参考

Google

此处忽略…,具体参考

Zitadel

此处忽略…,具体参考

AWS SSO

此处忽略…,具体参考

RBAC 配置

RBAC 功能可以限制对 Argo CD 资源的访问。Argo CD 没有自己的用户管理系统,只有一个内置用户管理员。管理员用户是超级用户,可以不受限制地访问系统。RBAC 需要 SSO 配置或设置一个或多个本地用户。配置 SSO 或本地用户后,可以定义其他 RBAC 角色,然后可以将 SSO 组或本地用户映射到角色。

基本内置角色

Argo CD 有两个预定义角色,但 RBAC 配置允许定义角色和组(见下文)。

  • role:readonly - 对所有资源的只读访问
  • role:admin - 不受限制地访问所有资源

这些默认的内置角色定义可以在builtin-policy.csv中看到

RBAC 权限结构

在 Argo CD 中,权限定义的细分在应用程序和其他每种资源类型之间略有不同。

  • 除应用程序特定权限之外的所有资源(请参阅下一个项目符号):p, <role/user/group>, <resource>, <action>, <object>
  • 应用程序、应用程序集、日志和 exec(属于 AppProject):p, <role/user/group>, <resource>, <action>, <appproject>/<object>
RBAC 资源和动作
  • 资源:clusters, projects, applications, applicationsets, repositories, certificates, accounts, gpgkeys, logs, exec, extensions
  • 动作:get, create, update, delete, sync, override,action/<group/kind/action-name>

请注意,sync、override 和 action/<group/kind/action-name> 仅对应用程序资源有意义。

应用资源

应用程序对象的资源路径的形式为<project-name>/<application-name>
无法精细地管理对项目子资源(例如 rolloutpod)的删除访问权限。<project-name>/<application-name> 授予对应用程序所有子资源的访问权限。

action动作

操作 action 对应于 Argo CD 存储库中定义的内置资源自定义,或您定义的自定义资源操作。操作路径的格式为 action/<api-group>/<Kind>/<action-name>。例如,资源自定义路径 resource_customizations/extensions/DaemonSet/actions/restart/action.lua 对应于操作路径 action/extensions/DaemonSet/restart。还可以在操作路径中使用 glob 模式:action/*(或正则表达式模式,如果已启用正则表达式匹配模式)。

如果资源不在组下(例如,PodConfigMaps),则从 RBAC 配置中省略组名:p, example-user, applications, action//Pod/maintenance-off, default/*, allow

exec资源

exec 是一种特殊资源。当通过 create 操作启用时,此权限允许用户通过 Argo CD UI 执行 Pod 操作。该功能类似于 kubectl exec

请参阅基于 Web 的终端以了解更多信息。

applicationsets资源

ApplicationSets 提供了一种声明性的方式来自动create/update/delete应用程序。
授予 applicationsets, create 权限实际上授予了创建应用程序的能力。虽然它不允许用户直接创建应用程序,但他们可以通过 ApplicationSet 创建应用程序。
在 v2.5 中,无法通过 API(或 CLI)创建具有模板化 Project 字段的 ApplicationSet(例如 project: {{path.basename}})。禁止模板化项目可确保通过 RBAC 进行项目限制的安全:p, dev-group, applicationsets, *, dev-project/*, allow
有了此规则,dev-group 用户将无法创建能够在 dev-project 项目之外创建应用程序的 ApplicationSet

extensions资源

使用扩展资源可以配置权限以调用代理扩展。扩展 RBAC 验证与应用程序资源协同工作。登录 Argo CD(UI 或 CLI)的用户需要至少对请求来源的项目、命名空间和应用程序具有读取权限。
请考虑以下示例:

g, ext, role:extension
p, role:extension, applications, get, default/httpbin-app, allow
p, role:extension, extensions, invoke, httpbin, allow

解释:

  • line1: 定义与主题 ext 关联的组role:extension
  • line2:定义一个策略,允许该角色读取(get)项目中的 default/httpbin-app 应用程序。
  • line3:定义另一个允许该角色invokehttpbin 扩展的策略。

注1:为了允许扩展请求,还需要第2行中定义的策略。
注 2:invoke 是专门为与extensions资源配合使用而引入的新操作。的当前操作extensions*invoke

把所有东西结合在一起

可以在 argocd-rbac-cm ConfigMap 中配置其他角色和组。下面的示例配置了一个名为 org-admin 的自定义角色。该角色分配给属于 your-github-org:your-team 组的任何用户。所有其他用户都获得默认策略 role:readonly,该策略无法修改 Argo CD 设置。

所有经过身份验证的用户至少会获得默认策略授予的权限。此访问无法通过拒绝规则阻止。相反,应限制默认策略,然后根据需要向各个角色授予权限。

ArgoCD ConfigMap argocd-rbac-cm 示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.default: role:readonly
  policy.csv: |
    p, role:org-admin, applications, *, */*, allow
    p, role:org-admin, clusters, get, *, allow
    p, role:org-admin, repositories, get, *, allow
    p, role:org-admin, repositories, create, *, allow
    p, role:org-admin, repositories, update, *, allow
    p, role:org-admin, repositories, delete, *, allow
    p, role:org-admin, projects, get, *, allow
    p, role:org-admin, projects, create, *, allow
    p, role:org-admin, projects, update, *, allow
    p, role:org-admin, projects, delete, *, allow
    p, role:org-admin, logs, get, *, allow
    p, role:org-admin, exec, create, */*, allow

    g, your-github-org:your-team, role:org-admin

另一个 ·policy.csv· 示例可能如下所示:

p, role:staging-db-admin, applications, create, staging-db-project/*, allow
p, role:staging-db-admin, applications, delete, staging-db-project/*, allow
p, role:staging-db-admin, applications, get, staging-db-project/*, allow
p, role:staging-db-admin, applications, override, staging-db-project/*, allow
p, role:staging-db-admin, applications, sync, staging-db-project/*, allow
p, role:staging-db-admin, applications, update, staging-db-project/*, allow
p, role:staging-db-admin, logs, get, staging-db-project/*, allow
p, role:staging-db-admin, exec, create, staging-db-project/*, allow
p, role:staging-db-admin, projects, get, staging-db-project, allow
g, db-admins, role:staging-db-admin

此示例定义了一个名为 staging-db-admin 的角色,该角色具有九个权限,允许具有该角色的用户执行以下操作:

  • staging-db-project 项目中的应用程序·create, delete, get, override, sync, update·,
  • staging-db-project 项目中的对象get日志,
  • staging-db-project 项目中的对象create exec,
  • 并为名为 staging-db-project 的项目get

scopes字段控制在 rbac 执行期间检查哪些 OIDC 范围(除了sub范围)。如果省略,则默认为: ‘[groups]’ 。范围值可以是字符串或字符串列表。

以下示例显示了来自 OIDC 提供商的定位email以及groups

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-rbac-cm
    app.kubernetes.io/part-of: argocd
data:
  policy.csv: |
    p, my-org:team-alpha, applications, sync, my-project/*, allow
    g, my-org:team-beta, role:admin
    g, user@example.org, role:admin
  policy.default: role:readonly
  scopes: '[groups, email]'

有关范围的更多信息,请参阅用户管理文档

政策 CSV 组成

可以在 argocd-rbac-cm configmap 中提供其他条目来组成最终策略 csv。在这种情况下,密钥必须遵循模式 policy.<any string>.csv。Argo CD 会将它找到的所有附加策略与此模式连接在主策略(policy.csv)下。附加提供的策略的顺序由密钥字符串决定。例如:如果提供了两个附加策略,其密钥分别为 policy.A.csvpolicy.B.csv,它将首先连接 policy.A.csv,然后连接 policy.B.csv

这对于允许在 Kustomize、Helm 等配置管理工具中编写策略很有用。

下面的示例展示了如何在覆盖中提供 Kustomize 补丁以向现有 RBAC 策略添加额外配置。

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.tester-overlay.csv: |
    p, role:tester, applications, *, */*, allow
    p, role:tester, projects, *, *, allow
    g, my-org:team-qa, role:tester
匿名访问

可以使用 argocd-cm 中的 users.anonymous.enabled 字段启用对 Argo CD 的匿名访问(参见 argocd-cm.yaml)。匿名用户获得由 argocd-rbac-cm.yaml 中的 policy.default 指定的默认角色权限。对于只读访问,需要使用如上所述的 policy.default: role:readonly

验证和测试 RBAC 策略

如果想确保 RBAC 策略按预期工作,可以使用 argocd admin settings rbac 命令来验证它们。此工具允许测试某个角色或主体是否可以使用系统中尚未生效的策略(即来自本地文件或配置映射)执行请求的操作。此外,它还可以用于 Argo CD 正在运行的集群中的实时策略。

要检查新策略是否有效并被 Argo CD 的 RBAC 实现理解,您可以使用 argocd admin settings rbac verify 命令。

验证策略

要验证存储在本地文本文件中的策略:

argocd admin settings rbac validate --policy-file somepolicy.csv

要验证 YAML 文件中本地 K8s ConfigMap 定义中存储的策略:

argocd admin settings rbac validate --policy-file argocd-rbac-cm.yaml

要验证存储在 K8s 中的策略(由 Argo CD 在命名空间 argocd 中使用),请确保 ~/.kube/config 中的当前上下文指向 Argo CD 集群并提供适当的命名空间:

argocd admin settings rbac validate --namespace argocd
测试策略

要测试角色或主体(组或本地用户)是否具有足够的权限对​​某些资源执行某些操作,可以使用 argocd admin settings rbac can 命令。其一般语法为

argocd admin settings rbac can SOMEROLE ACTION RESOURCE SUBRESOURCE [flags]

鉴于上述 ConfigMap 中的示例,它定义角色 role:org-admin,并以 argocd-rbac-cm-yaml 的形式存储在本地系统中,您可以测试该角色是否可以执行如下操作:

$ argocd admin settings rbac can role:org-admin get applications --policy-file argocd-rbac-cm.yaml
Yes

$ argocd admin settings rbac can role:org-admin get clusters --policy-file argocd-rbac-cm.yaml
Yes

$ argocd admin settings rbac can role:org-admin create clusters 'somecluster' --policy-file argocd-rbac-cm.yaml
No

$ argocd admin settings rbac can role:org-admin create applications 'someproj/someapp' --policy-file argocd-rbac-cm.yaml
Yes

另一个示例,给定来自 policy.csv 的上述策略,该策略定义角色 role:staging-db-admin 并将组 db-admins 与其关联。策略在本地存储为 policy.csv

可以针对该角色进行测试:

$ # Plain policy, without a default role defined
$ argocd admin settings rbac can role:staging-db-admin get applications --policy-file policy.csv
No

$ argocd admin settings rbac can role:staging-db-admin get applications 'staging-db-project/*' --policy-file policy.csv
Yes

$ # Argo CD augments a builtin policy with two roles defined, the default role
$ # being 'role:readonly' - You can include a named default role to use:
$ argocd admin settings rbac can role:staging-db-admin get applications --policy-file policy.csv --default-role role:readonly
Yes

或者针对定义的组:

$ argocd admin settings rbac can db-admins get applications 'staging-db-project/*' --policy-file policy.csv
Yes

7.10.安全

Argo CD 经过了严格的内部安全审查和渗透测试,以满足 PCI 合规性要求。以下是 Argo CD 的一些安全主题和实施细节。

概括

身份验证

Argo CD API 服务器的身份验证仅使用 JSON Web Tokens (JWT) 执行。用户名/密码承载令牌不用于身份验证。JWT 可通过以下方式之一获取/管理:

  1. 对于本地admin用户,使用 /api/v1/session 端点将用户名/密码交换为 JWT。此令牌由 Argo CD API 服务器本身签名和颁发,并在 24 小时后过期(此令牌以前不会过期,请参阅 CVE-2021-26921)。更新管理员密码后,所有现有的管理员 JWT 令牌都会立即被撤销。密码以 bcrypt 哈希的形式存储在 argocd-secret Secret 中。
  2. 对于单点登录用户,用户完成 OAuth2 登录流程,登录到已配置的 OIDC 身份提供商(通过捆绑的 Dex 提供商委托,或直接委托给自管理的 OIDC 提供商)。此 JWT 由 IDP 签名和颁发,到期和撤销由提供商处理。Dex 令牌将在 24 小时后过期。
  3. 使用 /api/v1/projects/{project}/roles/{role}/token 端点为项目生成自动化令牌,并由 Argo CD 签名和颁发。这些令牌的范围和权限有限,只能用于管理其所属项目中的应用程序资源。项目 JWT 具有可配置的有效期,可以通过从项目角色中删除 JWT 引用 ID 立即撤销。
授权

授权是通过迭代用户 JWT 组声明中的组成员列表,并将每个组与 RBAC 策略中的角色/规则进行比较来执行的。任何匹配的规则都允许访问 API 请求。

TLS

所有网络通信均通过 TLS 进行,包括三个组件(argocd-server、argocd-repo-server、argocd-application-controller)之间的服务到服务通信。Argo CD API 服务器可以使用以下标志强制使用 TLS 1.2:--tlsminversion 1.2。默认情况下,与 Redis 的通信通过纯 HTTP 进行。可以使用命令行参数设置 TLS。

Git 和 Helm 存储库

Git 和 helm 存储库由独立服务(称为 repo-server)管理。repo-server 不具有任何 Kubernetes 权限,也不存储任何服务(包括 git)的凭据。repo-server 负责克隆已获得 Argo CD 操作员允许和信任的存储库,并在存储库中的给定路径生成 Kubernetes 清单。为了提高性能和带宽效率,repo-server 维护这些存储库的本地克隆,以便高效下载对存储库的后续提交。

配置允许 Argo CD 部署的 git 存储库时需要考虑安全问题。简而言之,未经授权获取 Argo CD 信任的 git 存储库的写入权限将产生如下所述的严重安全隐患。

未经授权的部署

由于 Argo CD 部署了 git 中定义的 Kubernetes 资源,因此有权访问受信任 git 存储库的攻击者将能够影响已部署的 Kubernetes 资源。例如,攻击者可以更新部署清单,将恶意容器映像部署到环境中,或者删除 git 中的资源,导致它们在实时环境中被删除。

工具命令调用

除了原始 YAML,Argo CD 还原生支持两种流行的 Kubernetes 配置管理工具:helmkustomize。在呈现清单时,Argo CD 会执行这些配置管理工具(即 helm template、kustomize build)来生成清单。具有受信任git 存储库写权限的攻击者可能会构建恶意的 helm chartkustomizations,试图读取树外的文件。这包括相邻的 git 存储库,以及存储库服务器本身上的文件。这是否对组织构成风险取决于 git 存储库中的内容是否本质上是敏感的。默认情况下,存储库服务器本身不包含敏感信息,但可能配置了包含敏感信息的配置管理插件(例如解密密钥)。如果使用此类插件,必须格外小心,以确保存储库内容始终值得信赖。

内置配置管理工具可以单独禁用。如果知道用户不需要某个配置管理工具,建议禁用该工具。有关更多信息,请参阅工具检测

远程基地和舵图依赖关系

Argo CD 的存储库允许列表仅限制克隆的初始存储库。但是,kustomizehelm 都包含引用和跟踪其他存储库(例如 kustomize 远程基础、helm chart依赖项)的功能,这些存储库可能不在存储库允许列表中。Argo CD 操作员必须了解,对受信任的 git 存储库具有写访问权限的用户可以引用其他远程 git 存储库,这些存储库包含 Kubernetes 资源,在配置的 git 存储库中不易搜索或审核。

敏感信息
密钥

Argo CD 从不从其 API 返回敏感数据,并会删除 API 有效负载和日志中的所有敏感数据。这包括:

  • 集群凭据
  • Git 凭据
  • OAuth2 客户端密钥
  • Kubernetes 密钥值
外部集群凭证

为了管理外部集群,Argo CD 将外部集群的凭据作为 Kubernetes Secret 存储在 argocd 命名空间中。此 secret 包含与在 argocd cluster add期间创建的 argocd-manager ServiceAccount 关联的 K8s API 承载令牌,以及与该 API 服务器的连接选项(TLS 配置/证书、AWS role-arn 等)。该信息用于为 Argo CD 服务使用的集群重建 REST 配置和 kubeconfig。

# run using a kubeconfig for the externally managed cluster
kubectl delete secret argocd-manager-token-XXXXXX -n kube-system
argocd cluster add CONTEXTNAME

Kubernetes 1.24 停止自动为服务帐户创建令牌。从 Argo CD 2.4 开始,argocd cluster add 在添加 1.24 集群时会创建一个服务帐户和一个永不过期的服务帐户令牌密钥。将来,Argo CD 将添加对 Kubernetes TokenRequest API 的支持,以避免使用长期令牌。

要撤销 Argo CD 对托管集群的访问权限,请删除针对托管集群的 RBAC 工件,并从 Argo CD 中删除集群条目:

# run using a kubeconfig for the externally managed cluster
kubectl delete sa argocd-manager -n kube-system
kubectl delete clusterrole argocd-manager-role
kubectl delete clusterrolebinding argocd-manager-role-binding
argocd cluster rm https://your-kubernetes-cluster-addr

注意:对于 AWS EKS 集群,get-token 命令用于对外部集群进行身份验证,它使用 IAM 角色代替本地存储的令牌,因此不需要令牌轮换,并且通过 IAM 处理撤销。

集群 RBAC

默认情况下,Argo CD 使用 clusteradmin 级别角色来:

  1. 监视和操作集群状态
  2. 将资源部署到集群

尽管 Argo CD 需要对托管集群中的资源具有集群范围的读取权限才能正常运行,但它不一定需要对集群具有完全的写入权限。 argocd-serverargocd-application-controller 使用的 ClusterRole 可以进行修改,以便写入权限仅限于希望 Argo CD 管理的命名空间和资源。

要微调外部管理集群的权限,请编辑 argocd-manager-role 的 ClusterRole

# run using a kubeconfig for the externally managed cluster
kubectl edit clusterrole argocd-manager-role

为了微调 Argo CD 对其自身集群(即 https://kubernetes.default.svc)的权限,请编辑 Argo CD 正在运行的以下集群角色:

# run using a kubeconfig to the cluster Argo CD is running in
kubectl edit clusterrole argocd-server
kubectl edit clusterrole argocd-application-controller

如果拒绝 Argo CD 访问某种资源,那么请将其添加为排除的资源。

审计

作为 GitOps 部署工具,Git 提交历史记录提供了自然的审计日志,记录了对应用程序配置进行了哪些更改、更改时间以及更改者。但是,此审计日志仅适用于 Git 中发生的事情,并不一定与集群中发生的事件一一对应。例如,用户 A 可能对应用程序清单进行了多次提交,但用户 B 可能只是在稍后将这些更改同步到集群。

为了补充 Git 修订历史记录,Argo CD 会发出应用程序活动的 Kubernetes 事件,并在适用时指明负责的参与者。例如:

$ kubectl get events
LAST SEEN   FIRST SEEN   COUNT   NAME                         KIND          SUBOBJECT   TYPE      REASON               SOURCE                          MESSAGE
1m          1m           1       guestbook.157f7c5edd33aeac   Application               Normal    ResourceCreated      argocd-server                   admin created application
1m          1m           1       guestbook.157f7c5f0f747acf   Application               Normal    ResourceUpdated      argocd-application-controller   Updated sync status:  -> OutOfSync
1m          1m           1       guestbook.157f7c5f0fbebbff   Application               Normal    ResourceUpdated      argocd-application-controller   Updated health status:  -> Missing
1m          1m           1       guestbook.157f7c6069e14f4d   Application               Normal    OperationStarted     argocd-server                   admin initiated sync to HEAD (8a1cb4a02d3538e54907c827352f66f20c3d7b0d)
1m          1m           1       guestbook.157f7c60a55a81a8   Application               Normal    OperationCompleted   argocd-application-controller   Sync operation to 8a1cb4a02d3538e54907c827352f66f20c3d7b0d succeeded
1m          1m           1       guestbook.157f7c60af1ccae2   Application               Normal    ResourceUpdated      argocd-application-controller   Updated sync status: OutOfSync -> Synced
1m          1m           1       guestbook.157f7c60af5bc4f0   Application               Normal    ResourceUpdated      argocd-application-controller   Updated health status: Missing -> Progressing
1m          1m           1       guestbook.157f7c651990e848   Application               Normal    ResourceUpdated      argocd-application-controller   Updated health status: Progressing -> Healthy

然后可以使用事件导出器或事件路由器等其他工具将这些事件保存更长时间。

WebHook 负载

来自 webhook 事件的有效负载被视为不受信任。Argo CD 仅检查有效负载以推断 webhook 事件所涉及的应用程序(例如,修改了哪个存储库),然后刷新相关应用程序以进行协调。此刷新与每隔三分钟定期发生的刷新相同,只是通过 webhook 事件进行了快速跟踪。

日志记录
安全属性

与安全相关的日志都标有安全字段,以便于查找、分析和报告。

界级别友好程度描述示例
1正常、非恶意事件成功访问
2可能表示恶意事件,但很可能是用户/系统错误拒绝访问
3可能是恶意事件,但没有副作用或已被阻止存储库中的符号链接超出范围
4严重任何有副作用的恶意或可利用事件文件系统中遗留的密钥
5急救毫无疑问是恶意事件,绝不应该意外发生,并表示存在主动攻击暴力破解账户

在适用的情况下,还会添加一个 CWE 字段,指定常见弱点枚举编号

API 日志

Argo CD 记录大多数 API 请求的有效负载,但被视为敏感的请求除外,例如 /cluster.ClusterService/Create, /session.SessionService/Create 等。方法的完整列表可以在 server/server.go 中找到。

Argo CD 不会记录请求 API 端点的客户端的 IP 地址,因为 API 服务器通常位于代理后面。相反,建议配置在位于 API 服务器前面的代理服务器中记录 IP 地址。

应用程序集(ApplicationSets)

Argo CD 的 ApplicationSets 功能有其自身的安全注意事项。在使用 ApplicationSets 之前请注意这些问题。

限制目录应用程序内存使用量

2.2.10, 2.1.16, >2.3.5

目录类型应用程序(其源是原始 JSONYAML 文件的应用程序)可能会消耗大量 repo 服务器内存,具体取决于 YAML 文件的大小和结构。

为了避免在 repo-server 中过度使用内存(可能导致崩溃和拒绝服务),请在 argocd-cmd-params-cm 中设置 reposerver.max.combined.directory.manifests.size 配置选项。

此选项限制单个应用中所有 JSONYAML 文件的总大小。请注意,清单在内存中的表示形式可能高达磁盘上清单大小的 300 倍。另请注意,限制是针对每个应用的。如果一次为多个应用生成清单,内存使用量会更高。

例子:
假设你的 repo 服务器有 10G 的内存限制,并且有 10 个使用原始 JSON 或 YAML 文件的应用程序。要计算每个应用程序的最大安全组合文件大小,请将 10G 除以 300 * 10 个应用程序(300 是清单的最坏情况内存增长因子)。

10G / 300 * 10 = 3M

因此,此设置的合理安全配置是每个应用程序 3M 的限制。

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cmd-params-cm
data:
  reposerver.max.combined.directory.manifests.size: '3M'

300x 比率假设清单文件是恶意制作的。如果只想防止意外过度使用内存,使用较小的比率可能是安全的。

请记住,如果恶意用户可以创建其他应用程序,则可以增加总内存使用量。请谨慎授予应用程序创建权限

Snyk 扫描

每个星期日,Snyk 都会针对 Argo CD 的主分支和最近三个次要版本的最新补丁生成扫描。

如需查看最新扫描,请查看文档的最新版本。您可以使用页面顶部的下拉选择器返回到您喜欢的文档站点版本。

版本扫描

验证 Argo CD 清单

先决条件
发布资源

| Asset | Description |
| argocd-darwin-amd64 | CLI Binary |
| argocd-darwin-arm64 | CLI Binary |
| argocd-linux_amd64 | CLI Binary |
| argocd-linux_arm64 | CLI Binary |
| argocd-linux_ppc64le | CLI Binary |
| argocd-linux_s390x | CLI Binary |
| argocd-windows_amd64 | CLI Binary |
| argocd-cli.intoto.jsonl | Attestation of CLI binaries |
| argocd-sbom.intoto.jsonl | Attestation of SBOM |
| cli_checksums.txt | Checksums of binaries |
| sbom.tar.gz | Sbom |
| sbom.tar.gz.pem | Certificate used to sign sbom |
| sbom.tar.gz.sig | Signature of sbom |

容器镜像验证

Argo CD 容器镜像使用基于身份(“无密钥”)的签名和透明度通过 cosign 进行签名。执行以下命令可用于验证容器镜像的签名:

cosign verify \
--certificate-identity-regexp https://github.com/argoproj/argo-cd/.github/workflows/image-reuse.yaml@refs/tags/v \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
quay.io/argoproj/argocd:v2.7.0 | jq

如果容器镜像被正确验证,该命令应该输出以下内容:

The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - Any certificates were verified against the Fulcio roots.
[
  {
    "critical": {
      "identity": {
        "docker-reference": "quay.io/argoproj/argo-cd"
      },
      "image": {
        "docker-manifest-digest": "sha256:63dc60481b1b2abf271e1f2b866be8a92962b0e53aaa728902caa8ac8d235277"
      },
      "type": "cosign container image signature"
    },
    "optional": {
      "1.3.6.1.4.1.57264.1.1": "https://token.actions.githubusercontent.com",
      "1.3.6.1.4.1.57264.1.2": "push",
      "1.3.6.1.4.1.57264.1.3": "a6ec84da0eaa519cbd91a8f016cf4050c03323b2",
      "1.3.6.1.4.1.57264.1.4": "Publish ArgoCD Release",
      "1.3.6.1.4.1.57264.1.5": "argoproj/argo-cd",
      "1.3.6.1.4.1.57264.1.6": "refs/tags/<version>",
      ...
使用 SLSA 证明验证容器映像

使用 slsa-github-generator 生成 SLSA 3 级出处。

以下命令将验证证明的签名及其颁发方式。它将包含 payloadType、payload 和签名。

根据slsa-verifier 文档运行以下命令:

# Get the immutable container image to prevent TOCTOU attacks https://github.com/slsa-framework/slsa-verifier#toctou-attacks
IMAGE=quay.io/argoproj/argocd:v2.7.0
IMAGE="${IMAGE}@"$(crane digest "${IMAGE}")
# Verify provenance, including the tag to prevent rollback attacks.
slsa-verifier verify-image "$IMAGE" \
    --source-uri github.com/argoproj/argo-cd \
    --source-tag v2.7.0

如果只想验证源存储库标签的主要版本或次要版本(而不是完整标签),请使用执行语义版本验证的 --source-versioned-tag

slsa-verifier verify-image "$IMAGE" \
    --source-uri github.com/argoproj/argo-cd \
    --source-versioned-tag v2 # Note: May use v2.7 for minor version verification.

证明有效负载包含不可伪造的出处,它是 base64 编码的,可以通过将 --print-provenance 选项传递给上面的命令来查看:

slsa-verifier verify-image "$IMAGE" \
    --source-uri github.com/argoproj/argo-cd \
    --source-tag v2.7.0 \
    --print-provenance | jq

如果你更喜欢使用共同签名,请按照以下说明操作

cosignslsa-verifier 均可用于验证镜像证明。请查看每个二进制文件的文档以获取详细说明。

使用 SLSA 证明验证 CLI 工件

每个版本都提供了单个证明 (argocd-cli.intoto.jsonl)。这可以与 slsa-verifier一起使用,以验证 CLI 二进制文件是否是使用 GitHub 上的 Argo CD 工作流生成的,并确保它已进行加密签名。

slsa-verifier verify-artifact argocd-linux-amd64 \
  --provenance-path argocd-cli.intoto.jsonl \
  --source-uri github.com/argoproj/argo-cd \
  --source-tag v2.7.0

如果只想验证源存储库标签的主要版本或次要版本(而不是完整标签),请使用执行语义版本验证的 --source-versioned-tag

slsa-verifier verify-artifact argocd-linux-amd64 \
  --provenance-path argocd-cli.intoto.jsonl \
  --source-uri github.com/argoproj/argo-cd \
  --source-versioned-tag v2 # Note: May use v2.7 for minor version verification.

有效载荷是不可伪造的来源,它是 base64 编码的,可以通过将 --print-provenance 选项传递给上面的命令来查看:

slsa-verifier verify-artifact argocd-linux-amd64 \
  --provenance-path argocd-cli.intoto.jsonl \
  --source-uri github.com/argoproj/argo-cd \
  --source-tag v2.7.0 \
  --print-provenance | jq
Sbom 验证

每个版本都提供一份单独的证明 (argocd-sbom.intoto.jsonl) 以及 sbom (sbom.tar.gz)。这可以与 slsa-verifier 一起使用,以验证 SBOM 是否是使用 GitHub 上的 Argo CD 工作流生成的,并确保它已加密签名。

slsa-verifier verify-artifact sbom.tar.gz \
  --provenance-path argocd-sbom.intoto.jsonl \
  --source-uri github.com/argoproj/argo-cd \
  --source-tag v2.7.0
在 Kubernetes 上验证
策略控制器

我们鼓励所有用户使用选择的准入/策略控制器来验证签名和出处。这样做将验证我们在将映像部署到 Kubernetes 集群之前是否构建了该映像。

Cosign 签名和 SLSA 出处与多种类型的准入控制器兼容。请参阅 cosign 文档slsa-github-generator 了解受支持的控制器。

7.11.TLS 配置

Argo CD 提供了三个可配置的入站 TLS 端点:

  • argocd-server 工作负载面向用户的端点,为 UI 和 API 提供服务
  • argocd-repo-server 的端点,由 argocd-serverargocd-application-controller 工作负载访问以请求存储库操作。
  • argocd-dex-server 的端点,由 argocd-server访问以处理 OIDC 身份验证。

默认情况下,无需进一步配置,这些端点将被设置为使用自动生成的自签名证书。但是,大多数用户都希望明确配置这些 TLS 端点的证书,可能使用自动化方式(例如 cert-manager)或使用他们自己的专用证书颁发机构。

为 argocd-server 配置 TLS

argocd-server 的入站 TLS 选项

可以通过设置命令行参数来为 argocd-server 工作负载配置某些 TLS 选项。可用的参数如下:

参数默认描述
–insecurefalse完全禁用 TLS
–tlsminversion1.2向客户端提供的最低 TLS 版本
–tlsmaxversion1.3向客户端提供的最高 TLS 版本
–tlsciphersTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_256_GCM_SHA384以冒号分隔的要提供给客户端的 TLS 密码套件列表
argocd-server 使用的 TLS 证书

有两种方法可以配置 argocd-server 使用的 TLS 证书:

  • 设置 argocd-server-tls 密钥中的 tls.crttls.key 密钥以保存证书的 PEM 数据和相应的私钥。argocd-server-tls 密钥可以是 tls 类型,但不一定非得是。
  • 设置 argocd-secret 密钥中的 tls.crttls.key 密钥以保存证书的 PEM 数据和相应的私钥。此方法被视为已弃用,仅用于向后兼容。更改 argocd-secret 不应再用于覆盖 TLS 证书。

Argo CD 决定为 argocd-server 的端点使用哪个 TLS 证书,如下所示:

  • 如果 argocd-server-tls 密钥存在并且在 tls.crttls.key 密钥中包含有效的密钥对,则这将用于 argocd-server 端点的证书。
  • 否则,如果 argocd-secret 密钥在 tls.crttls.key 密钥中包含有效密钥对,则这将用作 argocd-server 端点的证书。
  • 如果在上述两个密钥中均未找到 tls.crttls.key 密钥,Argo CD 将生成一个自签名证书并将其保存在 argocd-secret 密钥中。

argocd-server-tls 密钥仅包含 argocd-server 使用的 TLS 配置信息,可通过 cert-manager 或 SealedSecrets 等第三方工具安全管理

要从现有密钥对手动创建此密钥,可以使用 kubectl

kubectl create -n argocd secret tls argocd-server-tls \
  --cert=/path/to/cert.pem \
  --key=/path/to/key.pem

Argo CD 将自动获取对 argocd-server-tls 机密的更改,并且不需要重新启动 pod 来使用更新的证书。

为 argocd-repo-server 配置入站 TLS

argocd-repo-server 的入站 TLS 选项

可以通过设置命令行参数来为 argocd-repo-server 工作负载配置某些 TLS 选项。可用的参数如下:

参数默认描述
–insecurefalse完全禁用 TLS
–tlsminversion1.2向客户端提供的最低 TLS 版本
–tlsmaxversion1.3向客户端提供的最高 TLS 版本
–tlsciphersTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_256_GCM_SHA384以冒号分隔的要提供给客户端的 TLS 密码套件列表
argocd-repo-server 使用的入站 TLS 证书

要配置 argocd-repo-server 工作负载使用的 TLS 证书,请在 Argo CD 运行的命名空间中创建一个名为 argocd-repo-server-tls 的密钥,并将证书的密钥对存储在 tls.crttls.key 密钥中。如果此密钥不存在,argocd-repo-server 将生成并使用自签名证书。

要创建此密钥,您可以使用 kubectl

kubectl create -n argocd secret tls argocd-repo-server-tls \
  --cert=/path/to/cert.pem \
  --key=/path/to/key.pem

如果证书是自签名的,还需要将 ca.crt 与 CA 证书的内容一起添加到密钥中。

请注意,与 argocd-server 不同,argocd-repo-server 无法自动获取此机密的更改。如果创建(或更新)此密钥,则需要重新启动 argocd-repo-server pod

另请注意,证书应使用 argocd-repo-server 的正确 SAN 条目颁发,至少包含 DNS:argocd-repo-serverDNS:argocd-repo-server.argo-cd.svc 的条目,具体取决于工作负载如何连接到存储库服务器。

为 argocd-dex-server 配置入站 TLS

argocd-dex-server 的入站 TLS 选项

可以通过设置命令行参数来为 argocd-dex-server 工作负载配置某些 TLS 选项。可用的参数如下:

参数默认描述
–disable-tlsfalse完全禁用 TLS
argocd-repo-server 使用的入站 TLS 证书

要配置 argocd-repo-server 工作负载使用的 TLS 证书,请在 Argo CD 运行的命名空间中创建一个名为 argocd-repo-server-tls 的密钥,并将证书的密钥对存储在 tls.crttls.key 密钥中。如果此密钥不存在,argocd-repo-server 将生成并使用自签名证书。

要创建此密钥,可以使用 kubectl

kubectl create -n argocd secret tls argocd-repo-server-tls \
  --cert=/path/to/cert.pem \
  --key=/path/to/key.pem

如果证书是自签名的,还需要将 ca.crt 与 CA 证书的内容一起添加到密钥中。

请注意,与 argocd-server 不同,argocd-repo-server 无法自动获取此密钥的更改。如果创建(或更新)此密钥,则需要重新启动 argocd-repo-server pod

另请注意,证书应使用 argocd-repo-server 的正确 SAN 条目颁发,至少包含 DNS:argocd-repo-serverDNS:argocd-repo-server.argo-cd.svc的条目,具体取决于工作负载如何连接到存储库服务器。

为 argocd-dex-server 配置入站 TLS

argocd-dex-server 的入站 TLS 选项

可以通过设置命令行参数来为 argocd-dex-server 工作负载配置某些 TLS 选项。可用的参数如下:

参数默认描述
–disable-tlsfalse完全禁用 TLS
argocd-dex-server 使用的入站 TLS 证书

要配置 argocd-dex-server 工作负载使用的 TLS 证书,请在 Argo CD 运行的命名空间中创建一个名为 argocd-dex-server-tls 的密钥,并将证书的密钥对存储在 tls.crttls.key 密钥中。如果此密钥不存在,argocd-dex-server 将生成并使用自签名证书。

要创建此密钥,可以使用 kubectl

kubectl create -n argocd secret tls argocd-dex-server-tls \
  --cert=/path/to/cert.pem \
  --key=/path/to/key.pem

如果证书是自签名的,还需要将 ca.crt 与 CA 证书的内容一起添加到密钥中。

请注意,与 argocd-server 不同,argocd-dex-server 无法自动获取此密钥的更改。如果创建(或更新)此密钥,则需要重新启动 argocd-dex-server pod

另请注意,证书应使用 argocd-dex-server 的正确 SAN 条目颁发,至少包含 DNS:argocd-dex-serverDNS:argocd-dex-server.argo-cd.svc的条目,具体取决于工作负载如何连接到存储库服务器。

在 Argo CD 组件之间配置 TLS

配置 TLS 到 argocd-repo-server

argocd-serverargocd-application-controller 都使用 TLS 上的 gRPC API 与 argocd-repo-server 通信。默认情况下,argocd-repo-server 会在启动时生成一个非持久的自签名证书,用于其 gRPC 端点。由于 argocd-repo-server 无法连接到 K8s 控制平面 API,因此外部消费者无法使用此证书进行验证。出于这个原因,argocd-serverargocd-application-server 都将使用非验证连接来连接到 argocd-repo-server

要通过让 argocd-serverargocd-application-controller 验证 argocd-repo-server 端点的 TLS 证书来改变此行为以使其更加安全,需要执行以下步骤:

  • 创建持久的 TLS 证书供 argocd-repo-server 使用,如上所示
  • 重新启动 argocd-repo-server pod
  • 修改 argocd-serverargocd-application-controllerpod 启动参数,包含 --repo-server-strict-tls 参数

argocd-serverargocd-application-controller 工作负载现在将使用存储在 argocd-repo-server-tls 密钥中的证书来验证 argocd-repo-server 的 TLS 证书。

请确保证书的有效期合适。请记住,当您必须替换证书时,必须重新启动所有工作负载才能再次正常工作。

配置 TLS 到 argocd-dex-server

argocd-server 使用 HTTPS API 通过 TLS 与 argocd-dex-server 通信。默认情况下,argocd-dex-server 会在启动时生成一个非持久性自签名证书,用于其 HTTPS 端点。由于 argocd-dex-server 无法连接到 K8s 控制平面 API,因此外部消费者无法使用此证书进行验证。出于这个原因,argocd-server 将使用非验证连接与 argocd-dex-server 建立连接。

要通过让 argocd-server 验证 argocd-dex-server 端点的 TLS 证书来改变此行为以使其更加安全,需要执行以下步骤:

  • 创建持久的 TLS 证书以供 argocd-dex-server 使用,如上所示
  • 重新启动 argocd-dex-server pod
  • 修改 argocd-serverpod 启动参数以包含 --dex-server-strict-tls 参数。

rgocd-server 工作负载现在将使用存储在 argocd-dex-server-tls 密钥中的证书来验证 argocd-dex-server 的 TLS 证书。

请确保证书的有效期合适。请记住,当您必须替换证书时,必须重新启动所有工作负载才能再次正常工作。

禁用 argocd-repo-server 的 TLS

在某些涉及通过侧车代理进行 mTLS 的场景中(例如在服务网格中),可能希望将 argocd-serverargocd-application-controller 之间的连接配置为 argocd-repo-server 完全不使用 TLS。

在这种情况下,需要:

  • 通过在 pod 容器的启动参数中指定 --disable-tls 参数,配置 argocd-repo-server 并在 gRPC API 上禁用 TLS。此外,考虑通过指定 --listen 127.0.0.1 参数将监听地址限制为环回接口,这样不安全的端点就不会暴露在 pod 的网络接口上,但仍可供 side-car 容器使用。
  • 通过在 pod 容器的启动参数中指定参数 --repo-server-plaintext,配置 argocd-serverargocd-application-controller 以不使用 TLS 连接到 argocd-repo-server
  • 通过 --repo-server <address> 参数指定其地址,配置 argocd-serverargocd-application-controller 以连接到 side-car,而不是直接连接到 argocd-repo-server 服务

进行此更改后,argocd-serverargocd-application-controller 将使用纯文本连接到 side-car 代理,该代理将处理 argocd-repo-server 的 TLS side-car 代理的 TLS 的所有方面。

禁用 argocd-dex-server 的 TLS

在某些涉及通过侧车代理进行 mTLS 的场景中(例如在服务网格中),可能希望将 argocd-serverargocd-dex-server 之间的连接配置为完全不使用 TLS。
在这种情况下,需要:

  • 通过在 pod 容器的启动参数中指定 --disable-tls 参数,配置 argocd-dex-server 并在 HTTPS API 上禁用 TLS
  • 通过在 pod 容器的启动参数中指定参数 --dex-server-plaintext,配置 argocd-server 以不使用 TLS 连接 argocd-dex-server
  • 通过在 --dex-server <address> 参数指定其地址,配置 argocd-server 以连接到 side-car,而不是直接连接到 argocd-dex-server 服务

进行此项更改后,argocd-server 将使用纯文本连接到侧车代理,该代理将处理 argocd-dex-server 的 TLS 侧车代理的 TLS 所有方面。

7.12.集群引导

本指南适用于已经安装 Argo CD、拥有新集群并希望在该集群中安装许多应用程序的操作员。

没有一种特定的模式可以解决这个问题,例如,可以编写脚本来创建应用程序,甚至可以手动创建它们。但是,Argo CD 的用户倾向于使用应用程序模式。

在任意项目中创建应用程序的能力是管理员级别的能力。只有管理员才应该拥有对父应用程序源存储库的推送访问权限。管理员应该审查对该存储库的拉取请求,特别注意每个应用程序中的项目字段。有权访问安装 Argo CD 的命名空间的项目实际上具有管理员级别的权限。

应用程序的应用程序模式

声明性地指定一个仅由其他应用程序组成的 Argo CD 应用程序。
在这里插入图片描述

Helm 示例

此示例展示了如何使用 Helm 来实现这一点。当然,如果你愿意,也可以使用其他工具。
Git 存储库的典型布局可能是:

├── Chart.yaml
├── templates
│   ├── guestbook.yaml
│   ├── helm-dependency.yaml
│   ├── helm-guestbook.yaml
│   └── kustomize-guestbook.yaml
└── values.yaml

Chart.yaml 是样板。
templates 为每个子应用程序包含一个文件,大致如下:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  destination:
    namespace: argocd
    server: {{ .Values.spec.destination.server }}
  project: default
  source:
    path: guestbook
    repoURL: https://github.com/argoproj/argocd-example-apps
    targetRevision: HEAD

将同步策略设置为自动 + 修剪,这样当清单发生更改时,子应用会自动创建、同步和删除,但可能希望禁用此功能。我还添加了终结器,这将确保您的应用被正确删除。

将修订版本修复为特定的 Git 提交 SHA,以确保即使子应用程序存储库发生变化,应用程序也只会在父应用程序更改该修订版本时更改。或者,可以将其设置为 HEAD 或分支名称。

由于可能想要覆盖集群服务器,这是一个模板值。

values.yaml 包含默认值:

spec:
  destination:
    server: https://kubernetes.default.svc

接下来,需要创建并同步您的父应用程序,例如通过 CLI:

argocd app create apps \
    --dest-namespace argocd \
    --dest-server https://kubernetes.default.svc \
    --repo https://github.com/argoproj/argocd-example-apps.git \
    --path apps  
argocd app sync apps  

父应用程序将显示为同步,但子应用程序将不同步:
在这里插入图片描述

注意:可能需要修改此行为以分批引导集群;有关更改此行为的信息,请参阅 v1.8 升级说明

可以通过 UI 进行同步,首先通过正确的标签进行过滤:
在这里插入图片描述
然后选择“out of sync”的应用程序并sync:
在这里插入图片描述
或者通过 CLI:

argocd app sync -l app.kubernetes.io/instance=apps

GitHub 上查看示例

级联删除

如果你想确保在删除父应用时删除子应用及其所有资源,请确保在应用程序定义中添加适当的终结器

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
 ...

7.13.密钥管理

Argo CD 对于如何管理密钥没有任何意见。有很多方法可以做到这一点,并且没有一刀切的解决方案。

许多解决方案使用插件将密钥注入应用程序清单。请参阅下面的“降低机密注入插件的风险”,以确保您安全地使用这些插件。

以下是人们实施 GitOps 密钥的一些方法:

  • Bitnami Sealed Secrets
  • External Secrets Operator
  • Hashicorp Vault
  • Bank-Vaults
  • Helm Secrets
  • Kustomize secret generator plugins
  • aws-secret-operator
  • KSOPS
  • argocd-vault-plugin
  • argocd-vault-replacer
  • Kubernetes Secrets Store CSI Driver
  • Vals-Operator

有关讨论,请参阅#1364

降低密钥注入插件的风险

Argo CD 将插件生成的清单以及注入的密钥缓存在其 Redis 实例中。这些清单也可通过 repo-server API(gRPC 服务)获取。这意味着任何有权访问 Redis 实例或 repo-server 的人都可以获取密钥。

考虑以下步骤来减轻密钥注入插件的风险:

  • 设置网络策略以防止直接访问 Argo CD 组件(Redis 和 repo-server)。确保集群支持这些网络策略并可以实际执行它们。
  • 考虑在其自己的集群上运行 Argo CD,并且不运行其他应用程序。
  • 在 Redis 实例上启用密钥验证(当前仅支持非 HA Argo CD 安装)。

7.14.容灾

可以使用 argocd admin 导入和导出所有 Argo CD 数据。
确保 ~/.kube/config 指向 Argo CD 集群。

确定正在运行的 Argo CD 版本:

argocd version | grep server
# ...
export VERSION=v1.0.1

导出至备份:

docker run -v ~/.kube:/home/argocd/.kube --rm quay.io/argoproj/argocd:$VERSION argocd admin export > backup.yaml

从备份导入:

docker run -i -v ~/.kube:/home/argocd/.kube --rm quay.io/argoproj/argocd:$VERSION argocd admin import - < backup.yaml

如果在不同于默认的命名空间上运行 Argo CD,请记住传递命名空间参数 (-n)。如果在错误的命名空间中运行“argocd admin export”,它不会失败。

7.15.协调优化

默认情况下,每次属于 Argo CD 应用程序的资源发生变化时,它都会刷新。

Kubernetes 控制器经常会定期更新它们监视的资源,从而导致应用程序持续进行协调操作,并导致 argocd-application-controller 的 CPU 使用率过高。Argo CD 允许选择性地忽略跟踪资源的特定字段上的资源更新。

当忽略资源更新时,如果资源的健康状态没有改变,则此资源所属的应用程序将不会被协调。

系统级配置

Argo CD 允许使用 RFC6902 JSON 补丁和 JQ 路径表达式忽略特定 JSON 路径的资源更新。可以在 argocd-cm ConfigMap 的 resource.customizations键中为指定组和类型配置它。

该功能位于标志后面。要启用它,请在 argocd-cm ConfigMap 中将 resource.ignoreResourceUpdatesEnabled 设置为true

以下是忽略 ExternalSecret 资源的 refreshTime 状态字段的自定义示例:

data:
  resource.customizations.ignoreResourceUpdates.external-secrets.io_ExternalSecret: |
    jsonPointers:
    - /status/refreshTime
    # JQ equivalent of the above:
    # jqPathExpressions:
    # - .status.refreshTime

可以配置 ignoreResourceUpdates 以应用于 Argo CD 实例管理的每个应用程序中的所有跟踪资源。为此,可以像以下示例一样配置资源自定义:

data:
  resource.customizations.ignoreResourceUpdates.all: |
    jsonPointers:
    - /status
使用 ignoreDifferences 忽略协调

也可以使用现有的系统级 ignoreDifferences 自定义来忽略资源更新。无需复制所有配置,可以使用 ignoreDifferencesOnResourceUpdates设置将所有忽略的差异添加为忽略的资源更新:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
data:
  resource.compareoptions: |
    ignoreDifferencesOnResourceUpdates: true

默认配置

默认情况下,所有资源的元数据字段generation、resourceVersion和managedFields都会被忽略。

寻找可以忽略的资源

当资源更改触发刷新时,应用程序控制器会记录日志。可以使用这些日志来查找高流失率的资源类型,然后检查这些资源以找出要忽略的字段。

要查找这些日志,请搜索“Requesting app refresh caused by object update”。日志包括 api-version 和 kind 的结构化字段。按 api-versionkind 计算触发的刷新次数应该可以发现高流失率的资源类型。

这些日志属于debug级别。请将应用程序控制器的日志级别配置为debug。

一旦确定了一些经常更改的资源,就可以尝试确定哪些字段正在更改。以下是一种方法:

kubectl get <resource> -o yaml > /tmp/before.yaml
# Wait a minute or two.
kubectl get <resource> -o yaml > /tmp/after.yaml
diff /tmp/before.yaml /tmp/after

差异可以让你了解哪些字段正在发生变化并且可能应该被忽略。

检查资源更新是否被忽略

每当 Argo CD 由于忽略资源更新而跳过刷新时,控制器都会记录以下行:“Ignoring change of object because none of the watched resource fields have changed”。

在应用程序控制器日志中搜索此行以确认您的资源忽略规则正在被应用。

这些日志属于debug级别。请将应用程序控制器的日志级别配置为debug。

例子

argoproj.io/Application

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
data:
  resource.customizations.ignoreResourceUpdates.argoproj.io_Application: |
    jsonPointers:
    # Ignore when ownerReferences change, for example when a parent ApplicationSet changes often.
    - /metadata/ownerReferences
    # Ignore reconciledAt, since by itself it doesn't indicate any important change.
    - /status/reconciledAt
    jqPathExpressions:
    # Ignore lastTransitionTime for conditions; helpful when SharedResourceWarnings are being regularly updated but not
    # actually changing in content.
    - .status.conditions[].lastTransitionTime

7.16.Git Webhook 配置

概述

Argo CD 每三分钟轮询一次 Git 存储库,以检测清单的更改。为了消除轮询延迟,可以配置 API 服务器以接收 webhook 事件。Argo CD 支持来自 GitHub、GitLab、Bitbucket、Bitbucket Server、Azure DevOps 和 Gogs 的 Git webhook 通知。以下内容介绍了如何为 GitHub 配置 Git webhook,但相同的过程也适用于其他提供商。

Webhook 处理程序不会区分分支事件和分支名称和标签名称相同的标签事件。推送到分支 x 的钩子事件将触发指向同一存储库且targetRevision: refs/tags/x 的应用的刷新。

1.在 Git 提供程序中创建 WebHook

在 Git 提供程序中,导航到可以配置 webhook 的设置页面。在 Git 提供程序中配置的有效负载 URL 应使用 Argo CD 实例的 /api/webhook 端点(例如 https://argocd.example.com/api/webhook)。如果希望使用共享密钥,请在密钥中输入任意值。此值将在下一步配置 webhook 时使用。

Github

在这里插入图片描述
在 GitHub 中创建 webhook 时,“内容类型”需要设置为“application/json”。用于处理钩子的库不支持默认值“application/x-www-form-urlencoded

2.使用 WebHook Secret 配置 Argo CD(可选)

配置 webhook 共享密钥是可选的,因为即使有未经身份验证的 webhook 事件,Argo CD 仍会刷新与 Git 存储库相关的应用程序。这样做是安全的,因为 webhook 有效负载的内容被视为不受信任,并且只会导致应用程序刷新(该过程已经以三分钟为间隔发生)。如果 Argo CD 可公开访问,则建议配置 webhook 密钥以防止 DDoS 攻击。

在 argocd-secret Kubernetes 密钥中,使用步骤 1 中配置的 Git 提供程序的 webhook 密钥配置以下密钥之一。

Provider K8sSecret Key
GitHubwebhook.github.secret
GitLabwebhook.gitlab.secret
BitBucketwebhook.bitbucket.uuid
BitBucketServerwebhook.bitbucketserver.secret
Gogswebhook.gogs.secret
Azure DevOpswebhook.azuredevops.username
webhook.azuredevops.password
编辑 Argo CD Kubernetes 密钥:
kubectl edit secret argocd-secret -n argocd

提示:为了方便输入密钥,Kubernetes 支持在 stringData 字段中输入密钥,这样就省去了对值进行 base64 编码并将其复制到 data字段的麻烦。只需将步骤 1 中创建的共享 webhook 密钥复制到 stringData 字段下相应的 GitHub/GitLab/BitBucket 密钥即可:

apiVersion: v1
kind: Secret
metadata:
  name: argocd-secret
  namespace: argocd
type: Opaque
data:
...

stringData:
  # github webhook secret
  webhook.github.secret: shhhh! it's a GitHub secret

  # gitlab webhook secret
  webhook.gitlab.secret: shhhh! it's a GitLab secret

  # bitbucket webhook secret
  webhook.bitbucket.uuid: your-bitbucket-uuid

  # bitbucket server webhook secret
  webhook.bitbucketserver.secret: shhhh! it's a Bitbucket server secret

  # gogs server webhook secret
  webhook.gogs.secret: shhhh! it's a gogs server secret

  # azuredevops username and password
  webhook.azuredevops.username: admin
  webhook.azuredevops.password: secret-password

保存后,更改将自动生效。

替代方案

如果想将 webhook 数据存储在另一个 Kubernetes Secret 中,而不是 argocd-secret 中。ArgoCD 知道检查 Kubernetes Secret 中数据下的密钥,这些密钥以 $ 开头,然后是 Kubernetes Secret 名称和 :(冒号)。

Syntax: $<k8s_secret_name>:<a_key_in_that_k8s_secret>

注意:Secret 必须有标签 app.kubernetes.io/part-of: argocd

7.17.资源运行状况

概述

Argo CD 为几种标准 Kubernetes 类型提供内置健康评估,然后将其反映到整个应用程序的健康状况中。针对特定类型的 Kubernetes 资源进行以下检查:

Deployment, ReplicaSet, StatefulSet, DaemonSet
  • 观察到的一代等于期望的一代。
  • 更新的副本数量等于所需副本数量。
Service

如果服务类型为 LoadBalancer类型,则 status.loadBalancer.ingress 列表非空,并且至少有一个hostnameIP 值。

Ingress

status.loadBalancer.ingress 列表非空,至少有一个hostnameIP 值。

Job

如果作业 .spec.suspended 设置为true,则该作业和应用程序运行状况将被标记为暂停(suspended)。

PersistentVolumeClaim

status.phaseBound

Argocd App

argoproj.io/Application CRD 的健康评估已在 argocd 1.8 中删除(有关更多信息,请参阅 #3781)。如果使用 app-of-apps 模式并使用同步波编排同步,则可能需要恢复它。在 argocd-cm ConfigMap 中添加以下资源自定义:

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-cm
    app.kubernetes.io/part-of: argocd
data:
  resource.customizations: |
    argoproj.io/Application:
      health.lua: |
        hs = {}
        hs.status = "Progressing"
        hs.message = ""
        if obj.status ~= nil then
          if obj.status.health ~= nil then
            hs.status = obj.status.health.status
            if obj.status.health.message ~= nil then
              hs.message = obj.status.health.message
            end
          end
        end
        return hs

定制健康检查

Argo CD支持LUA编写的自定义健康检查。

由于资源控制器中的错误而受到入口或状态全部资源的影响,因此受到已知问题的影响。

拥有一个自定义资源,ARGO CD没有内置的健康检查。

有两种配置自定义健康检查的方法。接下来的两个部分描述了这些方法。

方式1.在ArgoCD-CM Configmap中定义自定义健康检查

可以定义自定义健康检查

  resource.customizations: |
    <group/kind>:
      health.lua: |

ArgoCD-CM领域。如果您使用的是ArgoCD-operator,则Argocd-operator ResourceCustomizations覆盖了这一点。

以下示例演示了CERT-MANAGER.IO/certificate的健康检查。

data:
  resource.customizations: |
    cert-manager.io/Certificate:
      health.lua: |
        hs = {}
        if obj.status ~= nil then
          if obj.status.conditions ~= nil then
            for i, condition in ipairs(obj.status.conditions) do
              if condition.type == "Ready" and condition.status == "False" then
                hs.status = "Degraded"
                hs.message = condition.message
                return hs
              end
              if condition.type == "Ready" and condition.status == "True" then
                hs.status = "Healthy"
                hs.message = condition.message
                return hs
              end
            end
          end
        end

        hs.status = "Progressing"
        hs.message = "Waiting for certificate"
        return hs

为了防止重复自定义健康检查是否有潜在的多个资源,也可以在资源类型和资源组中的任何地方指定通配符,例如:

  resource.customizations: |
    ec2.aws.crossplane.io/*:
      health.lua: |
        ...
  resource.customizations: |
    "*.aws.crossplane.io/*":
      health.lua: | 
        ...

如果通配符以 *开头,请注意“资源自定义健康”部分中所需的引号。

obj是包含资源的全局变量。脚本必须返回具有状态和可选消息字段的对象。自定义健康检查可能会返回以下健康状况之一:

  • Healthy 资源很健康
  • Progressing 资源还不健康,但仍在取得进步,可能很快就会健康
  • Degraded 资源退化
  • Suspended 该资源被暂停,等待一些外部事件恢复(例如,暂停的Cronjob或暂停的部署)

默认情况下,健康通常返回Progressing 状态。

注意:作为一种安全措施,默认情况下将禁用对标准LUA库的访问。管理员可以通过设置资源来控制访问。customizations.useopenlibs。<group_kind>。在下面的示例中,启用了标准库,以进行cert-manager.io/certificate的健康检查。

data:
  resource.customizations: |
    cert-manager.io/Certificate:
      health.lua.useOpenLibs: true
      health.lua: |
        # Lua standard libraries are enabled for this script
方式2.贡献自定义健康检查

可以将健康检查捆绑到Argo CD中。自定义健康检查脚本位于https://github.com/argoproj/argo-cdresource_customizations 目录中。这必须具有以下目录结构:

argo-cd
|-- resource_customizations
|    |-- your.crd.group.io               # CRD group
|    |    |-- MyKind                     # Resource kind
|    |    |    |-- health.lua            # Health check
|    |    |    |-- health_test.yaml      # Test inputs and expected results
|    |    |    +-- testdata              # Directory with test resource YAML definitions

每个健康检查必须在health_test.yaml文件中定义测试。 health_test.yaml是一个具有以下结构的YAML文件:

tests:
- healthStatus:
    status: ExpectedStatus
    message: Expected message
  inputPath: testdata/test-resource-definition.yaml

要测试实施的自定义健康检查,请运行go test -v ./util/lua/

PR#1139是Cert Manager CRDS自定义健康检查的示例。
请注意,不支持使用通配符捆绑的健康检查。

健康检查

Argo CD应用程序的健康是根据其直接孩子资源的健康(来源控制中代表的资源)推断出来的。

但是,资源的健康不是从孩子资源中继承的 - 它仅使用有关资源本身的信息来计算。资源状态字段可能或可能不包含有关孩子资源健康的信息,资源的健康检查可能会或可能不会考虑到这些信息。

缺乏继承是设计。无法从子女那里推断出资源的健康,因为儿童资源的健康可能与父母资源的健康无关。例如,部署的健康不一定会受到其Pod健康状况的影响。

App (healthy)
└── Deployment (healthy)
    └── ReplicaSet (healthy)
        └── Pod (healthy)
    └── ReplicaSet (unhealthy)
        └── Pod (unhealthy)

如果希望孩子资源的健康影响其父母的健康,则需要配置父母的健康检查以考虑孩子的健康。由于只有父级资源的状态可用于健康检查,因此父级资源的控制器需要使子资源的健康在父级资源的状态字段中可用。

App (healthy)
└── CustomResource (healthy) <- This resource's health check needs to be fixed to mark the App as unhealthy
    └── CustomChildResource (unhealthy)

7.18.资源动作

概述

Argo CD允许操作员定义用户可以在特定资源类型上执行的自定义操作。这用于内部用来提供诸如Daemonset restart或retry Argo推出之类的动作。

操作员可以以LUA脚本的形式将操作添加到自定义资源中,并扩展这些功能。

自定义资源操作

Argo CD支持LUA编写的自定义资源操作。

  • 拥有一个自定义资源,Argo CD不提供任何内置操作。
  • 具有通常执行的手动任务,如果用户通过kubectl执行可能会易于错误

资源动作对单个对象作用。
可以在argocd-cm ConfigMap中定义自己的自定义资源操作。

自定义资源操作类型
修改源资源的动作

此操作修改并返回源资源。这种动作是直到2.8的唯一一个可用的动作,并且仍然得到支持。

产生新资源或修改资源列表的动作

2.8中引入的alpha功能。
此操作返回了受影响资源的列表,每个受影响的资源都有K8S资源和可执行的操作。
当前支持的操作是“create”和“patch”,“patch”仅支持源资源。
通过为返回列表中的每个此类资源指定“create”操作,可以创建新资源。
通过为返回列表中的每个此类资源指定“create”操作,可以创建新资源。
返回的资源之一可以是修改后的源对象,如果需要,可以使用“patch”操作。
请参阅下面的定义示例。

在ArgoCD-CM Configmap中定义自定义资源操作

可以在资源中定义自定义资源操作。resource.customizations.actions.<group_kind>的字段。以下示例演示了Cronjob资源的一组自定义操作,每个此类操作都返回修改后的Cronjob。自定义密钥以resource.customizations.actions.<apiGroup_Kind>的格式。

resource.customizations.actions.batch_CronJob: |
  discovery.lua: |
    actions = {}
    actions["suspend"] = {["disabled"] = true}
    actions["resume"] = {["disabled"] = true}

    local suspend = false
    if obj.spec.suspend ~= nil then
        suspend = obj.spec.suspend
    end
    if suspend then
        actions["resume"]["disabled"] = false
    else
        actions["suspend"]["disabled"] = false
    end
    return actions
  definitions:
  - name: suspend
    action.lua: |
      obj.spec.suspend = true
      return obj
  - name: resume
    action.lua: |
      if obj.spec.suspend ~= nil and obj.spec.suspend then
          obj.spec.suspend = false
      end
      return obj

Discovery.lua脚本必须返回一个键名代表操作名称的表。可以选择包含逻辑以启用或禁用基于当前对象状态的某些操作。

每个操作名称必须在定义列表中用随附的操作列表表示。LUA脚本以控制资源修改。 OBJ是包含资源的全局变量。每个操作脚本都返回资源的可选修改版本。在此示例中,我们只是将.spec.suspend设置为truefalse

通过自定义动作创建新资源

通过Argo CD UI创建资源是与Gitops原则的有意,战略性的。建议很少使用此功能,仅用于不属于应用程序状态的资源。

调用操作的资源将称为源资源。
新的资源和所有作为隐性创建的资源必须在AppProject级别上允许,否则创建将失败。

通过自定义操作创建源资源孩子资源
如果新资源代表源资源的K8S孩子,则必须在新资源上设置源资源所有者Rereference。

这是一个示例LUA片段,它负责构建一个是源cronjob资源的工作资源 - OBJ是一个全局变量,其中包含源资源:

-- ...
ownerRef = {}
ownerRef.apiVersion = obj.apiVersion
ownerRef.kind = obj.kind
ownerRef.name = obj.metadata.name
ownerRef.uid = obj.metadata.uid
job = {}
job.metadata = {}
job.metadata.ownerReferences = {}
job.metadata.ownerReferences[1] = ownerRef
-- ...

通过自定义行动创建独立的孩子资源
如果新资源独立于源资源,则这种新资源的默认行为是,源资源的应用程序不知道它(因为它不是所需状态的一部分,也不是所有者Rereference)。

为了使应用程序了解新资源,必须在资源上设置app.kubernetes.io/instance标签(或其他AgroCD跟踪标签,如果配置)。
它可以从源资源中复制,例如:

-- ...
newObj = {}
newObj.metadata = {}
newObj.metadata.labels = {}
newObj.metadata.labels["app.kubernetes.io/instance"] = obj.metadata.labels["app.kubernetes.io/instance"]
-- ...

虽然新资源将成为该应用程序的一部分,并将其跟踪标签制定到位,但如果在应用程序上设置了Auto Prune,它将立即删除。

要保留资源,请使用此LUA代码片段设置Prune = false注释:

-- ...
newObj.metadata.annotations = {}
newObj.metadata.annotations["argocd.argoproj.io/sync-options"] = "Prune=false"
-- ...

资源和应用程序现在将出现在同步中 - 这是创建不属于所需状态一部分的资源时的预期ARGOCD行为。

如果想将该应用程序视为同步,请在LUA代码中添加以下资源注释:

产生资源列表的动作 - 一个完整的示例:

resource.customizations.actions.ConfigMap: |
  discovery.lua: |
    actions = {}
    actions["do-things"] = {}
    return actions
  definitions:
  - name: do-things
    action.lua: |
      -- Create a new ConfigMap
      cm1 = {}
      cm1.apiVersion = "v1"
      cm1.kind = "ConfigMap"
      cm1.metadata = {}
      cm1.metadata.name = "cm1"
      cm1.metadata.namespace = obj.metadata.namespace
      cm1.metadata.labels = {}
      -- Copy ArgoCD tracking label so that the resource is recognized by the App
      cm1.metadata.labels["app.kubernetes.io/instance"] = obj.metadata.labels["app.kubernetes.io/instance"]
      cm1.metadata.annotations = {}
      -- For Apps with auto-prune, set the prune false on the resource, so it does not get deleted
      cm1.metadata.annotations["argocd.argoproj.io/sync-options"] = "Prune=false"     
      -- Keep the App synced even though it has a resource that is not in Git
      cm1.metadata.annotations["argocd.argoproj.io/compare-options"] = "IgnoreExtraneous"         
      cm1.data = {}
      cm1.data.myKey1 = "myValue1"
      impactedResource1 = {}
      impactedResource1.operation = "create"
      impactedResource1.resource = cm1

      -- Patch the original cm
      obj.metadata.labels["aKey"] = "aValue"
      impactedResource2 = {}
      impactedResource2.operation = "patch"
      impactedResource2.resource = obj

      result = {}
      result[1] = impactedResource1
      result[2] = impactedResource2
      return result       

7.18.自定义工具

Argo CD捆绑包的支持版本的模板工具(Helm,Kustomize,KS,JSONNET)作为其容器图像的一部分。有时,可能希望使用除argo cd束外的工具的特定版本。这样做的一些原因可能是:

  • 由于错误或错误修复,要升级/降级到工具的特定版本。
  • 要安装kustomize的ConfigMap/Secret Generators使用的其他依赖项。 (例如 curl, vault, gpg, AWS CLI)
  • 安装配置管理插件

由于Argo CD回购服务器是负责生成Kubernetes表现出的单一服务,因此可以自定义使用环境所需的替代工具链。

通过卷挂载添加工具

第一种技术是使用初始容器和卷来将不同版本的工具复制到repo-server容器中。在下面的示例中,初始容器正在覆盖与Argo CD中捆绑的版本不同版本的Helm二进制文件:

    spec:
      # 1. Define an emptyDir volume which will hold the custom binaries
      volumes:
      - name: custom-tools
        emptyDir: {}
      # 2. Use an init container to download/copy custom binaries into the emptyDir
      initContainers:
      - name: download-tools
        image: alpine:3.8
        command: [sh, -c]
        args:
        - wget -qO- https://storage.googleapis.com/kubernetes-helm/helm-v2.12.3-linux-amd64.tar.gz | tar -xvzf - &&
          mv linux-amd64/helm /custom-tools/
        volumeMounts:
        - mountPath: /custom-tools
          name: custom-tools
      # 3. Volume mount the custom binary to the bin directory (overriding the existing version)
      containers:
      - name: argocd-repo-server
        volumeMounts:
        - mountPath: /usr/local/bin/helm
          name: custom-tools
          subPath: helm

BYOI (Build Your Own Image)

有时更换二进制是不够的,需要安装其他依赖项。以下示例从Dockerfile构建了一个完全自定义的回购服务器,安装了可能需要的额外依赖项。

FROM argoproj/argocd:v2.5.4 # Replace tag with the appropriate argo version

# Switch to root for the ability to perform install
USER root

# Install tools needed for your repo-server to retrieve & decrypt secrets, render manifests 
# (e.g. curl, awscli, gpg, sops)
RUN apt-get update && \
    apt-get install -y \
        curl \
        awscli \
        gpg && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
    curl -o /usr/local/bin/sops -L https://github.com/mozilla/sops/releases/download/3.2.0/sops-3.2.0.linux && \
    chmod +x /usr/local/bin/sops

# Switch back to non-root user
USER $ARGOCD_USER_ID

7.19.定制样式

Argo CD从Argo-UI项目中进口了其大多数UI样式表。有时,可能希望将UI的某些组件自定义,或者有助于区分在不同环境中运行的Argo CD的多个实例。

可以通过将URL提供给远程托管的CSS文件,也可以通过将CSS文件直接加载到ArgOCD-Server容器中来应用此类自定义样式。这两种机制都是通过修改ArgoCD-CM ConfigMap来驱动的。

通过远程URL添加样式

第一个方法只需要将远程URL添加到ArgoCD-CM ConfigMap:

argocd-cm

---
apiVersion: v1
kind: ConfigMap
metadata:
  ...
  name: argocd-cm
data:
  ui.cssurl: "https://www.example.com/my-styles.css"

通过卷挂载添加样式

第二种方法需要将CSS文件直接安装到ArgoCD-Server容器上,然后为ArgoCD-CM提供正确配置的该文件的路径。在下面的示例中,CSS文件实际上是在单独的ConfigMap内部定义的(通过在InitContainer中生成或下载CSS文件可以实现相同的效果):

argocd-cm

---
apiVersion: v1
kind: ConfigMap
metadata:
  ...
  name: argocd-cm
data:
  ui.cssurl: "./custom/my-styles.css"

请注意,CSSURL应相对于“/shared/app”目录指定;不是绝对的路径。

argocd-styles-cm

---
apiVersion: v1
kind: ConfigMap
metadata:
  ...
  name: argocd-styles-cm
data:
  my-styles.css: |
    .sidebar {
      background: linear-gradient(to bottom, #999, #777, #333, #222, #111);
    }

argocd-server

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: argocd-server
  ...
spec:
  template:
    ...
    spec:
      containers:
      - command:
        ...
        volumeMounts:
        ...
        - mountPath: /shared/app/custom
          name: styles
      ...
      volumes:
      ...
      - configMap:
          name: argocd-styles-cm
        name: styles

请注意,CSS文件应安装在“/shared/app”目录(例如“/shared/app/custom”)的子目录中。否则,浏览器可能不会以“不正确的MIME类型”错误导入该文件。可以使用argocd-cmd-params-cm.yaml中键为server.staticassets 更改子目录。

开发样式叠加

注入CSS文件中指定的样式应特定于Argo-UI中定义的组件和类。建议通过使用浏览器的内置开发人员工具来测试您希望首先应用的样式。为了获得更全面的体验,可能希望使用Argo CD UI Dev服务器构建一个单独的项目。

横幅:Banners

Argo CD可以选择显示横幅,该横幅可用于通知您的用户即将进行的维护和操作更改。可以通过使用ArgoCD-CM ConfigMap中的ui.bannercontent 字段指定横幅消息来启用此功能,而Argo CD将在每个UI页面的顶部显示此消息。您可以选择通过设置ui.bannerurl添加此消息的链接。您还可以通过将ui.bannerpermanent设置为TRUE并通过使用ui.bannerposition将其位置更改为“bottom”,从而使横幅粘性(永久permanent)变为“”或“bottom”:“both”,允许横幅在顶部和底部显示,或ui.bannerposition:“bottom”仅在底部显示。

argocd-cm

---
apiVersion: v1
kind: ConfigMap
metadata:
  ...
  name: argocd-cm
data:
    ui.bannercontent: "Banner message linked to a URL"
    ui.bannerurl: "www.bannerlink.com"
    ui.bannerpermanent: "true"
    ui.bannerposition: "bottom"

在这里插入图片描述

7.20.UI自定义

默认应用程序详细信息视图

默认情况下,应用程序详细信息将显示Tree视图。
可以通过应用程序来配置这一点,通过将pref.argocd.argoproj.io/default-view注释设置为:接受:tree, pods, network, list作为值。

对于PODS视图,可以使用pref.argocd.argoproj.io/default-pod-sort注释来配置默认分组机制,接受:node, parentResource, topLevelResource作为值之一。

7.21.指标

Argo CD揭露了每个服务器的不同集合量指标。

应用程序控制器指标

关于应用的指标。在ArgoCD-Metrics上 argocd-metrics:8082/metrics 端点。

MetricTypeDescription
argocd_app_infogauge有关应用程序的信息。它包含诸如Sync_status和Health_status之类的标签,这些标签反映了Argo CD中的应用状态。
argocd_app_k8s_request_totalcounter在申请对帐期间执行的Kubernetes请求数量
argocd_app_labelsgaugeArgo应用程序标签转换为Prometheus标签。默认情况下禁用。请参阅下面有关如何启用它的部分。
argocd_app_reconcilehistogram申请和解绩效。
argocd_app_sync_totalcounter申请同步历史记录的计数器
argocd_cluster_api_resource_objectsgauge缓存中的K8S资源对象的数量。
argocd_cluster_api_resourcesgauge受监控的Kubernetes API资源的数量。
argocd_cluster_cache_age_secondsgauge群集缓存年龄在几秒钟内。
argocd_cluster_connection_statusgaugeK8S群集当前连接状态。
argocd_cluster_events_totalcounter过程数量K8S资源事件。
argocd_cluster_infogauge有关集群的信息。
argocd_kubectl_exec_pendinggauge待处理的kubectl执行次数
argocd_kubectl_exec_totalcounterkubectl执行的数量
argocd_redis_request_durationhistogramREDIS请求持续时间。
argocd_redis_request_totalcounter在申请核对期间执行的REDIS请求数量

如果将Argo CD与许多应用程序以及项目创建和删除一起使用,则指标页面将保持在您的应用程序和项目历史记录中。如果由于已删除的资源而导致大量的度量基数,遇到问题,则可以安排重置度量标准以使用应用程序控制器标志清洁历史记录。示例:--metrics-cache-expiration="24h0m0s"

将申请标签视为Prometheus指标

在某些用例中,Argo CD应用程序包含希望将其视为Prometheus指标的标签。一些例子是:

  • 将团队名称作为标签,以允许将警报路由到特定的接收器
  • 创建仪表板被业务部门分解

由于应用程序标签是针对每个公司的特定的,因此该功能默认情况下是禁用的。要启用它,请将--metrics-application-labels标志添加到Argo CD应用程序控制器中。

下面的示例将使Argo CD应用程序标签team-namebusiness-unit与Prometheus:

containers:
- command:
  - argocd-application-controller
  - --metrics-application-labels
  - team-name
  - --metrics-application-labels
  - business-unit

在这种情况下,指标看起来像:

# TYPE argocd_app_labels gauge
argocd_app_labels{label_business_unit="bu-id-1",label_team_name="my-team",name="my-app-1",namespace="argocd",project="important-project"} 1
argocd_app_labels{label_business_unit="bu-id-1",label_team_name="my-team",name="my-app-2",namespace="argocd",project="important-project"} 1
argocd_app_labels{label_business_unit="bu-id-2",label_team_name="another-team",name="my-app-3",namespace="argocd",project="important-project"} 1

API服务器指标

有关API服务器API请求和响应活动的指标(请求总计,响应代码等)。argocd-server-metrics:8083/metrics端点。

MetricTypeDescription
argocd_redis_request_durationhistogramREDIS请求持续时间。
argocd_redis_request_totalcounter在申请对帐期间执行的Kubernetes请求数量。
grpc_server_handled_totalcounter无论成功或故障如何,服务器上完成的RPC总数。
grpc_server_msg_sent_totalcounter服务器发送的GRPC流消息的总数。
argocd_proxy_extension_request_total反向发送到配置的代理扩展名的请求数。
argocd_proxy_extension_request_duration_secondshistogram在Argo CD API服务器和代理扩展后端之间的几秒钟内请求持续时间。

存储服务器指标

关于远程服务器的指标。在argocd-repo-server:8084/metrics

MetricTypeDescription
argocd_git_request_duration_secondshistogramGIT请求持续时间秒。
argocd_git_request_totalcounterRepo服务器执行的GIT请求数量
argocd_git_fetch_fail_totalcounterrepo服务器的git提取请求失败数量
argocd_redis_request_duration_secondshistogramREDIS请求持续时间秒。
argocd_redis_request_totalcounter在申请对帐期间执行的Kubernetes请求数量。
argocd_repo_pending_request_totalgauge需要存储库锁的待处理请求数量

Prometheus操作员

如果使用Prometheus操作员,则可以使用以下服务示例清单。添加一个安装Argo CD的名称空间,然后将元数据更改为Prometheus选择的标签名称。

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-metrics
  labels:
    release: prometheus-operator
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-metrics
  endpoints:
  - port: metrics
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-server-metrics
  labels:
    release: prometheus-operator
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-server-metrics
  endpoints:
  - port: metrics
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-repo-server-metrics
  labels:
    release: prometheus-operator
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-repo-server
  endpoints:
  - port: metrics
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-applicationset-controller-metrics
  labels:
    release: prometheus-operator
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-applicationset-controller
  endpoints:
  - port: metrics
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-dex-server
  labels:
    release: prometheus-operator
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-dex-server
  endpoints:
    - port: metrics
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-redis-haproxy-metrics
  labels:
    release: prometheus-operator
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-redis-ha-haproxy
  endpoints:
  - port: http-exporter-port

对于通知控制器,需要另外添加以下方式:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-notifications-controller
  labels:
    release: prometheus-operator
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-notifications-controller-metrics
  endpoints:
    - port: metrics

仪表板

可以在此处找到一个示例Grafana仪表板或检查演示实例仪表板。
在这里插入图片描述

7.22.基于Web的终端

在这里插入图片描述

自v2.4以来,Argo CD具有基于Web的终端,可以像Kubectl Exec一样在运行吊舱内获取外壳。基本上是您的浏览器,完整的ANSI颜色支持等等!但是,对于安全性,默认情况下,此功能将被禁用。

这是一种强大的特权。它允许用户在由具有exec/create特权的应用程序管理的任何POD上运行任意代码。如果POD安装了ServiceAccount令牌(这是Kubernetes的默认行为),则用户具有与ServiceAccount相同的特权。

启用终端

  1. exec.enabled键设置为trueargocd-cm ConfigMap上。
  2. 修补argocd-server Role(如果使用命名空间为Argo)或ClusterRole(如果使用簇Argo)允许argocd-server execte exec
- apiGroups:
  - ""
  resources:
  - pods/exec
  verbs:
  - create

添加RBAC规则以允许的用户create exec pods,即

p, role:myrole, exec, create, */*, allow

有关更多信息,请参见RBAC配置

更改允许的脚本

默认情况下,Argo CD尝试按以下顺序执行脚本:

  1. bash
  2. sh
  3. powershell
  4. cmd

如果找不到脚本,则终端会话将失败。要添加或更改允许的脚本,请更改exec.shells键中的argocd-cm ConfigMap中的键,并用逗号将它们分开。

7.23.配置管理插件

Argo CD的“native”配置管理工具是Helm,Jsonnet和Kustomize。如果要使用其他配置管理工具,或者Argo CD的native工具支持不包括所需的功能,则可能需要转到配置管理插件(CMP)。

Argo CD “repo server” 组件负责构建Kubernetes根据Helm,OCI或GIT存储库中的某些源文件表现出来。当正确配置配置管理插件时,Repo服务器可以将构建的任务委托给插件。

以下各节将描述如何创建,安装和使用插件。查看示例插件以获取其他指南。

插件对Argo CD系统具有信任程度,因此安全地实现插件很重要。 Argo CD管理员只能从可信赖的来源安装插件,他们应审核插件以权衡其特定风险和收益。

安装配置管理插件

SideCar插件

操作员可以通过SIDECAR配置插件工具到repo-server。需要以下更改来配置新插件:

写插件配置文件

插件将通过位于插件容器内部的ConfigmanagementPlugin清单进行配置。

apiVersion: argoproj.io/v1alpha1
kind: ConfigManagementPlugin
metadata:
  # The name of the plugin must be unique within a given Argo CD instance.
  name: my-plugin
spec:
  # The version of your plugin. Optional. If specified, the Application's spec.source.plugin.name field
  # must be <plugin name>-<plugin version>.
  version: v1.0
  # The init command runs in the Application source directory at the beginning of each manifest generation. The init
  # command can output anything. A non-zero status code will fail manifest generation.
  init:
    # Init always happens immediately before generate, but its output is not treated as manifests.
    # This is a good place to, for example, download chart dependencies.
    command: [sh]
    args: [-c, 'echo "Initializing..."']
  # The generate command runs in the Application source directory each time manifests are generated. Standard output
  # must be ONLY valid Kubernetes Objects in either YAML or JSON. A non-zero exit code will fail manifest generation.
  # To write log messages from the command, write them to stderr, it will always be displayed.
  # Error output will be sent to the UI, so avoid printing sensitive information (such as secrets).
  generate:
    command: [sh, -c]
    args:
      - |
        echo "{\"kind\": \"ConfigMap\", \"apiVersion\": \"v1\", \"metadata\": { \"name\": \"$ARGOCD_APP_NAME\", \"namespace\": \"$ARGOCD_APP_NAMESPACE\", \"annotations\": {\"Foo\": \"$ARGOCD_ENV_FOO\", \"KubeVersion\": \"$KUBE_VERSION\", \"KubeApiVersion\": \"$KUBE_API_VERSIONS\",\"Bar\": \"baz\"}}}"
  # The discovery config is applied to a repository. If every configured discovery tool matches, then the plugin may be
  # used to generate manifests for Applications using the repository. If the discovery config is omitted then the plugin 
  # will not match any application but can still be invoked explicitly by specifying the plugin name in the app spec. 
  # Only one of fileName, find.glob, or find.command should be specified. If multiple are specified then only the 
  # first (in that order) is evaluated.
  discover:
    # fileName is a glob pattern (https://pkg.go.dev/path/filepath#Glob) that is applied to the Application's source 
    # directory. If there is a match, this plugin may be used for the Application.
    fileName: "./subdir/s*.yaml"
    find:
      # This does the same thing as fileName, but it supports double-start (nested directory) glob patterns.
      glob: "**/Chart.yaml"
      # The find command runs in the repository's root directory. To match, it must exit with status code 0 _and_ 
      # produce non-empty output to standard out.
      command: [sh, -c, find . -name env.yaml]
  # The parameters config describes what parameters the UI should display for an Application. It is up to the user to
  # actually set parameters in the Application manifest (in spec.source.plugin.parameters). The announcements _only_
  # inform the "Parameters" tab in the App Details page of the UI.
  parameters:
    # Static parameter announcements are sent to the UI for _all_ Applications handled by this plugin.
    # Think of the `string`, `array`, and `map` values set here as "defaults". It is up to the plugin author to make 
    # sure that these default values actually reflect the plugin's behavior if the user doesn't explicitly set different
    # values for those parameters.
    static:
      - name: string-param
        title: Description of the string param
        tooltip: Tooltip shown when the user hovers the
        # If this field is set, the UI will indicate to the user that they must set the value.
        required: false
        # itemType tells the UI how to present the parameter's value (or, for arrays and maps, values). Default is
        # "string". Examples of other types which may be supported in the future are "boolean" or "number".
        # Even if the itemType is not "string", the parameter value from the Application spec will be sent to the plugin
        # as a string. It's up to the plugin to do the appropriate conversion.
        itemType: ""
        # collectionType describes what type of value this parameter accepts (string, array, or map) and allows the UI
        # to present a form to match that type. Default is "string". This field must be present for non-string types.
        # It will not be inferred from the presence of an `array` or `map` field.
        collectionType: ""
        # This field communicates the parameter's default value to the UI. Setting this field is optional.
        string: default-string-value
      # All the fields above besides "string" apply to both the array and map type parameter announcements.
      - name: array-param
        # This field communicates the parameter's default value to the UI. Setting this field is optional.
        array: [default, items]
        collectionType: array
      - name: map-param
        # This field communicates the parameter's default value to the UI. Setting this field is optional.
        map:
          some: value
        collectionType: map
    # Dynamic parameter announcements are announcements specific to an Application handled by this plugin. For example,
    # the values for a Helm chart's values.yaml file could be sent as parameter announcements.
    dynamic:
      # The command is run in an Application's source directory. Standard output must be JSON matching the schema of the
      # static parameter announcements list.
      command: [echo, '[{"name": "example-param", "string": "default-string-value"}]']

  # If set to `true` then the plugin receives repository files with original file mode. Dangerous since the repository
  # might have executable files. Set to true only if you trust the CMP plugin authors.
  preserveFileMode: false

虽然ConfigManagementPlugin看起来像Kubernetes对象,但实际上并不是自定义资源。它仅遵循Kubernetes风格的规格约定。

生成命令必须将有效的kubernetes yaml或json对象流打印为stdout。初始化和生成命令均在应用程序源目录中执行。

discover.filename用作Glob模式,以确定插件是否支持应用程序存储库。

  discover:
    find:
      command: [sh, -c, find . -name env.yaml]

如果未提供discover.fileName,则执行discover.find.command,以确定插件是否支持应用程序存储库。在支持应用程序源类型时,FIND命令应返回非错误退出代码并产生输出。

将插件配置文件放在sidecar

Argo CD期望插件配置文件位于sidecar中的/home/argocd/cmp-server/config/plugin.yaml

如果为 sidecar 使用自定义镜像,则可以将文件直接添加到该镜像中。

WORKDIR /home/argocd/cmp-server/config/
COPY plugin.yaml ./

如果使用库存图片作为 sidecar,或者宁愿在 ConfigMap 中维护插件配置,只需将插件配置文件嵌套在 plugin.yaml 键下的 ConfigMap 中,然后将 ConfigMap 挂载到 sidecar 中(参见下一部分)。

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-plugin-config
data:
  plugin.yaml: |
    apiVersion: argoproj.io/v1alpha1
    kind: ConfigManagementPlugin
    metadata:
      name: my-plugin
    spec:
      version: v1.0
      init:
        command: [sh, -c, 'echo "Initializing..."']
      generate:
        command: [sh, -c, 'echo "{\"kind\": \"ConfigMap\", \"apiVersion\": \"v1\", \"metadata\": { \"name\": \"$ARGOCD_APP_NAME\", \"namespace\": \"$ARGOCD_APP_NAMESPACE\", \"annotations\": {\"Foo\": \"$ARGOCD_ENV_FOO\", \"KubeVersion\": \"$KUBE_VERSION\", \"KubeApiVersion\": \"$KUBE_API_VERSIONS\",\"Bar\": \"baz\"}}}"']
      discover:
        fileName: "./subdir/s*.yaml"
注册插件 sidecar

要安装插件,请修补 argocd-repo-server 以将插件容器作为sidecar 运行,并使用 argocd-cmp-server 作为其入口点。可以使用现成的或定制的插件映像作为 sidecar 映像。例如:

containers:
- name: my-plugin
  command: [/var/run/argocd/argocd-cmp-server] # Entrypoint should be Argo CD lightweight CMP server i.e. argocd-cmp-server
  image: busybox # This can be off-the-shelf or custom-built image
  securityContext:
    runAsNonRoot: true
    runAsUser: 999
  volumeMounts:
    - mountPath: /var/run/argocd
      name: var-files
    - mountPath: /home/argocd/cmp-server/plugins
      name: plugins
    # Remove this volumeMount if you've chosen to bake the config file into the sidecar image.
    - mountPath: /home/argocd/cmp-server/config/plugin.yaml
      subPath: plugin.yaml
      name: my-plugin-config
    # Starting with v2.4, do NOT mount the same tmp volume as the repo-server container. The filesystem separation helps 
    # mitigate path traversal attacks.
    - mountPath: /tmp
      name: cmp-tmp
volumes:
- configMap:
    name: my-plugin-config
  name: my-plugin-config
- emptyDir: {}
  name: cmp-tmp

确保使用 /var/run/argocd/argocd-cmp-server 作为入口点。argocd-cmp-server 是一种轻量级 GRPC 服务,允许 Argo CD 与插件交互。
确保 sidecar 容器以用户 999 身份运行。
确保插件配置文件位于 /home/argocd/cmp-server/config/plugin.yaml。它可以通过 configmap 进行卷映射或嵌入到图像中。

在插件中使用环境变量
插件命令可以访问
  1. sidecar 的系统环境变量
  2. 标准构建环境变量
  3. 应用程序规范中的变量(对系统和构建变量的引用将插入到变量的值中):
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
  source:
    plugin:
      env:
        - name: FOO
          value: bar
        - name: REV
          value: test-$ARGOCD_APP_REVISION

在到达 init.command, generate.command, discover.find.command命令之前,Argo CD 会为所有用户提供的环境变量(上面的 #3)添加 ARGOCD_ENV_ 前缀。这可防止用户直接设置可能敏感的环境变量。

  1. 应用程序规范中的参数:
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
 source:
   plugin:
     parameters:
       - name: values-files
         array: [values-dev.yaml]
       - name: helm-parameters
         map:
           image.tag: v1.2.3

这些参数在 ARGOCD_APP_PARAMETERS 环境变量中以 JSON 形式提供。上面的示例将生成以下 JSON:

[
    {
        "name": "values-files",
        "array": [
            "values-dev.yaml"
        ]
    },
    {
        "name": "helm-parameters",
        "map": {
            "image.tag": "v1.2.3"
        }
    }
]

即使指定了默认值,参数声明也不会发送到 ARGOCD_APP_PARAMETERS 中的插件。只有在应用程序规范中明确设置的参数才会发送到插件。插件将应用与 UI 中声明的相同的默认值。

相同的参数也可用作单独的环境变量。环境变量的名称遵循以下约定:

   - name: some-string-param
     string: some-string-value
   # PARAM_SOME_STRING_PARAM=some-string-value

   - name: some-array-param
     value: [item1, item2]
   # PARAM_SOME_ARRAY_PARAM_0=item1
   # PARAM_SOME_ARRAY_PARAM_1=item2

   - name: some-map-param
     map:
       image.tag: v1.2.3
   # PARAM_SOME_MAP_PARAM_IMAGE_TAG=v1.2.3

作为 Argo CD 清单生成系统的一部分,配置管理插件受到一定程度的信任。请务必在插件中转义用户输入,以防止恶意输入导致不良行为。

在应用程序中使用配置管理插件

可以将插件部分中的name字段留空,以便根据其发现规则自动将plugin与应用程序匹配。如果确实提到了名称,请确保它是 <metadata.name>-<spec.version>(如果在 ConfigManagementPlugin规范中提到了版本),否则只是 <metadata.name>。当明确指定名称时,只有当其发现pattern/command与提供的应用程序存储库匹配时,才会使用该特定插件。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
    path: guestbook
    plugin:
      env:
        - name: FOO
          value: bar

如果不需要设置任何环境变量,您可以设置一个空的插件部分。

    plugin: {}

如果 CMP 命令运行时间过长,该命令将被终止,并且 UI 将显示错误。CMP 服务器尊重 argocd-cm 中的 server.repo.server.timeout.secondscontroller.repo.server.timeout.seconds 项设置的超时。将其值从默认的 60 秒增加。

每个 CMP 命令还将在为 CMP sidecar 设置的 ARGOCD_EXEC_TIMEOUT 上独立超时。默认值为 90 秒。因此,如果将 repo 服务器超时时间增加到 90 秒以上,请务必在 sidecar 上设置 ARGOCD_EXEC_TIMEOUT

每个应用程序一次只能配置一个配置管理插件。如果要将通过 argocd-cm ConfigMap 配置的现有插件转换为 sidecar,请确保将插件名称更新为 <metadata.name>-<spec.version>(如果 ConfigManagementPlugin 规范中提到了版本),否则只需使用 <metadata.name>。也可以完全删除名称并让自动发现识别插件。

如果 CMP 呈现空白的清单,并且 prune 设置为 true,Argo CD 将自动删除资源。CMP 插件作者应确保错误是退出代码的一部分。通常,像 kustomize build . | cat 这样的命令不会因为管道而传递错误。考虑设置 set -o pipefail,这样任何管道都会在失败时传递错误。

调试 CMP

如果正在积极开发安装有 sidecar 的 CMP,请记住以下几点:

  1. 如果从 ConfigMap 安装 plugin.yaml,则必须重新启动 repo-server Pod,以便插件能够获取更改。
  2. 如果已将 plugin.yaml嵌入到镜像中,则必须在 repo-server Pod 上构建、推送并强制重新拉取该镜像,以便插件能够获取更改。如果使用的是 :latest,Pod 将始终拉取新镜像。如果您使用的是不同的静态标签,请在 CMP 的 sidecar 容器上设置 imagePullPolicy: Always
  3. CMP 错误由 Redis 中的 repo-server 缓存。重新启动 repo-server Pod 不会清除缓存。在积极开发 CMP 时,请务必执行“Hard Refresh”,以便获得最新的输出。
  4. 通过查看 Pod 并看到两个容器正在运行,验证你的 sidecar 是否已正确启动 kubectl get pod -l app.kubernetes.io/component=repo-server -n argocd
  5. 将日志消息写入 stderr 并在 sidecar 中设置 --loglevel=info 标志。这将打印写入 stderr 的所有内容,即使命令执行成功。
其他常见错误
Error MessageCause
no matches for kind “ConfigManagementPlugin” in version “argoproj.io/v1alpha1”ConfigManagementPlugin CRD 在 Argo CD 2.4 中已弃用,并在 2.8 中被删除。此错误意味着您尝试将插件的配置直接作为 CRD 放入 Kubernetes。

插件 tar 流排除

为了提高清单(manifest)生成速度,可以排除某些文件和文件夹,使其不发送到插件。如果没有必要,我们建议排除 .git 文件夹。使用 Go 的 filepatch.Match 语法。例如,.git/* 排除 .git 文件夹。

可以通过以下三种方式之一进行设置:

  1. 存储库服务器上的 --plugin-tar-exclude 参数。
  2. 如果使用 argocd-cmd-params-cm,则需要 reposerver.plugin.tar.exclusions
  3. 直接在 repo 服务器上设置 ARGOCD_REPO_SERVER_PLUGIN_TAR_EXCLUSIONS 环境变量。

对于选项 1,该标志可以重复多次。对于选项 2 和 3,可以指定多个 glob,并用分号分隔它们。

从 argocd-cm 插件迁移

通过修改 argocd-cm ConfigMap 来安装插件的方法从 v2.4 开始已被弃用,并且从 v2.8 开始已被完全删除。

CMP 插件的工作原理是将 sidecar 添加到 argocd-repo-server,并在该 sidecar中配置位于/home/argocd/cmp-server/config/plugin.yaml的配置。argocd-cm` 插件可以通过以下步骤轻松转换。

将 ConfigMap 条目转换为配置文件

首先,将插件的配置复制到其自己的 YAML 文件中。例如以下 ConfigMap 条目:

data:
  configManagementPlugins: |
    - name: pluginName
      init:                          # Optional command to initialize application source directory
        command: ["sample command"]
        args: ["sample args"]
      generate:                      # Command to generate Kubernetes Objects in either YAML or JSON
        command: ["sample command"]
        args: ["sample args"]
      lockRepo: true                 # Defaults to false. See below.

pluginName 项将转换为这样的配置文件:

apiVersion: argoproj.io/v1alpha1
kind: ConfigManagementPlugin
metadata:
  name: pluginName
spec:
  init:                          # Optional command to initialize application source directory
    command: ["sample command"]
    args: ["sample args"]
  generate:                      # Command to generate Kubernetes Objects in either YAML or JSON
    command: ["sample command"]
    args: ["sample args"]

lockRepo 键与 sidecar 插件无关,因为 sidecar 插件在生成清单时不共享单个源 repo 目录。

接下来,我们需要决定如何将此yaml 添加到 sidecar。我们可以将 yaml 直接嵌入到镜像中,也可以从 ConfigMap 中挂载它。

如果使用 ConfigMap,我们的示例将如下所示:

apiVersion: v1
kind: ConfigMap
metadata:
  name: pluginName
  namespace: argocd
data:
  pluginName.yaml: |
    apiVersion: argoproj.io/v1alpha1
    kind: ConfigManagementPlugin
    metadata:
      name: pluginName
    spec:
      init:                          # Optional command to initialize application source directory
        command: ["sample command"]
        args: ["sample args"]
      generate:                      # Command to generate Kubernetes Objects in either YAML or JSON
        command: ["sample command"]
        args: ["sample args"]

然后它将被安装在我们的插件边车(sidecar)中。

为你的插件编写发现规则

sidecar 插件可以使用发现规则或插件名称来将应用程序与插件进行匹配。如果省略发现规则,则必须在应用规范中通过名称明确指定插件,否则该特定插件将不会与任何应用程序匹配。

如果想使用发现而不是插件名称来将应用程序与你的插件匹配,请使用上述说明编写适用于你的插件的规则并将其添加到你的配置文件中。

要使用名称而不是发现,请将应用程序清单中的名称更新为 <metadata.name>-<spec.version>(如果在 ConfigManagementPlugin 规范中提到了版本),否则只需使用 <metadata.name>。例如:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
spec:
  source:
    plugin:
      name: pluginName  # Delete this for auto-discovery (and set `plugin: {}` if `name` was the only value) or use proper sidecar plugin name
确保插件可以访问其所需的工具

使用 argocd-cm 配置的插件在 Argo CD 映像上运行。这使其可以默认访问该映像上安装的所有工具(请参阅 Dockerfile 以了解基本映像和已安装的工具)。

可以使用库存映像(例如 busyboxalpine/k8s),也可以使用插件所需的工具设计自己的基础映像。出于安全考虑,请避免使用安装的二进制文件多于插件实际需要的映像。

测试插件

按照上述说明将插件安装为 sidecar 后,请先在几个应用程序上进行测试,然后再将它们全部迁移到 sidecar 插件。

测试完成后,从 argocd-cm ConfigMap 中删除插件条目。

其他设置

保留存储库文件模式
默认情况下,配置管理插件会以重置文件模式接收源存储库文件。这样做是出于安全原因。如果想保留原始文件模式,可以在插件规范中将preserveFileMode设置为true

确保信任所使用的插件。如果将preserveFileMode设置为true,那么插件可能会接收具有可执行权限的文件,这可能会带来安全风险。

apiVersion: argoproj.io/v1alpha1
kind: ConfigManagementPlugin
metadata:
  name: pluginName
spec:
  init:
    command: ["sample command"]
    args: ["sample args"]
  generate:
    command: ["sample command"]
    args: ["sample args"]
  preserveFileMode: true

7.24.深层链接

深层链接允许用户从 Argo CD 用户界面快速重定向到第三方系统,例如 Splunk、Datadog 等。

Argo CD 管理员将能够通过提供在 argocd-cm 中配置的深度链接模板来配置指向第三方系统的链接。这些模板可以有条件地呈现,并能够引用与链接显示位置相关的不同类型的资源,其中包括项目、应用程序或单个资源(pod、服务等)。

配置深层链接

Deep Links 的配置在 argocd-cm 中以 <location>.links 字段的形式存在,其中 <location> 确定其显示位置。<location> 的可能值为:

  • `project:此字段下的所有链接都将显示在 Argo CD UI 中的项目选项卡中
  • application:此字段下的所有链接都将显示在应用程序摘要选项卡中
  • resource:此字段下的所有链接都将显示在资源(部署、pod、服务等)摘要选项卡中

列表中的每个链接都有五个子字段:

  • title 与该链接对应的 UI 中将显示的 title/tag
  • url 深层链接将重定向到的实际 URL,此字段可以模板化以使用来自相应应用程序、项目或资源对象(取决于其所在位置)的数据。这使用 text/template pkg 进行模板化
  • description 可选 深度链接的描述
  • icon.class 可选 在下拉菜单中显示链接时使用的 font-awesome 图标类
  • if 可选 一个结果为真或假的条件语句,它也可以访问与 url 字段相同的数据。如果条件解析为真,则将显示深层链接 - 否则将隐藏。如果省略该字段,则默认将显示深层链接。这使用antonmedv/expr 来评估条件

对于 Secret 类型的资源,数据字段已被删除,但其他字段可用于模板深层链接。

确保验证 URL 模板和输入,以防止数据泄露或可能生成任何恶意链接。

如前所述,可以模板化链接和条件以使用来自资源的数据,每个类别的链接都可以访问链接到该资源的不同类型的数据。总的来说,我们在系统中有以下 4 种资源可用于模板化:

  • appapplication 该键用于访问应用程序资源数据。
  • resource 此键用于访问实际的 k8s 资源的值。
  • cluster 此键用于访问相关的目标集群数据,如名称、服务器、命名空间等。
  • project 此键用于访问项目资源数据。

上述资源可通过特定的链接类别访问,以下是每个类别中可用资源的列表:

  • resource.links: resource, application, cluster, project
  • application.links: app/application, cluster
  • project.links: project

具有深层链接及其变体的示例 argocd-cm.yaml 文件:

  # sample project level links
  project.links: |
    - url: https://myaudit-system.com?project={{.project.metadata.name}}
      title: Audit
      description: system audit logs
      icon.class: "fa-book"
  # sample application level links
  application.links: |
    # pkg.go.dev/text/template is used for evaluating url templates
    - url: https://mycompany.splunk.com?search={{.app.spec.destination.namespace}}&env={{.project.metadata.labels.env}}
      title: Splunk
    # conditionally show link e.g. for specific project
    # github.com/antonmedv/expr is used for evaluation of conditions
    - url: https://mycompany.splunk.com?search={{.app.spec.destination.namespace}}
      title: Splunk
      if: application.spec.project == "default"
    - url: https://{{.app.metadata.annotations.splunkhost}}?search={{.app.spec.destination.namespace}}
      title: Splunk
      if: app.metadata.annotations.splunkhost != ""
  # sample resource level links
  resource.links: |
    - url: https://mycompany.splunk.com?search={{.resource.metadata.name}}&env={{.project.metadata.labels.env}}
      title: Splunk
      if: resource.kind == "Pod" || resource.kind == "Deployment"
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

琴 韵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值