Harness 教程 18:GitOps 实践基础:安装 GitOps Agent、管理 Argo CD Application 与 Pipeline 同步
一:教程定位
前面的 Harness 教程主要采用传统 CI/CD 模式:
代码提交 ↓ 构建镜像 ↓ Pipeline 直接调用 Kubernetes API ↓ 部署 Deployment、Service、Ingress
这种方式简单直接,但在企业环境中会逐渐出现一些问题:
集群中的实际配置和 Git 配置不一致 运维人员手工修改 Kubernetes 资源后难以追踪 无法快速确认当前环境对应哪个 Git Commit 回滚依赖 Pipeline 历史或 kubectl rollout 多套环境的配置变更缺少统一审核 Pipeline 和集群之间存在较高权限耦合
GitOps 使用另一种交付模式:
Git 保存期望状态 ↓ GitOps Controller 持续读取 Git ↓ 比较 Git 期望状态与集群实际状态 ↓ 发现差异后执行同步 ↓ 让集群逐步收敛到 Git 中声明的状态
在 Harness GitOps 中,这个控制器体系由 Harness GitOps Agent 和 Argo CD 相关组件共同完成。
本篇将构建如下流程:
开发人员提交代码 ↓ Harness CI 执行测试 ↓ 构建镜像并推送 Harbor ↓ Pipeline 修改 GitOps 配置仓库中的镜像 Tag ↓ 提交 Git Commit ↓ Harness GitOpsSync 步骤触发 Application 同步 ↓ Argo CD 将配置同步到 Kubernetes ↓ 等待 Application 状态变为 Synced + Healthy
二:适合人群
本文适合中级用户:
DevOps 工程师 平台工程师 SRE Kubernetes 运维人员 正在从传统 CD 迁移到 GitOps 的团队 已经使用 Argo CD、希望纳入 Harness 管理的团队
建议已经掌握:
Harness Pipeline、Stage、Step Harness Service、Environment、Connector Kubernetes Deployment 和 Service Docker 镜像与 Harbor GitLab/Gitee 分支、Commit 和 Merge Request 基础 Shell 脚本
三:学习目标
完成本文后,你应该能够:
理解 GitOps 的核心原则 理解传统 CD 和 GitOps 的区别 理解 Harness GitOps Agent 与 Harness Delegate 的区别 安装 Harness GitOps Agent 检查 Agent 和 Argo CD 组件状态 配置 Harness GitOps Repository 配置 GitOps Cluster 创建 Harness GitOps Application 理解 Synced、OutOfSync、Healthy、Degraded 等状态 在 Pipeline 中更新 GitOps 配置仓库 使用 GitOpsSync 步骤同步 Application 等待 Application 达到 Healthy 通过 Git revert 完成可审计回滚 验证 Self Heal 和 Drift Correction 处理国内网络、私有仓库、自签证书和镜像拉取问题
四:GitOps 的核心原则
1. Git 是单一事实来源
应用应该部署成什么样,不以集群当前状态为准,而以 Git 中声明的配置为准。
例如:
spec:
replicas: 3
表示期望状态为三个副本。
如果有人手工执行:
kubectl scale deployment harness-gitops-demo \
--replicas=1 \
-n gitops-dev
那么:
Git 期望状态:3 集群实际状态:1 Application 状态:OutOfSync
开启自动同步和 Self Heal 后,GitOps Controller 可以把副本数重新调整为 3。
2. 所有变更通过 Git 完成
推荐流程:
修改 YAML ↓ 提交分支 ↓ 创建 Merge Request ↓ 自动校验 ↓ 人工 Review ↓ 合并 ↓ GitOps 同步
不推荐:
直接 kubectl edit 直接 kubectl patch 直接在集群修改镜像 绕过 Git 修改生产资源
3. 使用声明式配置
Git 中保存的是最终期望状态:
image: harbor.company.com/devops/harness-gitops-demo:v1.2.0
而不是保存一组命令:
kubectl set image ...
kubectl scale ...
kubectl patch ...
常见声明式资源包括:
Kubernetes YAML Helm Chart Helm values Kustomize Argo CD Application ApplicationSet
4. 控制器持续调谐
GitOps Controller 会持续比较:
Desired State:Git 中声明的状态 Live State:Kubernetes 中实际运行的状态
两者相同:
Synced
两者不同:
OutOfSync
资源正常运行:
Healthy
资源运行异常:
Degraded
五:传统 CD 与 GitOps 的区别
| 对比项 | 传统 CD | GitOps |
|---|---|---|
| 部署发起者 | Pipeline | GitOps Controller |
| 配置来源 | Pipeline、制品、脚本 | Git |
| 应用方式 | Pipeline 推送到集群 | Controller 从 Git 拉取并同步 |
| 漂移检测 | 通常需要额外工具 | 持续比较 Git 与集群 |
| 回滚方式 | Pipeline 回滚、kubectl undo | Git revert 后重新同步 |
| 审计来源 | Pipeline 执行记录 | Git 历史 + Pipeline 记录 |
| 集群凭证 | Pipeline 通常需要访问集群 | Agent/Controller 持有目标访问能力 |
| 手工修改 | 容易长期保留 | 可被检测或自动修正 |
GitOps 并不是完全替代 Pipeline。
更准确的组合是:
Pipeline: 负责构建、测试、扫描、审批、更新 Git
GitOps: 负责把 Git 中的期望状态同步到集群
六:Harness GitOps 核心组件
1. Harness GitOps Agent
GitOps Agent 运行在用户的 Kubernetes 环境中,主要负责:
连接 Harness SaaS 连接 GitOps Repository 连接目标 Kubernetes Cluster 处理 GitOps 实体和操作 向 Harness 返回同步和健康状态 协调 Argo CD 组件执行任务
Agent 主要使用出站连接,不要求从公网直接访问集群中的 Agent 服务。
2. Argo CD Application Controller
Application Controller 负责:
持续监控 Application 读取期望状态 读取集群实际状态 计算差异 判断同步状态 执行同步或纠正操作 判断资源健康状态
3. Argo CD Repo Server
Repo Server 负责:
访问 Git 仓库 拉取指定分支、Tag 或 Commit 读取 Kubernetes Manifest 执行 Helm 模板渲染 执行 Kustomize 渲染 向 Application Controller 返回最终 Manifest
4. Redis
Redis 用于缓存 GitOps 和 Argo CD 运行过程中需要的数据。
它不是业务应用的 Redis,也不应与业务 Redis 共用。
5. GitOps Repository
GitOps Repository 保存期望状态,可以是:
Git 仓库 HTTP Helm Repository OCI Helm Repository
注意:
Harness GitOps Repository 只服务于 GitOps。
Harness CI 或普通 CD Pipeline 拉取、修改代码时, 应使用普通 Git Connector。
这两个连接即使指向同一个 GitLab,也不是同一种 Harness 实体。
6. GitOps Cluster
GitOps Cluster 表示目标 Kubernetes 集群。
Agent 安装在目标集群时,通常可以使用:
in-cluster
Agent 安装在独立管理集群时,也可以配置远程目标集群。
7. GitOps Application
Application 将以下内容组合起来:
哪个 Agent 执行 从哪个 Repository 读取 读取哪个分支或 Tag 读取哪个目录 同步到哪个 Cluster 同步到哪个 Namespace 使用哪种 Sync Policy 是否 Prune 是否 Self Heal
可以简单理解为:
Application = Repository + Revision + Path + Cluster + Namespace + Sync Policy
七:Harness GitOps Agent 与 Delegate 的区别
这是初学 GitOps 时最容易混淆的概念。
GitOps Agent
主要负责:
读取 GitOps 期望状态 管理 Argo CD Application 同步 Kubernetes 配置 监控同步和健康状态 检测集群漂移
Harness Delegate
主要负责:
执行 Pipeline 内部步骤 访问 Git、Harbor、SonarQube 等内网资源 运行 Shell Script 调用云厂商 API 执行普通 CD 部署 执行 PR Pipeline 中的 Git 操作
本篇流程同时使用两者:
Delegate: 执行 CI 构建镜像 更新 GitOps 配置仓库
GitOps Agent: 读取 GitOps 仓库 让 Argo CD 同步目标集群
如果只在 Harness 页面手工创建 Application 并执行 GitOps Sync,通常只需要 GitOps Agent。
如果 Pipeline 还需要克隆、修改和推送 Git 仓库,则仍然需要 CI 执行环境或 Delegate。
八:推荐实验架构
Harness SaaS │ ├── Harness Delegate │ ├── 访问 GitLab │ ├── 访问 Harbor │ └── 更新 GitOps Repository │ └── Harness GitOps Service │ ▼ Harness GitOps Agent │ ├── Argo CD Application Controller ├── Argo CD Repo Server ├── Redis └── ApplicationSet Controller │ ▼ Kubernetes Cluster
国内环境建议:
Git:GitLab / Gitee / 企业 Git 镜像仓库:Harbor / ACR / TCR / SWR Kubernetes:自建集群 / ACK / TKE / CCE Agent 与 Delegate:部署在企业内网或云 VPC
九:准备条件
Kubernetes 集群
建议实验环境至少具备:
可用 Kubernetes 集群 kubectl 已配置 Helm 3 可访问 Harness SaaS 可访问 GitLab/Gitee 可访问 Harbor 能够创建 CRD、Deployment、StatefulSet、Role 等资源
检查:
kubectl cluster-info
kubectl get nodes
helm version
创建命名空间
Agent 命名空间:
kubectl create namespace harness-gitops
应用命名空间:
kubectl create namespace gitops-dev
注意:
在创建 GitOps Application 前, 目标应用 Namespace 应提前创建。
网络检查
curl -I --connect-timeout 10 https://app.harness.io
curl -k -I --connect-timeout 10 https://gitlab.company.com
curl -k -I --connect-timeout 10 https://harbor.company.com/v2/
如果企业使用代理,需要提前规划:
HTTP_PROXY HTTPS_PROXY NO_PROXY
NO_PROXY 至少应考虑:
localhost 127.0.0.1 .svc .cluster.local kubernetes.default.svc GitLab 内网域名 Harbor 内网域名
十:创建 Harness GitOps Agent
在 Harness 项目中进入:
Deployments → GitOps → Settings → GitOps Agents → New GitOps Agent
建议填写:
Name: gitops-dev-agent
GitOps Operator: Argo
Namespace: harness-gitops
Existing Argo CD: No
如果企业已经运行原生 Argo CD,可以选择 Bring Your Own Argo CD,但基础教程先使用 Harness 新建的组件。
安装方式一般有:
Helm Chart Kubernetes YAML
对于普通 Kubernetes 集群,推荐优先使用:
Helm Chart 或 Kubernetes YAML
十一:方式一:使用 Helm 安装 Agent
在 Harness Agent 安装向导中下载:
override.yaml
然后执行:
helm repo add gitops-agent \
https://harness.github.io/gitops-helm/
helm repo update gitops-agent
helm install harness-gitops-agent \
gitops-agent/gitops-helm \
--values override.yaml \
--namespace harness-gitops
如果需要由 Helm 创建命名空间,也可以加入:
--create-namespace
完整示例:
helm install harness-gitops-agent \
gitops-agent/gitops-helm \
--values override.yaml \
--namespace harness-gitops \
--create-namespace
如果集群已经存在 Argo CD CRD,需要根据实际情况评估是否跳过 CRD 安装:
--set argo-cd.crds.install=false
不要在不了解现有 Argo CD 环境的情况下重复创建或删除 CRD。
十二:方式二:使用 YAML 安装 Agent
在 Harness 向导中下载:
gitops-agent.yaml
执行:
kubectl apply \
-f gitops-agent.yaml \
-n harness-gitops
检查资源:
kubectl get all -n harness-gitops
kubectl get pods -n harness-gitops
kubectl get statefulset -n harness-gitops
kubectl get cronjob -n harness-gitops
一般可以看到:
gitops-agent argocd-application-controller argocd-repo-server argocd-redis argocd-applicationset-controller gitops-agent-upgrader
具体资源名称以当前生成的 YAML 为准。
十三:国内网络环境下同步 Agent 镜像
Agent YAML 或 Helm Chart 可能引用公网镜像。
先检查镜像清单:
grep -E '^[[:space:]]*image:' gitops-agent.yaml \
| awk '{print $2}' \
| sort -u
Helm 安装前可以先渲染:
helm template harness-gitops-agent \
gitops-agent/gitops-helm \
--values override.yaml \
--namespace harness-gitops \
> rendered-agent.yaml
查看:
grep -E '^[[:space:]]*image:' rendered-agent.yaml \
| awk '{print $2}' \
| sort -u
如果节点无法稳定访问公网镜像仓库,应:
把所需镜像同步到 Harbor 在 Agent 安装配置中使用企业私有镜像仓库 配置 Harbor imagePullSecret 确保 Agent 自动升级任务也能从私有仓库拉取镜像
不要只修改当前 Deployment,而忽略:
Agent Upgrader Application Controller Repo Server Redis ApplicationSet Controller 初始化容器
具体镜像覆盖字段应以当前下载的 override.yaml 和 Agent 安装向导为准,不建议根据旧版本文档硬写字段。
十四:检查 Agent 是否正常
查看 Pod
kubectl get pods -n harness-gitops -o wide
查看 Agent 日志
kubectl logs \
deployment/gitops-agent \
-n harness-gitops \
--tail=200
如果实际资源名不同:
kubectl get deployment -n harness-gitops
查看 Argo CD Controller
kubectl logs \
statefulset/argocd-application-controller \
-n harness-gitops \
--tail=200
查看 Repo Server
kubectl logs \
deployment/argocd-repo-server \
-n harness-gitops \
--tail=200
最终在 Harness 页面确认:
Agent Status: Healthy Connected
十五:准备 GitOps 配置仓库
建议把应用源代码和部署配置拆成两个仓库。
应用源码仓库
harness-gitops-demo-app
保存:
业务代码 Dockerfile 单元测试 CI 配置
GitOps 配置仓库
harness-gitops-config
保存:
Kubernetes YAML Helm values Kustomize overlays 环境配置
推荐结构:
harness-gitops-config/ ├── README.md ├── applications/ │ └── harness-gitops-demo/ │ ├── dev/ │ │ ├── deployment.yaml │ │ ├── service.yaml │ │ └── configmap.yaml │ ├── test/ │ │ ├── deployment.yaml │ │ ├── service.yaml │ │ └── configmap.yaml │ └── prod/ │ ├── deployment.yaml │ ├── service.yaml │ └── configmap.yaml └── docs/ ├── release-process.md └── rollback-process.md
十六:编写 Deployment
applications/harness-gitops-demo/dev/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: harness-gitops-demo
namespace: gitops-dev
labels:
app: harness-gitops-demo
spec:
replicas: 2
revisionHistoryLimit: 5
selector:
matchLabels:
app: harness-gitops-demo
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: harness-gitops-demo
spec:
imagePullSecrets:
- name: harbor-pull-secret
containers:
- name: harness-gitops-demo
image: harbor.company.com/devops/harness-gitops-demo:v1.0.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 3000
envFrom:
- configMapRef:
name: harness-gitops-demo-config
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 6
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 20
periodSeconds: 20
timeoutSeconds: 2
failureThreshold: 3
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
十七:编写 Service
applications/harness-gitops-demo/dev/service.yaml
apiVersion: v1
kind: Service
metadata:
name: harness-gitops-demo
namespace: gitops-dev
labels:
app: harness-gitops-demo
spec:
type: ClusterIP
selector:
app: harness-gitops-demo
ports:
- name: http
port: 80
targetPort: http
十八:编写 ConfigMap
applications/harness-gitops-demo/dev/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: harness-gitops-demo-config
namespace: gitops-dev
data:
APP_NAME: harness-gitops-demo
APP_ENV: dev
APP_VERSION: v1.0.0
LOG_LEVEL: info
十九:准备 Harbor 拉取凭证
kubectl create secret docker-registry harbor-pull-secret \
--docker-server=harbor.company.com \
--docker-username='robot$gitops' \
--docker-password='YOUR_TOKEN' \
--namespace gitops-dev
更推荐由以下方案管理 Secret:
External Secrets Operator HashiCorp Vault Sealed Secrets 云厂商 Secret Manager
不要把 Harbor Token 直接提交到 Git。
二十:提交初始 GitOps 配置
git clone \
https://gitlab.company.com/devops/harness-gitops-config.git
cd harness-gitops-config
git add applications/harness-gitops-demo/dev
git commit -m "feat: add harness gitops demo dev manifests"
git push origin main
此时 Git 已保存 dev 环境的期望状态。
二十一:添加 Harness GitOps Repository
进入:
Deployments → GitOps → Settings → Repositories → New Repository
选择:
Repository Type: Git
Name: gitops-config-repository
GitOps Agent: gitops-dev-agent
Repository URL: https://gitlab.company.com/devops/harness-gitops-config.git
认证可以选择:
HTTPS 用户名 + Token SSH Key 凭证模板
国内企业建议:
优先使用只读 Deploy Token 或专用 GitOps Robot Account
GitOps Agent读取配置仓库通常只需要:
read_repository
Pipeline 如果还要修改这个仓库,则需要另一个可写凭证,并通过普通 Git Connector或 Harness Secret 使用。
二十二:自签证书和内网 GitLab
如果 GitLab 使用企业私有 CA,不建议长期打开跳过验证。
推荐进入:
GitOps → Settings → Repository Certificates → New Repository Certificate
上传:
TLS Repository Certificate
证书内容应为 PEM 格式:
-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----
如果使用 SSH,还应配置正确的 Known Host Key。
二十三:创建 GitOps Cluster
Agent 安装在目标集群且使用集群级权限时,一般会自动存在:
in-cluster
基础实验可以直接使用它。
如果 Agent 是 Namespaced 模式,或需要管理远程集群,应额外创建 Cluster,并提供:
Kubernetes API 地址 认证凭证 允许的 Namespace Agent
生产环境应坚持最小权限原则:
dev Agent 只管理 dev Cluster/Namespace prod Agent 只管理 prod Cluster/Namespace 不同团队使用不同 Agent 或 Argo Project
二十四:创建 Harness Service
创建:
Service Name: harness-gitops-demo
Identifier: harness_gitops_demo
该 Service 用于关联:
Pipeline Environment GitOps Application 运行实例
不要把 Service Identifier 随意修改,否则 Pipeline 和 Application 的关联可能失效。
二十五:创建 Harness Environment
创建:
Environment Name: dev
Environment Type: Pre-Production
后续还可以创建:
test pre prod
生产环境应单独配置权限和审批。
二十六:创建 GitOps Application
进入:
Deployments → GitOps → Applications → New Application
推荐填写:
Application Name: harness-gitops-demo-dev
Service: harness-gitops-demo
Environment: dev
GitOps Agent: gitops-dev-agent
Repository: gitops-config-repository
Target Revision: main
Path: applications/harness-gitops-demo/dev
Cluster: in-cluster
Namespace: gitops-dev
Manifest 类型由 Repo Server 根据目录内容处理。本例使用普通 Kubernetes YAML。
二十七:配置 Sync Policy
基础教程建议先使用手动同步:
Automatic Sync: Disabled
Prune: Disabled
Self Heal: Disabled
原因:
先观察 OutOfSync 手工确认差异 验证 Pipeline GitOpsSync 降低误删资源的风险
完成实验后,可以逐步开启:
Automatic Sync Self Heal Prune Apply Out Of Sync Only
二十八:Prune、Self Heal 的含义
Prune
如果 Git 中删除了某个资源,例如:
service.yaml 被删除
开启 Prune 后,GitOps 同步可以从集群删除这个 Service。
风险:
错误提交可能删除仍在使用的资源
建议:
dev/test 可在验证后开启 prod 开启前必须有 MR 审核、保护分支和删除保护策略
Self Heal
如果有人手工修改集群:
kubectl scale deployment harness-gitops-demo \
--replicas=1 \
-n gitops-dev
而 Git 中仍是:
replicas: 2
开启 Self Heal 后,Controller 可以重新恢复为两个副本。
二十九:第一次手工同步
创建 Application 后,初始状态通常可能是:
Sync Status: OutOfSync
进入 Application 页面,查看 App Diff。
确认差异后执行:
Sync → Synchronize
同步后检查:
kubectl get deployment -n gitops-dev
kubectl get pods -n gitops-dev
kubectl get service -n gitops-dev
期望 Harness 显示:
Sync Status: Synced
Health Status: Healthy
三十:Pipeline GitOps 流程设计
推荐 Pipeline:
Pipeline: harness-gitops-release
Stage 1: CI Test
- npm install
- npm test
Stage 2: Build And Push
- docker build
- docker push Harbor
Stage 3: Update GitOps Repository
- clone GitOps Repository
- 修改 Deployment image
- 修改 ConfigMap APP_VERSION
- git commit
- git push
Stage 4: GitOps Sync
- GitOpsSync
- Wait Until Healthy
- Fail If Step Times Out
Stage 5: Verify
- 检查 Application 状态
- 业务冒烟测试
GitOps 模式下不要再加入:
K8sRollingDeploy kubectl apply HelmDeploy
否则会形成两个部署控制源:
Pipeline 直接部署 GitOps Controller 同步
容易造成配置互相覆盖。
三十一:Pipeline 变量
variables:
- name: app_name
type: String
value: harness-gitops-demo
- name: deploy_env
type: String
value: dev
- name: image_repository
type: String
value: harbor.company.com/devops/harness-gitops-demo
- name: image_tag
type: String
value: <+input>
- name: gitops_repo_url
type: String
value: https://gitlab.company.com/devops/harness-gitops-config.git
- name: gitops_branch
type: String
value: main
- name: gitops_manifest_path
type: String
value: applications/harness-gitops-demo/dev/deployment.yaml
- name: gitops_configmap_path
type: String
value: applications/harness-gitops-demo/dev/configmap.yaml
三十二:更新 GitOps Repository 脚本
scripts/update-gitops-image.sh
#!/usr/bin/env bash
set -euo pipefail
GITOPS_REPO_URL="${GITOPS_REPO_URL:?GITOPS_REPO_URL is required}"
GITOPS_BRANCH="${GITOPS_BRANCH:-main}"
GIT_USERNAME="${GIT_USERNAME:?GIT_USERNAME is required}"
GIT_TOKEN="${GIT_TOKEN:?GIT_TOKEN is required}"
GIT_HOST="${GIT_HOST:?GIT_HOST is required}"
APP_NAME="${APP_NAME:?APP_NAME is required}"
DEPLOY_ENV="${DEPLOY_ENV:?DEPLOY_ENV is required}"
IMAGE_REPOSITORY="${IMAGE_REPOSITORY:?IMAGE_REPOSITORY is required}"
IMAGE_TAG="${IMAGE_TAG:?IMAGE_TAG is required}"
IMAGE_FULL_NAME="${IMAGE_REPOSITORY}:${IMAGE_TAG}"
DEPLOYMENT_FILE="${DEPLOYMENT_FILE:?DEPLOYMENT_FILE is required}"
CONFIGMAP_FILE="${CONFIGMAP_FILE:?CONFIGMAP_FILE is required}"
WORK_DIR="$(mktemp -d)"
NETRC_FILE="${HOME}/.netrc"
cleanup() {
rm -rf "${WORK_DIR}"
rm -f "${NETRC_FILE}"
}
trap cleanup EXIT
if [ "${DEPLOY_ENV}" = "prod" ] && [ "${IMAGE_TAG}" = "latest" ]; then
echo "ERROR: 生产环境禁止使用 latest"
exit 1
fi
cat > "${NETRC_FILE}" <<EOF
machine ${GIT_HOST}
login ${GIT_USERNAME}
password ${GIT_TOKEN}
EOF
chmod 600 "${NETRC_FILE}"
git clone \
--branch "${GITOPS_BRANCH}" \
"${GITOPS_REPO_URL}" \
"${WORK_DIR}/gitops-config"
cd "${WORK_DIR}/gitops-config"
test -f "${DEPLOYMENT_FILE}"
test -f "${CONFIGMAP_FILE}"
OLD_IMAGE="$(yq '.spec.template.spec.containers[0].image' "${DEPLOYMENT_FILE}")"
echo "OLD_IMAGE=${OLD_IMAGE}"
echo "NEW_IMAGE=${IMAGE_FULL_NAME}"
IMAGE_FULL_NAME="${IMAGE_FULL_NAME}" \
yq -i \
'.spec.template.spec.containers[0].image = strenv(IMAGE_FULL_NAME)' \
"${DEPLOYMENT_FILE}"
IMAGE_TAG="${IMAGE_TAG}" \
yq -i \
'.data.APP_VERSION = strenv(IMAGE_TAG)' \
"${CONFIGMAP_FILE}"
git diff -- "${DEPLOYMENT_FILE}" "${CONFIGMAP_FILE}"
if git diff --quiet; then
echo "GitOps 配置没有变化,无需提交"
exit 0
fi
git config user.name "Harness GitOps Bot"
git config user.email "harness-gitops-bot@company.com"
git add "${DEPLOYMENT_FILE}" "${CONFIGMAP_FILE}"
git commit -m "deploy(${DEPLOY_ENV}): ${APP_NAME} ${IMAGE_TAG}"
git push origin "${GITOPS_BRANCH}"
echo "GitOps Repository 更新完成"
echo "IMAGE_FULL_NAME=${IMAGE_FULL_NAME}"
三十三:在 Pipeline 中运行更新脚本
建议使用包含以下工具的企业内部镜像:
git yq bash ca-certificates
例如:
harbor.company.com/library/git-yq:latest
Run Step:
chmod +x scripts/update-gitops-image.sh
GITOPS_REPO_URL="<+pipeline.variables.gitops_repo_url>" \
GITOPS_BRANCH="<+pipeline.variables.gitops_branch>" \
GIT_HOST="gitlab.company.com" \
GIT_USERNAME="<+secrets.getValue('gitops_bot_username')>" \
GIT_TOKEN="<+secrets.getValue('gitops_bot_token')>" \
APP_NAME="<+pipeline.variables.app_name>" \
DEPLOY_ENV="<+pipeline.variables.deploy_env>" \
IMAGE_REPOSITORY="<+pipeline.variables.image_repository>" \
IMAGE_TAG="<+pipeline.variables.image_tag>" \
DEPLOYMENT_FILE="<+pipeline.variables.gitops_manifest_path>" \
CONFIGMAP_FILE="<+pipeline.variables.gitops_configmap_path>" \
scripts/update-gitops-image.sh
不要开启:
set -x
否则 Secret 有被输出到日志的风险。
三十四:生产环境不要直接推 main
为了简化实验,dev 可以让 Pipeline 直接推送到配置仓库。
生产推荐:
Pipeline 创建发布分支 ↓ 修改生产 Manifest ↓ 创建 Merge Request ↓ 质量门检查 ↓ 生产负责人审批 ↓ 合并 main ↓ GitOps Sync
生产配置仓库应启用:
保护分支 禁止 Force Push 至少一人或两人 Review CODEOWNERS 提交签名,可选 敏感文件扫描 YAML 校验 OPA/Kyverno 策略检查
三十五:在 Pipeline 中添加 GitOpsSync
创建 Deployment Stage,并选择与 Application 一致的:
Service: harness-gitops-demo
Environment: dev
Cluster: in-cluster
进入 Execution:
Add Step → GitOpsSync
配置:
Application Selection: Application Name
Application: harness-gitops-demo-dev
Wait Until Healthy: Enabled
Fail If Step Times Out: Enabled
Timeout: 10m 或 15m
初次实验建议:
Prune: Disabled
Force: Disabled
Replace: Disabled
具体可见选项会随 Harness 版本和 Application 配置变化。
三十六:GitOpsSync YAML 参考
GitOpsSync 的 YAML 字段可能随 Harness 版本、Application 选择方式和 Sync Options 变化。
建议先在 Visual Editor 配置成功,再导出实际 YAML。
结构示意:
- step:
type: GitOpsSync
name: Sync GitOps Application
identifier: sync_gitops_application
timeout: 15m
spec: {}
不要根据示意 YAML 猜测完整字段。
在 UI 中重点确认:
应用选择正确 Service、Environment、Cluster 与 Application 一致 Wait Until Healthy 已开启 Fail If Step Times Out 已开启 同步超时时间合理
三十七:为什么要开启 Wait Until Healthy
只完成 Sync,不等于业务已经正常。
例如:
Manifest 已成功提交到 Kubernetes Deployment 已创建 Pod 仍然 ImagePullBackOff readinessProbe 失败 应用一直 CrashLoopBackOff
如果不等待 Healthy,Pipeline 可能在业务不可用时显示成功。
推荐:
dev/test: Wait Until Healthy = true
pre/prod: Wait Until Healthy = true Fail If Step Times Out = true
三十八:验证 Pipeline 发布结果
Pipeline 完成后检查 Git:
git log --oneline -5
检查 Manifest:
grep image: \
applications/harness-gitops-demo/dev/deployment.yaml
检查 Kubernetes:
kubectl get deployment \
harness-gitops-demo \
-n gitops-dev \
-o wide
kubectl get pods \
-n gitops-dev \
-l app=harness-gitops-demo
kubectl get deployment \
harness-gitops-demo \
-n gitops-dev \
-o jsonpath='{.spec.template.spec.containers[0].image}'
检查业务:
kubectl port-forward \
service/harness-gitops-demo \
18080:80 \
-n gitops-dev
另一个终端:
curl -f http://127.0.0.1:18080/health
curl -f http://127.0.0.1:18080/
三十九:GitOps 状态说明
Synced + Healthy
Git 与集群状态一致 资源运行正常
这是正常状态。
OutOfSync + Healthy
业务当前可以运行 但集群状态与 Git 不一致
常见原因:
Git 已修改但尚未同步 有人手工修改集群 外部 Controller 修改了资源
Synced + Progressing
配置已经应用 但 Deployment 正在发布
Synced + Degraded
配置已经应用 但业务资源运行异常
常见原因:
镜像不存在 镜像拉取失败 容器启动失败 readinessProbe 失败 资源限制不足 应用依赖不可用
Unknown
Agent 无法完整读取 Git 或 Cluster 状态
常见原因:
Git Repository 不可访问 Cluster 凭证失效 Agent 异常 Repo Server 异常 网络超时
四十:测试 Drift Detection
先确认 Git 中:
replicas: 2
手工修改集群:
kubectl scale deployment \
harness-gitops-demo \
--replicas=1 \
-n gitops-dev
检查:
kubectl get deployment \
harness-gitops-demo \
-n gitops-dev
回到 Harness Application 页面,执行 Refresh。
预期:
Application = OutOfSync
如果 Self Heal 未开启,副本数会暂时保持为 1。
执行 Sync 后:
kubectl get deployment \
harness-gitops-demo \
-n gitops-dev
副本数应重新恢复到 2。
开启 Self Heal 后再次测试,Controller 应能自动纠正漂移。
四十一:GitOps 正确回滚方式
传统 Kubernetes 回滚可能使用:
kubectl rollout undo deployment/harness-gitops-demo
但在 GitOps 中,这不是推荐的最终回滚方式。
原因:
kubectl rollout undo 只修改集群 Git 仍然指向新版本 Application 会变成 OutOfSync 下一次 Sync 可能再次部署新版本
GitOps 推荐:
找到修改镜像的 Git Commit ↓ git revert ↓ 推送回配置仓库 ↓ GitOpsSync ↓ 集群恢复旧版本
四十二:Git revert 回滚示例
查看历史:
git log --oneline -10
假设错误发布 Commit:
abc1234 deploy(dev): harness-gitops-demo v1.2.0
执行:
git revert abc1234
git push origin main
然后重新运行 GitOpsSync。
验证:
kubectl get deployment \
harness-gitops-demo \
-n gitops-dev \
-o jsonpath='{.spec.template.spec.containers[0].image}'
这样 Git 历史会保留:
发布 v1.2.0 回滚 v1.2.0 恢复到上一版本
整个过程可审计、可复现。
四十三:Pipeline 自动回滚到上一 Git Commit
可以在 Pipeline 中准备一个人工回滚流程:
输入 rollback_commit ↓ 创建 Revert Commit ↓ 推送 GitOps Repository ↓ GitOpsSync ↓ 等待 Healthy
示例脚本:
#!/usr/bin/env bash
set -euo pipefail
ROLLBACK_COMMIT="${ROLLBACK_COMMIT:?ROLLBACK_COMMIT is required}"
git revert \
--no-edit \
"${ROLLBACK_COMMIT}"
git push origin main
生产环境不要让流水线任意执行:
git reset --hard
git push --force
Force Push 会破坏审计历史。
四十四:自动同步与手动同步如何选择
dev
推荐:
Automatic Sync: Enabled
Self Heal: Enabled
Prune: 验证后开启
适合快速反馈。
test
推荐:
Automatic Sync: 可选
Self Heal: Enabled
Prune: 谨慎开启
pre
推荐:
Manual Sync 或 Pipeline GitOpsSync 必须审批 Wait Until Healthy
prod
推荐:
配置变更必须 MR 合并前必须审批 通过 Pipeline GitOpsSync 同步 Wait Until Healthy Fail If Step Times Out Prune 需要严格治理
不要只依赖“任何 main Commit 自动进入生产”。
四十五:GitOps 配置仓库校验
建议为 GitOps Repository 增加 CI。
检查 YAML:
find applications \
-name "*.yaml" \
-o -name "*.yml" \
| xargs -r yamllint -d relaxed
执行客户端 Dry Run:
kubectl apply \
--dry-run=client \
-f applications/harness-gitops-demo/dev
使用 kubeconform:
kubeconform \
-strict \
-summary \
applications/harness-gitops-demo/dev/*.yaml
检查生产 latest:
if grep -RIn 'image:.*:latest' applications/*/prod; then
echo "ERROR: prod 禁止使用 latest"
exit 1
fi
检查明文 Secret:
grep -RInE \
'password:|token:|secretKey:|accessKey:' \
applications \
&& exit 1 || true
四十六:GitOps 仓库权限设计
GitOps Agent 读取账号
权限:
只读配置仓库
Harness Pipeline Bot
dev 可配置:
允许推送 dev 配置
生产推荐:
只能创建分支和 Merge Request 不能直接推送保护分支
开发人员
建议:
可以修改自己服务目录 不能修改其他服务 生产目录需要 CODEOWNERS
平台团队
负责:
目录规范 同步策略 Application Agent Cluster RBAC 基础策略
四十七:Agent 权限设计
基础实验中可能使用较高权限,但生产应收紧。
推荐按以下边界拆分:
dev Agent: 只管理 dev Namespace 或 dev Cluster
test Agent: 只管理 test Namespace 或 test Cluster
prod Agent: 只管理 prod Cluster
不要让一个开发环境 Agent 同时拥有:
所有生产集群 cluster-admin
如果使用 Namespaced Agent,需要确认:
Agent 访问范围 CRD 是否已安装 目标 Namespace Repository 和 Cluster 配置 Application 是否只管理允许的资源
四十八:国内网络环境问题
1. Agent 镜像拉取失败
表现:
ImagePullBackOff ErrImagePull i/o timeout
解决:
把 Agent 和 Argo CD 镜像同步到 Harbor 配置私有镜像地址 创建 imagePullSecret 检查节点到 Harbor 的网络 配置企业 CA
2. GitLab 连接失败
表现:
repository not found authentication required x509 unknown authority connection timeout
排查:
kubectl exec \
deployment/argocd-repo-server \
-n harness-gitops \
-- sh
容器内检查:
wget -S -O - https://gitlab.company.com 2>&1 | head
更推荐直接查看 Repo Server 日志:
kubectl logs \
deployment/argocd-repo-server \
-n harness-gitops \
--tail=300
3. Harbor 镜像拉取失败
检查:
kubectl describe pod POD_NAME -n gitops-dev
kubectl get secret \
harbor-pull-secret \
-n gitops-dev
常见原因:
Secret 不在目标 Namespace Robot Token 失效 镜像 Tag 不存在 节点不信任 Harbor CA
4. Harness SaaS 连接失败
查看 Agent 日志:
kubectl logs \
deployment/gitops-agent \
-n harness-gitops \
--tail=300
检查:
企业防火墙 HTTPS 代理 DNS NO_PROXY 系统时间 证书链
5. Application 一直 OutOfSync
检查:
Repository Revision 是否正确 Path 是否正确 Namespace 是否正确 App Diff 具体内容 是否有 Mutating Webhook 修改字段 是否有 HPA 修改 replicas 是否有其他 Controller 修改资源
如果 HPA 管理副本数,应考虑忽略由 HPA 管理的差异,而不是反复让两个 Controller 互相修改。
四十九:常见问题排查
1. Agent 状态不健康
kubectl get pods -n harness-gitops
kubectl get events -n harness-gitops \
--sort-by=.metadata.creationTimestamp
逐个查看:
kubectl logs deployment/gitops-agent -n harness-gitops
kubectl logs deployment/argocd-repo-server -n harness-gitops
kubectl logs statefulset/argocd-application-controller -n harness-gitops
2. Application 显示 Missing
可能原因:
资源被手工删除 目标 Namespace 错误 Application Path 中已删除资源 集群访问权限不足
执行 Refresh 后查看 App Diff。
3. Sync 成功但 Pipeline 超时
可能是:
Application 已同步 但一直没有达到 Healthy
检查:
kubectl get pods -n gitops-dev
kubectl describe deployment harness-gitops-demo -n gitops-dev
kubectl get events -n gitops-dev \
--sort-by=.metadata.creationTimestamp
通常原因是:
镜像拉取失败 readinessProbe 错误 资源不足 应用启动过慢 依赖服务不可用
4. Pipeline 更新 Git 后 Application 没变化
检查:
Application Target Revision Application Path Pipeline 推送的分支 Git Commit 是否真正成功 Repository 是否读取到新 Commit
在 Harness Application 页面执行:
Refresh
Refresh 只刷新状态,不等同于 Sync。
五十:企业最佳实践
1. 应用仓库与配置仓库分离
推荐:
应用仓库: 源码、测试、Dockerfile
配置仓库: Kubernetes、Helm、Kustomize、环境配置
2. 镜像 Tag 必须不可变
推荐:
v1.2.0 main-a1b2c3d-102 release-20260715-001
禁止生产使用:
latest prod stable
3. 生产通过 MR 更新 GitOps 仓库
推荐:
Build ↓ Scan ↓ 创建 GitOps MR ↓ 审批 ↓ 合并 ↓ GitOpsSync
4. 不允许多个系统同时管理同一资源
不要同时使用:
Harness K8sRollingDeploy Argo CD GitOps Sync 手工 kubectl apply Helm CLI
管理同一个 Deployment。
每个资源应明确唯一控制者。
5. 回滚必须回到 Git
短期紧急操作可以在集群中止损,但最终必须:
把正确状态提交回 Git
否则 GitOps Controller 后续仍会按 Git 重新同步。
6. Application 必须设置健康检查
Deployment 应配置:
readinessProbe livenessProbe resources
否则 Application 的 Healthy 状态不能完整代表业务可用。
7. 监控 Agent
至少监控:
Agent Connected 状态 Repo Server 错误率 Application Controller 状态 同步失败次数 OutOfSync Application 数量 Degraded Application 数量 Redis 状态 Agent Pod 重启次数
五十一:练习 1:安装 GitOps Agent
目标:
Agent 在 harness-gitops Namespace 正常运行。
步骤:
- 在 Harness 创建 Agent
- 下载 override.yaml 或 gitops-agent.yaml
- 使用 Helm 或 kubectl 安装
- 检查 Pod
- 在 Harness 确认 Healthy 和 Connected
验收:
kubectl get pods -n harness-gitops
所有核心组件正常运行。
五十二:练习 2:创建 Repository 和 Application
目标:
创建 harness-gitops-demo-dev Application。
步骤:
- 创建 GitOps Repository
- 使用 in-cluster
- 创建 Service 和 Environment
- 创建 Application
- 设置 main 分支
- 设置 dev Manifest 路径
- 手工 Sync
验收:
Application = Synced Application = Healthy
五十三:练习 3:Pipeline 更新镜像并同步
目标:
Pipeline 把镜像从 v1.0.0 更新到 v1.1.0。
步骤:
- 构建 v1.1.0 镜像
- 推送到 Harbor
- 更新 Deployment image
- 提交 GitOps Repository
- 执行 GitOpsSync
- 等待 Healthy
验收:
kubectl get deployment \
harness-gitops-demo \
-n gitops-dev \
-o jsonpath='{.spec.template.spec.containers[0].image}'
输出为:
harbor.company.com/devops/harness-gitops-demo:v1.1.0
五十四:练习 4:验证 Drift Correction
目标:
手工修改副本数,并让 GitOps 恢复期望状态。
执行:
kubectl scale deployment \
harness-gitops-demo \
--replicas=1 \
-n gitops-dev
观察:
Application 变成 OutOfSync
执行 Sync 或开启 Self Heal。
验收:
kubectl get deployment \
harness-gitops-demo \
-n gitops-dev
副本数重新恢复为 Git 中声明的数量。
五十五:练习 5:Git revert 回滚
目标:
把错误镜像版本回滚到上一版本。
步骤:
- 找到镜像更新 Commit
- 执行 git revert
- 推送 main
- 执行 GitOpsSync
- 等待 Healthy
验收:
Git 中为旧镜像 集群中为旧镜像 Application = Synced Application = Healthy
五十六:验收标准
完成本文后,应达到:
已理解 GitOps 基本原理 已理解 Desired State 和 Live State 已理解 Synced、OutOfSync、Healthy、Degraded 已能安装 Harness GitOps Agent 已能检查 Agent 和 Argo CD 组件 已能添加 GitOps Repository 已能使用 in-cluster 或配置目标 Cluster 已能创建 Service、Environment 和 Application 已能手工执行 Sync 已能在 Pipeline 中更新 GitOps 配置仓库 已能配置 GitOpsSync 已能等待 Application Healthy 已能验证 Drift Correction 已能通过 git revert 完成回滚 已能处理国内网络和私有仓库问题
五十七:本篇总结
本篇完成了 Harness GitOps 的基础落地。
需要重点记住:
Git 是期望状态的单一事实来源 Pipeline 负责构建、测试和更新 Git GitOps Agent 与 Argo CD 负责同步集群 GitOps Agent 不等于 Harness Delegate Application 连接 Repository、Cluster 和 Agent Refresh 只刷新状态,Sync 才应用变更 Synced 不一定等于 Healthy Pipeline 中应开启 Wait Until Healthy 不要让 GitOps 和普通 CD 同时管理同一资源 生产配置应通过 Merge Request 变更 GitOps 回滚应使用 git revert Self Heal 可以纠正手工集群漂移 Prune 可能删除资源,生产开启前必须严格治理 国内环境要提前解决镜像、代理、证书和私有 Git 访问
更多推荐




所有评论(0)