一、什么是 argo cd
Argo CD 是用于 Kubernetes 的声明性 GitOps 连续交付工具。
二、为什么使用 argo cd
Argo CD 可在指定的目标环境中自动部署所需的应用程序状态,应用程序部署可以在 Git 提交时跟踪对分支,标签的更新,或固定到清单的特定版本。
三、argo cd 架构图
Argo CD 的主要职责是 CD(Continuous Delivery,持续交付),将应用部署到 Kubernetes 等环境中,而 CI(Continuous Integration,持续集成)主要是交给 Jenkins,Gitlab CI 等工具来完成。
Argo CD 的架构图如下
四、Argo CD 使用
Argo CD 一般安装在 Kubernetes 集群中。
1、安装 Argo CD
使用以下命令在 argocd 命名空间部署 Argo CD:
# 创建命名空间
kubectl create namespace argocd
# 部署 argo cd
wget https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl apply -n argocd -f install.yaml
2、安装 Argo CD CLI
Argo CD CLI 是用于管理 Argo CD 的命令行工具,不同操作系统具体的安装方式可以参考 Argo CD CLI Installation
Mac 系统可以直接使用 brew install 进行安装,如下:
brew install argocd
3、发布 Argo CD 服务
默认情况下, Argo CD 服务不对外暴露服务,可以通过 LoadBalancer 或者 NodePort 类型的 Service、Ingress、Kubectl 端口转发等方式将 Argo CD 服务发布到 Kubernetes 集群外部。
这里使用以下命令通过 NodePort 服务的方式暴露 Argo CD 到集群外部:
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "NodePort"}}'
现在已经将名字为 argocd-server 的 Service 改成 NodePort 类型了,可以在集群外部通过 <节点 IP>:<随机生成的 NodePort 端口> 来访问 Argo CD。
浏览器输入 https://<节点 IP>:port 访问 Argo CD。
4、获取 Argo CD 密码
默认情况下 admin 帐号的初始密码是自动生成的,会以明文的形式存储在 Argo CD 安装的命名空间中名为 argocd-initial-admin-secret 的 Secret 对象下的 password 字段下,可以用下面的命令获取:
kubectl -n argocd get secret \
argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d
# 返回结果
kj8bDMiDTnsEfnjg
在浏览器输入密码登录 Argo CD,登录界面如下图:
登录后的界面如下所示:
5、准备 Git 仓库
在 Gitlab 上创建项目,取名为 argocd-lab,为了方便实验将仓库设置为 public 公共仓库。在仓库中创建 quickstart 目录,在目录中创建两个 yaml 资源文件,分别是 myapp-deployment.yaml 和 myapp-service.yaml。
gitlab 内容如下:
yaml 资源文件内容如下:
# myapp-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- image: registry.cn-shanghai.aliyuncs.com/public-namespace/myapp:v1
name: myapp
ports:
- containerPort: 80
---
# myapp-service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
ports:
- port: 80
targetPort: 80
nodePort: 32060
type: NodePort
selector:
app: myapp
6、创建 Argo CD App
首先创建一个命名空间 devops 用于 Argo CD 部署应用。
kubectl create ns devops
可以有三种方式创建 app,分别介绍如下:
方式一:使用 UI 创建 App
-
Application Name: 自定义的应用名。
-
Project: 使用默认创建好的 default 项目。
-
SYNC POLICY: 同步方式,可以选择自动或者手动,这里我们选择手动同步。
-
Repository URL: 项目的 Git 地址。
-
Revision: 分支名。
-
Path: yaml 资源文件所在的相对路径。
Cluster URL: Kubernetes API Server 的访问地址,由于 Argo CD 和下发应用的 Kubernetes 集群是同一个,因此可以直接使用 http://kubernetes.default.svc 来访问。关于 Kubernetes 中 DNS 解析规则可以查看 Pod 与 Service 的 DNS。 Namespace: 部署应用的命名空间。
创建完成后如下图所示,此时处于 OutOfSync 的状态:
由于设置的是手动同步,因此需要点一下下面的 SYNC 进行同步:
在弹出框点击 SYNCHRONIZE,确认同步:
等待同步完成。
在 Argo CD 上点击应用进入查看详情,如下图:
方式二:使用 CLI 创建 APP
argocd app create myapp2 \
--repo http://11.8.36.29/root/argocd-lab.git \
--path quickstart --dest-server \
https://kubernetes.default.svc \
--dest-namespace devops
使用 argocd 命令查看创建的应用:
# 列出应用
❯ argocd app list
NAME CLUSTER NAMESPACE PROJECT STATUS HEALTH SYNCPOLICY CONDITIONS REPO PATH TARGET
myapp https://kubernetes.default.svc devops default Synced Healthy <none> <none> http://11.8.36.29/root/argocd-lab.git quickstart main
# 查看 myapp 应用
❯ argocd app get myapp
Name: myapp
Project: default
Server: https://kubernetes.default.svc
Namespace: devops
URL: https://11.8.36.159:32313/applications/myapp
Repo: http://11.8.36.29/root/argocd-lab.git
Target: main
Path: quickstart
SyncWindow: Sync Allowed
Sync Policy: <none>
Sync Status: Synced to main (82baed1)
Health Status: Healthy
GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
Service devops myapp Synced Healthy service/myapp created
apps Deployment devops myapp Synced Healthy deployment.apps/myapp created
方式三:使用 YAML 文件创建
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
destination:
namespace: devops # 部署应用的命名空间
server: https://kubernetes.default.svc # API Server 地址
project: default # 项目名
source:
path: quickstart # 资源文件路径
repoURL: http://11.8.36.29/root/argocd-lab.git # Git 仓库地址
targetRevision: main # 分支名
7、版本升级
将 myapp 应用从手动同步改成自动同步。点击 APP DETAILS -> SYNC POLICY,点击 ENABLE AUTO-SYNC:
编辑 myapp 资源文件,将版本从 v1 改为 v2,点击 Commit changes,提交更改:
等待一会 Argo CD 会自动更新应用,如果等不及可以点击 Refresh,Argo CD 会去立即获取最新的资源文件。可以看到此时 myapp Deployment 会新创建 v2 版本的 Replicaset,v2 版本的 Replicaset 会创建并管理 v2 版本的 Pod。
在集群外部通过 <节点 IP>:<NodePort>
端口访问 myapp 程序,可以看到此时是 v2 版本。
8、版本回滚
升级到 v2 版本以后, v1 版本的 Replicaset 并没有被删除,而是继续保留,这是为了方便我们回滚应用。在 myapp 应用中点击 HISTORY AND ROLLBACK 查看历史记录,可以看到有 2 个历史记录:
假设刚刚上线的 v2 版本出现了问题,需要回滚回 v1 版本,那么可以选中 v1 版本,然后点击 Rollback 进行回滚:
在回滚的时候需要禁用 AUTO-SYNC 自动同步,点击 OK 确认即可:
等待一会可以看到此时已经回滚成功,此时 Pod 是 v1 版本的,并且由于此时线上的版本并不是 Git 仓库中最新的版本,因此此时同步状态是 OutOfSync:
五、传统 CD 工作流
目前大多数 CI/CD 工具都使用基于 Push 的部署模式,例如 Jenkins、CircleCI 等。这种模式一般都会在 CI 流水线运行完成后执行一个命令(比如 kubectl)将应用部署到目标环境中。
这种 CD 模式的缺陷很明显:
-
需要安装配置额外工具(比如 kubectl);
-
需要 Kubernetes 对其进行授权;
-
需要云平台授权;
-
无法感知部署状态。也就无法感知期望状态与实际状态的偏差,需要借助额外的方案来保障一致性。
六、使用 Argo CD 的 CD 工作流
和传统 CI/CD 工具一样,CI 部分并没有什么区别,无非就是测试、构建镜像、推送镜像、修改部署清单等等。重点在于 CD 部分。
Argo CD 会被部署在 Kubernetes 集群中,使用的是基于 Pull 的部署模式,它会周期性地监控应用的实际状态,也会周期性地拉取 Git 仓库中的配置清单,并将实际状态与期望状态进行比较,如果实际状态不符合期望状态,就会更新应用的实际状态以匹配期望状态。
无论是通过 CI 流水线触发更新 K8s 编排文件,还是 DevOps 工程师直接修改 K8s 编排文件,Argo CD 都会自动拉取最新的配置并应用到 K8s 集群中。
最终会得到一个相互隔离的 CI 与 CD 流水线,CI 流水线通常由研发人员(或者 DevOps 团队)控制,CD 流水线通常由集群管理员(或者 DevOps 团队)控制。
七、Argo CD 的优势
下面我们来看看 Argo CD 相较于传统 CD 工具有哪些比较明显的优势。
7.1 Git 作为应用的唯一真实来源
所有 K8s 的声明式配置都保存在 Git 中,并把 Git 作为应用的唯一事实来源,我们不再需要手动更新应用(比如执行脚本,执行 kubectl apply 或者 helm install 命令),只需要通过统一的接口(Git)来更新应用。
此外,Argo CD 不仅会监控 Git 仓库中声明的期望状态,还会监控集群中应用的实际状态,并将两种状态进行对比,只要实际状态不符合期望状态,实际状态就会被修正与期望状态一致。所以即使有人修改了集群中应用的状态(比如修改了副本数量),Argo CD 还是会将其恢复到之前的状态。这就真正确保了 Git 仓库中的编排文件可以作为集群状态的唯一真实来源。
当然,有时候我们需要快速更新应用并进行调试,通过 Git 来触发更新还是慢了点,这也不是没有办法,我们可以修改 Argo CD 的配置,使其不对手动修改的部分进行覆盖或者回退,而是直接发送告警,提醒管理员不要忘了将更新提交到 Git 仓库中。
7.2 快速回滚
Argo CD 会定期拉取最新配置并应用到集群中,一旦最新的配置导致应用出现了故障(比如应用启动失败),我们可以通过 Git History 将应用状态快速恢复到上一个可用的状态。
如果你有多个 Kubernetes 集群使用同一个 Git 仓库,这个优势会更明显,因为你不需要分别在不同的集群中通过 kubectl delete 或者 helm uninstall 等手动方式进行回滚,只需要将 Git 仓库回滚到上一个可用的版本,Argo CD 便会自动同步。
7.3 集群灾备
如果你在青云[3]北京3区中的 KubeSphere[4] 集群出现故障,且短期内不可恢复,可以直接创建一个新集群,然后将 Argo CD 连接到 Git 仓库,这个仓库包含了整个集群的所有配置声明。最终新集群的状态会与之前旧集群的状态一致,完全不需要人工干预。
7.4 使用 Git 实现访问控制
通常在生产环境中是不允许所有人访问 Kubernetes 集群的,如果直接在 Kubernetes 集群中控制访问权限,必须要使用复杂的 RBAC 规则。在 Git 仓库中控制权限就比较简单了,例如所有人(DevOps 团队,运维团队,研发团队,等等)都可以向仓库中提交 Pull Request,但只有高级工程师可以合并 Pull Request。
这样做的好处是,除了集群管理员和少数人员之外,其他人不再需要直接访问 Kubernetes 集群,只需访问 Git 仓库即可。对于程序而言也是如此,类似于 Jenkins 这样的 CI 工具也不再需要访问 Kubernetes 的权限,因为只有 Argo CD 才可以 apply 配置清单,而且 Argo CD 已经部署在 Kubernetes 集群中,必要的访问权限已经配置妥当,这样就不需要给集群外的任意人或工具提供访问的证书,可以提供更强大的安全保障。
7.5 扩展 Kubernetes
虽然 Argo CD 可以部署在 Kubernetes 集群中,享受 Kubernetes 带来的好处,但这不是 Argo CD 专属的呀!Jenkins 不是也可以部署在 Kubernetes 中吗?Argo CD 有啥特殊的吗?
那当然有了,没这金刚钻也不敢揽这瓷器活啊,Argo CD 巧妙地利用了 Kubernetes 集群中的很多功能来实现自己的目的,例如所有的资源都存储在 Etcd 集群中,利用 Kubernetes 的控制器来监控应用的实际状态并与期望状态进行对比,等等。
这样做最直观的好处就是可以实时感知应用的部署状态。例如,当你在 Git 仓库中更新配置清单中的镜像版本后,Argo CD 会将集群中的应用更新到最新版本,你可以在 Argo CD 的可视化界面中实时查看更新状态(比如 Pod 创建成功,应用成功运行并且处于健康状态,或者应用运行失败需要进行回滚操作)。
八、Argo CD 架构
从功能架构来看,Argo CD 主要有三个组件:API Server、Repository Server 和 Application Controller。从 GitOps 工作流的角度来看,总共分为 3 个阶段:检索、调谐和呈现。
8.1 检索 -- Repository Server
检索阶段会克隆应用声明式配置清单所在的 Git 仓库,并将其缓存到本地存储。包含 Kubernetes 原生的配置清单、Helm Chart 以及 Kustomize 配置清单。履行这些职责的组件就是 Repository Server。
8.2 调谐 -- Application Controller
调谐(Reconcile)阶段是最复杂的,这个阶段会将 Repository Server 获得的配置清单与反映集群当前状态的实时配置清单进行对比,一旦检测到应用处于 OutOfSync 状态,Application Controller 就会采取修正措施,使集群的实际状态与期望状态保持一致。
8.3 呈现 -- API Server
最后一个阶段是呈现阶段,由 Argo CD 的 API Server 负责,它本质上是一个 gRPC/REST Server,提供了一个无状态的可视化界面,用于展示调谐阶段的结果。同时还提供了以下这些功能:
应用管理和状态报告;
调用与应用相关的操作(例如同步、回滚、以及用户自定义的操作);
Git 仓库与集群凭证管理(以 Kubernetes Secret 的形式存储);
为外部身份验证组件提供身份验证和授权委托;
RBAC 增强;
Git Webhook 事件的监听器/转发器。
九、Argo CD 核心概念
在正式开始使用 Argo CD 之前,需要先了解两个基本概念。
9.1 Argo CD Application
Argo CD 中的 Application 定义了 Kubernetes 资源的来源(Source)和目标(Destination)。来源指的是 Git 仓库中 Kubernetes 资源配置清单所在的位置,而目标是指资源在 Kubernetes 集群中的部署位置。
来源可以是原生的 Kubernetes 配置清单,也可以是 Helm Chart 或者 Kustomize 部署清单。
目标指定了 Kubernetes 集群中 API Server 的 URL 和相关的 namespace,这样 Argo CD 就知道将应用部署到哪个集群的哪个 namespace 中。
简而言之,Application 的职责就是将目标 Kubernetes 集群中的 namespace 与 Git 仓库中声明的期望状态连接起来。
Application 的配置清单示例:
如果有多个团队,每个团队都要维护大量的应用,就需要用到 Argo CD 的另一个概念:项目(Project)。
9.2 Argo CD Project
Argo CD 中的项目(Project)可以用来对 Application 进行分组,不同的团队使用不同的项目,这样就实现了多租户环境。项目还支持更细粒度的访问权限控制:
限制部署内容(受信任的 Git 仓库);
限制目标部署环境(目标集群和 namespace);
限制部署的资源类型(例如 RBAC、CRD、DaemonSets、NetworkPolicy 等);
定义项目角色,为 Application 提供 RBAC(与 OIDC group 或者 JWT 令牌绑定)。