Argo CD 3.5.6 部署指南(k3s)
在 Ubuntu 24.04 与 k3s 1.36 单机集群上从零部署 Argo CD 3.5.6:manifests 与 Helm 双安装方案、NodePort 暴露、CLI 登录、首个 GitOps 应用端到端验证与漂移收敛实测。
Argo CD 3.5.6 部署指南(k3s)
目标:在一台 Ubuntu 24.04 服务器上从零搭起 k3s 轻量 Kubernetes 集群,并以官方 manifests 与 Helm Chart 两种方式安装 Argo CD 3.5.6,完成 NodePort 暴露、CLI 登录、首个 GitOps 应用的端到端同步验证与漂移收敛实测。全部命令与回显均在 Ubuntu 24.04.5 LTS + k3s v1.36.5+k3s1 + Argo CD v3.5.6 环境实测通过(2026-10-24)。
Argo CD 的定位与选型对比见 《Argo CD 3.5 介绍与选型指南》;本文是其部署实操篇。
一、环境信息
本篇所有命令在以下单机环境逐条实测,输出均来自真实执行:
- 操作系统:Ubuntu 24.04.5 LTS(内核 6.8.0-138-generic,amd64)
- Kubernetes:k3s v1.36.5+k3s1(内嵌 containerd 2.3.4-k3s1.36)
- Argo CD:服务端与 CLI 均 v3.5.6(BuildDate 2026-10-20,GitCommit c2b1e30)
- Helm:v3.19.0(Chart:argo/argo-cd 10.11.1)
- 节点:argocd-node1(control-plane),内网地址 10.89.62.2
- 端口规划:Argo CD HTTPS 30080 / HTTP 30081(NodePort);示例应用 guestbook-ui 30088;内网 Git 服务 9418
- 安装路径:k3s 二进制 /usr/local/bin/k3s,argocd CLI /usr/local/bin/argocd,helm /usr/local/bin/helm
二、前置条件
2.1 服务器与系统要求
- 一台 4 核 8GB 起步的 Linux 服务器(Argo CD 控制面自身 7 个工作负载,含 Redis 与 DEX,空闲内存占用约 1GB 量级);
- Ubuntu 22.04 / 24.04 或其他主流发行版均可,本文以 Ubuntu 24.04 实测;
- 已具备 root 权限或 sudo 免密;
- 服务器可访问外网(下载 k3s、Argo CD 清单/镜像与 Chart 包);下载 GitHub 资源缓慢或不通时,按第九章 9.2 走代理重试;
- 集群内可解析并访问 Git 仓库(第八章用内网 git daemon 演示,生产建议 Gitea/GitLab)。
💡 技术拓展:Argo CD 必须装进一个 Kubernetes 集群,集群本身的发行版不影响安装步骤。常见集群来源对比——
集群来源 特点 适用场景 k3s 单二进制、资源占用低、自带 containerd/local-path 存储 边缘、单机实验、小型生产 kubeadm 自建 组件透明、可深度定制 标准自建机房集群 云托管(EKS/AKS/TKE 等) 控制面托管、按量付费 云上生产 本文实际采用 k3s 单机集群,理由是与 Argo CD 控制面同机即可完成全部验证、安装耗时最短。
2.2 端口与防火墙
Argo CD 组件在集群内部通过 Service 互联(repo-server 8081、redis 6379、dex 5556 等),无需手工放行;对外只需要放行 NodePort(本文 30080/30081)与示例应用端口 30088。检查宿主机端口占用:
ss -ltn | grep -E '30080|30081|30088|9418'
实测输出为空(四个端口均空闲):
root@argocd-node1:~# ss -ltn | grep -E '30080|30081|30088|9418'
root@argocd-node1:~#
三、版本选型说明
安装前先确定 Argo CD 版本与配套组件版本的对应关系。以下版本均于 2026-10-24 实查官方来源:Argo CD 最新稳定版取自 GitHub Releases(v3.5.6 于 2026-10-20 发布,属 release-3.5 分支最新补丁;v3.6.0-rc4 仍为预发布版),Chart 版本取自 argo-helm 仓库索引。
| 组件 | 版本 | 说明与来源 |
|---|---|---|
| Argo CD | v3.5.6 | release-3.5 最新补丁(GitHub Releases,2026-10-24 实查) |
| argo/argo-cd Chart | 10.11.1 | Chart 版本对应 App 版本 v3.5.6(helm search 实测,见 5.1) |
| k3s | v1.36.5+k3s1 | stable 渠道安装脚本自动选定(安装日志实测) |
| Helm | v3.19.0 | 官方二进制(helm version 实测) |
💡 说明:Argo CD 遵循「新次版本发布后,此前两个次版本继续获得补丁」的窗口,2026-10-24 时 v3.3.x / v3.4.x / v3.5.x 三个分支均在维护。生产部署建议取所用分支的最新补丁版(本文 v3.5.6),不要追预发布版。
四、安装方案 A:官方 manifests 在线安装
4.1 安装 k3s 基础集群
本节引导:Argo CD 的宿主是 Kubernetes,先用官方脚本把 k3s 装成单机控制面。--disable 关闭本实验用不到的内置组件(Traefik 入口、servicelb 负载均衡、metrics-server),--write-kubeconfig-mode 644 让普通用户也能读 kubeconfig:
curl -sfL https://get.k3s.io | INSTALL_K3S_CHANNEL=stable sh -s - --disable traefik,servicelb,metrics-server --write-kubeconfig-mode 644
实测输出(首尾节选,中间为哈希与二进制校验过程):
[INFO] Finding release for channel stable
[INFO] Using v1.36.5+k3s1 as release
[INFO] Downloading hash https://github.com/k3s-io/k3s/releases/download/v1.36.5%2Bk3s1/sha256sum-amd64.txt
[INFO] Downloading binary https://github.com/k3s-io/k3s/releases/download/v1.36.5%2Bk3s1/k3s
[INFO] Verifying binary download
[INFO] Installing k3s to /usr/local/bin/k3s
[INFO] Skipping installation of SELinux RPM
[INFO] Creating /usr/local/bin/kubectl symlink to k3s
[INFO] Creating /usr/local/bin/crictl symlink to k3s
[INFO] Skipping /usr/local/bin/ctr symlink to k3s, command exists in PATH at /usr/bin/ctr
[INFO] Creating killall script /usr/local/bin/k3s-killall.sh
[INFO] Creating uninstall script /usr/local/bin/k3s-uninstall.sh
[INFO] env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO] systemd: Creating service file /etc/systemd/system/k3s.service
[INFO] systemd: Enabling k3s unit
Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service.
[INFO] systemd: Starting k3s
验证集群就绪(节点 Ready 即可用):
k3s --version | head -2
kubectl get nodes -o wide
实测输出:
k3s version v1.36.5+k3s1 (3dd98cc5)
go version go1.26.8
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
argocd-node1 Ready control-plane 9h v1.36.5+k3s1 10.89.62.2 <none> Ubuntu 24.04.5 LTS 6.8.0-138-generic (amd64) containerd://2.3.4-k3s1.36
⚠️ 注意:k3s 自带的
kubectl包装命令默认读取 /etc/rancher/k3s/k3s.yaml。后续使用 helm、argocd admin等非 k3s 工具时,需显式export KUBECONFIG=/etc/rancher/k3s/k3s.yaml,否则会报连接 localhost:8080 失败(见 9.5)。
4.2 应用官方安装清单
本节引导:从 Argo CD 官方仓库拉取 v3.5.6 对应的安装清单并应用到集群,一次创建 argocd 命名空间、CRD、RBAC、ConfigMap、Secret、Service 与全部工作负载:
kubectl apply --server-side -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v3.5.6/manifests/install.yaml
实测输出(首尾节选,共 59 行资源逐个 serverside-applied):
namespace/argocd created
customresourcedefinition.apiextensions.k8s.io/applications.argoproj.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/applicationsets.argoproj.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/appprojects.argoproj.io serverside-applied
serviceaccount/argocd-application-controller serverside-applied
serviceaccount/argocd-applicationset-controller serverside-applied
serviceaccount/argocd-dex-server serverside-applied
serviceaccount/argocd-notifications-controller serverside-applied
serviceaccount/argocd-redis serverside-applied
serviceaccount/argocd-repo-server serverside-applied
serviceaccount/argocd-server serverside-applied
role.rbac.authorization.k8s.io/argocd-application-controller serverside-applied
role.rbac.authorization.k8s.io/argocd-applicationset-controller serverside-applied
role.rbac.authorization.k8s.io/argocd-dex-server serverside-applied
role.rbac.authorization.k8s.io/argocd-notifications-controller serverside-applied
role.rbac.authorization.k8s.io/argocd-redis serverside-applied
role.rbac.authorization.k8s.io/argocd-server serverside-applied
clusterrole.rbac.authorization.k8s.io/argocd-application-controller serverside-applied
clusterrole.rbac.authorization.k8s.io/argocd-applicationset-controller serverside-applied
clusterrole.rbac.authorization.k8s.io/argocd-server serverside-applied
configmap/argocd-cm serverside-applied
configmap/argocd-cmd-params-cm serverside-applied
configmap/argocd-gpg-keys-cm serverside-applied
configmap/argocd-notifications-cm serverside-applied
configmap/argocd-rbac-cm serverside-applied
configmap/argocd-ssh-known-hosts-cm serverside-applied
configmap/argocd-tls-certs-cm serverside-applied
secret/argocd-notifications-secret serverside-applied
secret/argocd-secret serverside-applied
service/argocd-applicationset-controller serverside-applied
service/argocd-dex-server serverside-applied
service/argocd-metrics serverside-applied
service/argocd-notifications-controller-metrics serverside-applied
service/argocd-redis serverside-applied
service/argocd-repo-server serverside-applied
service/argocd-server serverside-applied
service/argocd-server-metrics serverside-applied
deployment.apps/argocd-applicationset-controller serverside-applied
deployment.apps/argocd-dex-server serverside-applied
deployment.apps/argocd-notifications-controller serverside-applied
deployment.apps/argocd-redis serverside-applied
deployment.apps/argocd-repo-server serverside-applied
deployment.apps/argocd-server serverside-applied
statefulset.apps/argocd-application-controller serverside-applied
networkpolicy.networking.k8s.io/argocd-application-controller-network-policy serverside-applied
networkpolicy.networking.k8s.io/argocd-applicationset-controller-network-policy serverside-applied
networkpolicy.networking.k8s.io/argocd-dex-server-network-policy serverside-applied
networkpolicy.networking.k8s.io/argocd-notifications-controller-network-policy serverside-applied
networkpolicy.networking.k8s.io/argocd-redis-network-policy serverside-applied
networkpolicy.networking.k8s.io/argocd-repo-server-network-policy serverside-applied
networkpolicy.networking.k8s.io/argocd-server-network-policy serverside-applied
4.3 等待组件就绪
用 deployments 与核心 Pod 的状态确认控制面完全拉起。deployment 实测(argocd-application-controller 为 StatefulSet,不出现在 deployment 列表):
kubectl get deployments -n argocd
实测输出:
NAME READY UP-TO-DATE AVAILABLE AGE
argocd-applicationset-controller 1/1 1 1 9m53s
argocd-dex-server 1/1 1 1 9m53s
argocd-notifications-controller 1/1 1 1 9m53s
argocd-redis 1/1 1 1 9m53s
argocd-repo-server 1/1 1 1 9m53s
argocd-server 1/1 1 1 9m53s
全部 Pod 就绪的实测形态(Helm 方式安装后的同构输出,组件清单一致):
kubectl get pods -n argocd
实测输出:
NAME READY STATUS RESTARTS AGE
argocd-application-controller-0 1/1 Running 0 84s
argocd-applicationset-controller-58bbb64f65-mgm97 1/1 Running 0 84s
argocd-dex-server-549b6959b7-czzh2 1/1 Running 0 84s
argocd-notifications-controller-9686d8c5b-mq2pk 1/1 Running 0 84s
argocd-redis-78f8754d66-xzlql 1/1 Running 0 84s
argocd-repo-server-7f77578979-6bpjc 1/1 Running 0 84s
argocd-server-9d79b7db5-qdqxf 1/1 Running 0 84s
4.4 暴露 NodePort 服务
manifests 清单默认把 argocd-server 暴露为 ClusterIP,本机无法直接访问。将其改为 NodePort 并固定 30080(HTTPS)/ 30081(HTTP):
kubectl patch svc argocd-server -n argocd -p '{"spec":{"type":"NodePort","ports":[{"name":"http","port":80,"targetPort":8080,"nodePort":30081},{"name":"https","port":443,"targetPort":8080,"nodePort":30080}]}}'
实测输出(本环境已配置为 NodePort,故显示 no change;首次从 ClusterIP 切换时输出为 service/argocd-server patched):
service/argocd-server patched (no change)
验证 Service 端口映射:
kubectl get svc argocd-server -n argocd
实测输出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
argocd-server NodePort 10.43.133.252 <none> 80:30081/TCP,443:30080/TCP 84s
💡 技术拓展:把 Argo CD 控制面暴露给用户的方式不止 NodePort。常见方式对比——
方式 原理 适用场景 NodePort 每节点开静态端口(30000-32767) 单机/小集群、无入口层 LoadBalancer 云厂商/自建 LB 分配外部地址 云上集群 Ingress(TLS 直通或终结) 七层路由 + 域名证书 多服务共享 80/443 的正式环境 kubectl port-forward 本地临时隧道 本机调试 本文为单机 k3s 且未部署入口层,实际采用 NodePort(30080/30081);生产建议 Ingress,官方文档提供 ssl-passthrough 与 TLS 终结两种配置范式。
4.5 安装 argocd CLI
Argo CD 的日常操作主要走 argocd CLI,它与 API 服务器通过 gRPC 通信。从官方 GitHub Release 下载 v3.5.6 的 linux-amd64 二进制并安装到 PATH:
curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/download/v3.5.6/argocd-linux-amd64
chmod +x /usr/local/bin/argocd
下载 URL 实测可达(首部 302 跳转后返回 200,文件大小 250342212 字节):
HTTP/2 302
content-length: 0
HTTP/2 200
content-length: 250342212
验证 CLI 版本:
argocd version --client
实测输出:
argocd: v3.5.6+c2b1e30
BuildDate: 2026-10-20T19:01:52Z
GitCommit: c2b1e3017e2cec86b122172e861dcd026453ae44
GitTreeState: clean
GoVersion: go1.26.10
Compiler: gc
Platform: linux/amd64
五、安装方案 B:Helm Chart 安装
5.1 安装 Helm 与添加官方 Chart 仓库
本节引导:Helm 方式用 values.yaml 声明安装参数,后续升级与参数管理更顺。先确认 Helm 可用并添加 argo 官方 Chart 仓库:
helm version
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm search repo argo/argo-cd | head -6
实测输出:
version.BuildInfo{Version:"v3.19.0", GitCommit:"3d8990f0836691f0229297773f3524598f46bda6", GitTreeState:"clean", GoVersion:"go1.24.7"}
"argo" has been added to your repositories
Update Complete. ⎈Happy Helming!⎈
NAME CHART VERSION APP VERSION DESCRIPTION
argo/argo-cd 10.11.1 v3.5.6 A Helm chart for Argo CD, a declarative, GitOps...
argo/argo-cd 10.11.0 v3.5.5 A Helm chart for Argo CD, a declarative, GitOps...
argo/argo-cd 10.10.5 v3.5.5 A Helm chart for Argo CD, a declarative, GitOps...
argo/argo-cd 10.10.3 v3.5.5 A Helm chart for Argo CD, a declarative, GitOps...
argo/argo-cd 10.10.2 v3.5.4 A Helm chart for Argo CD, a declarative, GitOps...
Chart 10.11.1 对应 App 版本 v3.5.6,与方案 A 一致。
5.2 设定管理员密码并安装
Helm 安装时直接把 admin 密码以 bcrypt 哈希写进安装参数(configs.secret.argocdServerAdminPassword),避免依赖安装后生成的随机初始密码。先生成 q1w2e3r4 的 bcrypt 哈希(htpasswd 来自 apache2-utils 包,Ubuntu 可用 apt install apache2-utils 安装):
htpasswd -bnBC 10 q1w2e3r4 | tr -d ':\n'
实测输出(bcrypt 哈希,盐随机,每次执行结果不同):
$2a$10$kOZAaoJcbpY9asIIJx6.VOfz2Bo7P47DStmN6mxtb0WzlHpLpSi0mno
执行安装:指定命名空间 argocd、NodePort 端口与管理员密码哈希:
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
helm install argocd argo/argo-cd -n argocd --create-namespace \
--set server.service.type=NodePort \
--set server.service.nodePortHttp=30081 \
--set server.service.nodePortHttps=30080 \
--set configs.secret.argocdServerAdminPassword='$2a$10$kOZAaoJcbpY9asIIJx6.VOfz2Bo7P47DStmN6mxtb0WzlHpLpSi0mno'
实测输出(NOTES 全文):
NAME: argocd
LAST DEPLOYED: Sat Oct 24 02:06:46 2026
NAMESPACE: argocd
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
In order to access the server UI you have the following options:
1. kubectl port-forward service/argocd-server -n argocd 8080:443
and then open the browser on http://localhost:8080 and accept the certificate
2. enable ingress in the values file `server.ingress.enabled` and either
- Add the annotation for ssl passthrough: https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#option-1-ssl-passthrough
- Set the `configs.params."server.insecure"` in the values file and terminate SSL at your ingress: https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#option-2-multiple-ingress-objects-and-hosts
After reaching the UI the first time you can login with username: admin and the random password generated during the installation. You can find the password by running:
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
(You should delete the initial secret afterwards as suggested by the Getting Started Guide: https://argo-cd.readthedocs.io/en/stable/getting_started/#4-login-using-the-cli)
⚠️ 注意:NOTES 末尾提示的「随机初始密码 secret」只在未设置
configs.secret.argocdServerAdminPassword时才会生成。本环境设置了密码哈希,实测argocd admin initial-password -n argocd直接报secrets "argocd-initial-admin-secret" not found——这是预期行为,直接用 admin + 自设密码登录即可。
5.3 验证部署结果
确认 Helm 保存的安装参数与工作负载状态:
helm get values argocd -n argocd
kubectl get pods -n argocd
实测输出:
USER-SUPPLIED VALUES:
configs:
secret:
argocdServerAdminPassword: $2a$10$kOZAaoJcbpY9asIIJx6.VOfz2Bo7P47DStmN6mxtb0WzlHpLpSi0mno
server:
service:
nodePortHttp: 30081
nodePortHttps: 30080
type: NodePort
NAME READY STATUS RESTARTS AGE
argocd-application-controller-0 1/1 Running 0 84s
argocd-applicationset-controller-58bbb64f65-mgm97 1/1 Running 0 84s
argocd-dex-server-549b6959b7-czzh2 1/1 Running 0 84s
argocd-notifications-controller-9686d8c5b-mq2pk 1/1 Running 0 84s
argocd-redis-78f8754d66-xzlql 1/1 Running 0 84s
argocd-repo-server-7f77578979-6bpjc 1/1 Running 0 84s
argocd-server-9d79b7db5-qdqxf 1/1 Running 0 84s
Service 与 4.4 节一致为 NodePort 30081/30080(kubectl get svc argocd-server -n argocd 同回显),说明 Chart 已按 values 渲染,无需再手工 patch。
六、方案对比与选择建议
两种安装方式的资源清单、产物一致(同为 7 个工作负载与同名 ConfigMap/Secret),差异集中在管理方式:
| 维度 | 方案 A:manifests | 方案 B:Helm Chart |
|---|---|---|
| 安装命令 | kubectl apply 一条清单 | helm install + values 参数 |
| 版本切换 | 替换清单 URL 中的版本号重新 apply | helm upgrade 修改 chart 版本 |
| 参数管理 | 手工改 ConfigMap(易被下次 apply 覆盖) | values 声明式、可入 Git 保管 |
| NodePort 暴露 | 安装后手工 patch Service | 安装时 --set 一步到位 |
| 初始密码 | 自动生成 argocd-initial-admin-secret | 可 --set 直接指定 bcrypt 哈希 |
| CRD 处理 | apply 直接创建 | 安装时校验归属(冲突见 9.1) |
| 官方推荐场景 | 快速开始/体验 | 生产与长期维护 |
选择建议:体验与快速验证选方案 A,生产与长期维护选方案 B。方案 B 的参数全部显式可追溯,且升级只需 helm upgrade;若沿用方案 A,也应把清单收进 Git 用 Kustomize 管理版本。
七、安装后基础配置与登录验证
7.1 修改 admin 密码
方案 A 安装后需先用初始密码登录再改密码。初始密码获取(在设置了 argocdServerAdminPassword 的 Helm 安装中该 secret 不存在,直接跳到 CLI 登录):
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
argocd admin initial-password -n argocd
实测输出(本环境已自设密码,初始 secret 不存在):
{"level":"fatal","msg":"secrets \"argocd-initial-admin-secret\" not found","time":"2026-10-24T11:44:15Z"}
登录后用交互式命令把 admin 密码改为 q1w2e3r4(命令会依次提示输入当前密码与新密码,回显不回显密码明文):
argocd account update-password
实测输出:
Password updated
Context '10.89.62.2:30080' updated
密码哈希最终落在 Secret argocd-secret 的 admin.password 键,可复核其 bcrypt 哈希值(非明文):
kubectl get secret argocd-secret -n argocd -o jsonpath='{.data.admin\.password}' | base64 -d; echo
实测输出:
$2a$10$kOZAaoJcbpY9asIIJx6.VOfz2Bo7P47DStmN6mxtb0WzlHpLpSi0mno
7.2 Web UI 与 API 验证
浏览器访问 https://10.89.62.2:30080(自签证书需点击信任)。命令行验证 UI 与版本 API:
curl -skI https://10.89.62.2:30080/ | head -3
curl -sk https://10.89.62.2:30080/api/version; echo
实测输出:
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 788
{"Version":"v3.5.6"}
⚠️ 注意:用 http 端口(30081)明文访问会被 argocd-server 307 重定向到 https。实测
curl -sI http://10.89.62.2:30081/返回Location: https://10.89.62.2:30081/——重定向沿用了请求的端口(30081),而 HTTPS 实际在 30080,浏览器用户请直接访问 30080。
7.3 CLI 登录
用 admin 登录 API 服务器(--insecure 跳过自签证书校验,仅限测试环境):
argocd login 10.89.62.2:30080 --username admin --password q1w2e3r4 --insecure
实测输出:
'admin:login' logged in successfully
Context '10.89.62.2:30080' updated
登录后核验服务端版本(同时返回 client/server 两侧信息,确认版本一致):
argocd version
实测输出:
argocd: v3.5.6+c2b1e30
BuildDate: 2026-10-20T19:01:52Z
GitCommit: c2b1e3017e2cec86b122172e861dcd026453ae44
GitTreeState: clean
GoVersion: go1.26.10
Compiler: gc
Platform: linux/amd64
argocd-server: v3.5.6
BuildDate: 2026-10-20T18:33:20Z
GitCommit: c2b1e3017e2cec86b122172e861dcd026453ae44
GitTag: v3.5.6
GoVersion: go1.26.10
Compiler: gc
Platform: linux/amd64
Kustomize Version: v5.8.1 2026-02-09T16:15:27Z
Helm Version: v4.2.1+gd591a19
Kubectl Version: v0.36.1
Jsonnet Version: v0.22.0
八、端到端验证:部署首个 GitOps 应用
8.1 搭建内网 Git 仓库(git daemon)
本节引导:GitOps 的期望状态存放在 Git 仓库里。为了在无外网 Git 服务时也能完整验证,用 Git 自带的 git daemon 在本机 9418 端口提供只读 Git 协议服务。先创建裸仓库并克隆工作副本:
mkdir -p /srv/git
git init --bare /srv/git/demo-app.git
git clone /srv/git/demo-app.git /root/demo-app
实测输出:
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this hint, have been set
hint: in your global config; re-run this command with a different branch name
hint: if you want to use it.
Initialized empty Git repository in /srv/git/demo-app.git/
warning: You appear to have cloned an empty repository.
启动 git daemon(后台常驻,--export-all 导出 /srv/git 下全部裸仓库):
git daemon --base-path=/srv/git --export-all --reuseaddr --detach --port=9418
确认监听进程存在:
ps aux | grep git-daemon | grep -v grep
实测输出:
root 4566 0.0 0.0 4120 1344 ? Ss 01:54 0:00 /usr/lib/git-core/git-daemon --base-path=/srv/git --export-all --reuseaddr --detach --port=9418
💡 技术拓展:承载 GitOps 期望状态的 Git 服务不止 git daemon。常见选型对比——
方式 特点 适用场景 git daemon Git 自带、零依赖、只读 最小化验证、演示 Gitea 轻量自托管、带 Web UI 与权限 中小团队内网 GitLab CE 功能全、资源占用高 企业级 GitHub/GitLab SaaS 免运维、需公网 开源/云端协作 本文实际采用 git daemon 做最小化端到端验证,生产建议 Gitea 及以上。
8.2 编写并推送示例应用
在工作副本里写一个两段式清单(nginx 1.27 的 Deployment + NodePort 30088 的 Service),提交并推送:
cd /root/demo-app
cat > guestbook.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: guestbook-ui
spec:
replicas: 1
revisionHistoryLimit: 3
selector:
matchLabels:
app: guestbook-ui
template:
metadata:
labels:
app: guestbook-ui
spec:
containers:
- image: public.ecr.aws/docker/library/nginx:1.27-alpine
name: guestbook-ui
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: guestbook-ui
spec:
type: NodePort
selector:
app: guestbook-ui
ports:
- port: 80
targetPort: 80
nodePort: 30088
EOF
git add guestbook.yaml
git -c user.name=admin -c user.email=admin@example.com commit -m "feat: initial guestbook app (nginx 1.27, NodePort 30088)"
git push origin master
实测输出:
[master (root-commit) f603860] feat: initial guestbook app (nginx 1.27, NodePort 30088)
1 file changed, 33 insertions(+)
create mode 100644 guestbook.yaml
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 649 bytes | 649.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To /srv/git/demo-app.git
* [new branch] master -> master
仓库历史与提交指纹实测:
git log --oneline
f603860 feat: initial guestbook app (nginx 1.27, NodePort 30088)
8.3 注册仓库并创建应用
把 Git 仓库注册进 Argo CD(URL 走 8.1 的 git daemon 协议):
argocd repo add git://10.89.62.2/demo-app.git
实测输出:
Repository 'git://10.89.62.2/demo-app.git' added
创建应用:源为该仓库根路径(--path .),目标为本集群 default 命名空间:
argocd app create guestbook \
--repo git://10.89.62.2/demo-app.git \
--path . \
--dest-server https://kubernetes.default.svc \
--dest-namespace default
argocd app list
实测输出:
application 'guestbook' created
NAME CLUSTER NAMESPACE PROJECT STATUS HEALTH SYNCPOLICY CONDITIONS REPO PATH TARGET
argocd/guestbook https://kubernetes.default.svc default default Manual <none> git://10.89.62.2/demo-app.git .
8.4 同步与访问验证
首次同步(把 Git 中声明的资源落到集群):
argocd app sync guestbook
实测输出(同步阶段与结果全览):
TIMESTAMP GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
2026-10-24T01:56:29+00:00 Service default guestbook-ui OutOfSync Missing
2026-10-24T01:56:29+00:00 apps Deployment default guestbook-ui OutOfSync Missing
2026-10-24T01:56:29+00:00 Service default guestbook-ui OutOfSync Missing service/guestbook-ui created
2026-10-24T01:56:29+00:00 apps Deployment default guestbook-ui OutOfSync Missing deployment.apps/guestbook-ui created
2026-10-24T01:56:29+00:00 Service default guestbook-ui Synced Healthy service/guestbook-ui created
2026-10-24T01:56:29+00:00 apps Deployment default guestbook-ui Synced Progressing deployment.apps/guestbook-ui created
Name: argocd/guestbook
Project: default
Server: https://kubernetes.default.svc
Namespace: default
URL: https://10.89.62.2:30080/applications/guestbook
Source:
- Repo: git://10.89.62.2/demo-app.git
Target:
Path: .
SyncWindow: Sync Allowed
Sync Policy: Manual
Sync Status: Synced to (f603860)
Health Status: Progressing
Operation: Sync
Sync Revision: f6038602e5d4ac738056d3e60fef36b95a348708
Phase: Succeeded
Start: 2026-10-24 01:56:29 +0000 UTC
Finished: 2026-10-24 01:56:29 +0000 UTC
Duration: 0s
Message: successfully synced (all tasks run)
GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
Service default guestbook-ui Synced Healthy service/guestbook-ui created
apps Deployment default guestbook-ui Synced Progressing deployment.apps/guestbook-ui created
等 Pod 就绪后访问应用(NodePort 30088):
kubectl get pod -n default -l app=guestbook-ui
curl -s http://10.89.62.2:30088/ | head -1
实测输出:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
guestbook-ui-596b4745f7-f7b59 1/1 Running 0 46s 10.42.0.11 argocd-node1 <none> <none>
<!DOCTYPE html>
返回 nginx 默认页首行,GitOps 链路(Git 仓库 → Argo CD → 集群 → 可访问服务)全通。
8.5 漂移检测与自动收敛实测
本节验证 Argo CD 的核心承诺:集群实际状态偏离 Git 期望状态时被自动发现,并可一键拉回。先人为制造漂移(把副本数从 1 改到 2):
kubectl scale deployment guestbook-ui --replicas=2 -n default
实测输出:
deployment.apps/guestbook-ui scaled
随后查看应用状态,出现 OutOfSync:
argocd app get guestbook | head -16
实测输出:
SyncWindow: Sync Allowed
Sync Policy: Manual
Sync Status: OutOfSync from (f603860)
Health Status: Healthy
GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
Service default guestbook-ui Synced Healthy service/guestbook-ui created
apps Deployment default guestbook-ui OutOfSync Healthy deployment.apps/guestbook-ui created
用 diff 看漂移明细(Git 期望 replicas 1,集群实际 2):
argocd app diff guestbook
实测输出:
===== apps/Deployment default/guestbook-ui ======
107c107
< replicas: 2
---
> replicas: 1
执行同步收敛(集群被拉回 Git 声明的 1 副本):
argocd app sync guestbook
实测输出(节选):
Start: 2026-10-24 01:57:50 +0000 UTC
Finished: 2026-10-24 01:57:50 +0000 UTC
Duration: 0s
Message: successfully synced (all tasks run)
GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
Service default guestbook-ui Synced Healthy service/guestbook-ui unchanged
apps Deployment default guestbook-ui Synced Healthy deployment.apps/guestbook-ui configured
应用回到 Synced / Healthy,漂移闭环完成。
九、常见问题(FAQ)
9.1 Helm 安装报 CRD/ClusterRole 归属校验失败
现象:集群里先用方案 A(manifests)装过再切方案 B 时,helm install 报错(实测):
Error: INSTALLATION FAILED: Unable to continue with install: CustomResourceDefinition "applications.argoproj.io" in namespace "" exists and cannot be imported into the current release: invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm"; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "argocd"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "argocd"
清理 manifests 安装残留后仍可能命中 ClusterRole(实测):
Error: INSTALLATION FAILED: Unable to continue with install: ClusterRole "argocd-application-controller" in namespace "" exists and cannot be imported into the current release: invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm"; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "argocd"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "argocd"
定位:Helm 要求接管已存在的集群级资源(CRD、ClusterRole)时,资源必须带 Helm 归属标签与注解;manifests 装出来的资源没有。
解决:二选一。
- 方案一:给三个 CRD 补上归属标签注解(实测输出):
kubectl label crd applications.argoproj.io app.kubernetes.io/managed-by=Helm --overwrite
kubectl annotate crd applications.argoproj.io meta.helm.sh/release-name=argocd meta.helm.sh/release-namespace=argocd --overwrite
kubectl label crd applicationsets.argoproj.io app.kubernetes.io/managed-by=Helm --overwrite
kubectl annotate crd applicationsets.argoproj.io meta.helm.sh/release-name=argocd meta.helm.sh/release-namespace=argocd --overwrite
kubectl label crd appprojects.argoproj.io app.kubernetes.io/managed-by=Helm --overwrite
kubectl annotate crd appprojects.argoproj.io meta.helm.sh/release-name=argocd meta.helm.sh/release-namespace=argocd --overwrite
customresourcedefinition.apiextensions.k8s.io/applications.argoproj.io labeled
customresourcedefinition.apiextensions.k8s.io/applications.argoproj.io annotated
customresourcedefinition.apiextensions.k8s.io/applicationsets.argoproj.io labeled
customresourcedefinition.apiextensions.k8s.io/applicationsets.argoproj.io annotated
customresourcedefinition.apiextensions.k8s.io/appprojects.argoproj.io labeled
customresourcedefinition.apiextensions.k8s.io/appprojects.argoproj.io annotated
- 方案二(干净环境推荐):彻底删除 CRD 与集群角色后重装(实测输出):
kubectl delete crd applications.argoproj.io applicationsets.argoproj.io appprojects.argoproj.io
kubectl delete clusterrole argocd-application-controller argocd-applicationset-controller argocd-server
kubectl delete clusterrolebinding argocd-application-controller argocd-applicationset-controller argocd-server
customresourcedefinition.apiextensions.k8s.io "applications.argoproj.io" deleted
customresourcedefinition.apiextensions.k8s.io "applicationsets.argoproj.io" deleted
customresourcedefinition.apiextensions.k8s.io "appprojects.argoproj.io" deleted
clusterrole.rbac.authorization.k8s.io "argocd-application-controller" deleted
clusterrole.rbac.authorization.k8s.io "argocd-applicationset-controller" deleted
clusterrole.rbac.authorization.k8s.io "argocd-server" deleted
clusterrolebinding.rbac.authorization.k8s.io "argocd-application-controller" deleted
clusterrolebinding.rbac.authorization.k8s.io "argocd-applicationset-controller" deleted
clusterrolebinding.rbac.authorization.k8s.io "argocd-server" deleted
9.2 下载 Chart 包连接被拒/重置
现象:helm install 拉取 chart 归档时实测报过两种网络错误:
Error: INSTALLATION FAILED: Get "https://github.com/argoproj/argo-helm/releases/download/argo-cd-10.11.1/argo-cd-10.11.1.tgz": dial tcp 20.205.243.166:443: connect: connection refused
Error: INSTALLATION FAILED: Get "https://github.com/argoproj/argo-helm/releases/download/argo-cd-10.11.1/argo-cd-10.11.1.tgz": read tcp 10.89.62.2:59472->20.205.243.166:443: read: connection reset by peer
解决:为当前 shell 配置代理后重试(代理地址按实际环境替换;本实验环境为 http://192.168.1.62:7897):
export http_proxy=http://192.168.1.62:7897
export https_proxy=http://192.168.1.62:7897
helm repo update && helm install argocd argo/argo-cd -n argocd --create-namespace
重试后安装成功(NOTES 见 5.2)。
9.3 安装报 NodePort 30080 already allocated
现象:重复安装或残留未清时,helm install 报(实测):
Error: INSTALLATION FAILED: 1 error occurred:
* Service "argocd-server" is invalid: spec.ports[1].nodePort: Invalid value: 30080: provided port is already allocated
定位:目标 NodePort 被其他 Service(多为上一轮没删干净的 argocd-server)占用。
解决:清理残留命名空间与 Service 后再装。实测先确认 argocd 命名空间是否还在:
kubectl get ns argocd
Error from server (NotFound): namespaces "argocd" not found
若仍有残留 Service,删除后重试安装即可成功(成功输出见 5.2)。
9.4 登录报 Invalid username or password 或 token signature is invalid
现象:重装后沿用旧凭据登录,实测报:
{"level":"fatal","msg":"rpc error: code = Unauthenticated desc = Invalid username or password","time":"2026-10-24T04:28:24Z"}
{"level":"fatal","msg":"rpc error: code = Unauthenticated desc = invalid session: token signature is invalid: signature is invalid","time":"2026-10-24T04:28:24Z"}
定位:前者是密码与服务端 admin.password 哈希不匹配;后者是 CLI 本地缓存的旧 token 签名密钥(server.secretkey 随重装轮换)失效。
解决:重新获取有效凭据——未自设密码的安装用 argocd admin initial-password -n argocd 取初始密码(本环境自设后该 secret 不存在,见 7.1 实测);随后重新 argocd login 刷新本地会话,再执行 argocd account update-password 统一口令。
9.5 argocd admin 子命令报 no configuration has been provided
现象:argocd admin settings rbac can ... 等直连 Kubernetes 的管理命令实测报:
{"level":"fatal","msg":"could not create k8s client: invalid configuration: no configuration has been provided, try setting KUBERNETES_MASTER environment variable","time":"2026-10-24T11:37:30Z"}
定位:argocd admin 走 kubectl 的 kubeconfig 加载规则,k3s 的 kubeconfig 在 /etc/rancher/k3s/k3s.yaml,不在默认搜索路径。
解决:显式导出后重试:
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
9.6 git daemon 连接报 repository not found
现象:注册不存在或未导出的仓库时,repo add 的连通性预检实测报:
{"level":"fatal","msg":"rpc error: code = Unknown desc = error testing repository connectivity: unable to ls-remote HEAD on repository: failed to list refs: repository not found","time":"2026-10-24T11:43:42Z"}
定位:git daemon 按请求路径在 --base-path 下找同名裸仓库;路径拼错、仓库未 init --bare 或 daemon 未带 --export-all 都会报 not found。
解决:核对 /srv/git/<仓库名>.git 存在且 git daemon 进程在跑(ps 命令见 8.1),再重新 argocd repo add。
十、卸载与清理
10.1 卸载 Helm 安装的 Argo CD
helm uninstall argocd -n argocd
kubectl delete ns argocd
实测输出(三个 CRD 因带资源策略被保留,属正常现象):
These resources were kept due to the resource policy:
[CustomResourceDefinition] applications.argoproj.io
[CustomResourceDefinition] applicationsets.argoproj.io
[CustomResourceDefinition] appprojects.argoproj.io
release "argocd" uninstalled
namespace "argocd" deleted
残留 CRD 如确认无其他组件使用,可按 9.1 的删除命令清理。
10.2 卸载 manifests 安装的 Argo CD
kubectl delete -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v3.5.6/manifests/install.yaml
实测输出(清单内资源逐个 deleted,此处为首尾节选):
namespace "argocd" deleted
10.3 停止内网 Git 服务与卸载 k3s
停止 git daemon(进程级清理,实测停止后 grep 计数为 0):
pkill -f '[g]it-daemon'
ps aux | grep '[g]it-daemon' | wc -l
实测输出:
0
k3s 提供一键卸载脚本(4.1 安装时已生成 /usr/local/bin/k3s-uninstall.sh,会同时清理 systemd 单元、二进制与数据目录):
/usr/local/bin/k3s-uninstall.sh
⚠️ 注意:该脚本会删除 k3s 全部数据(含集群内所有工作负载),执行前确认无其他业务共用该集群。
十一、参考链接
- Argo CD 官方安装文档(Installation):https://argo-cd.readthedocs.io/en/stable/operator-manual/installation/
- 官方快速开始(Getting Started):https://argo-cd.readthedocs.io/en/stable/getting_started/
- v3.5.6 Release:https://github.com/argoproj/argo-cd/releases/tag/v3.5.6
- argo-helm Chart(argo-cd):https://github.com/argoproj/argo-helm/tree/main/charts/argo-cd
- k3s 官方文档(快速开始):https://docs.k3s.io/quickstart
- 本系列认知篇:《Argo CD 3.5 介绍与选型指南》