1. 引言:什么是 Harness?
Harness 是一个现代化的持续交付(Continuous Delivery,CD)平台,旨在通过自动化、智能化和可观测性,帮助企业实现从代码提交到生产部署的端到端软件交付流程。它不仅仅是传统的 CI/CD 工具,更是一个集成了持续集成、持续部署、功能发布、云成本管理、安全合规(如 STO)和混沌工程等能力的综合性平台。
核心价值主张:
- 自动化:减少手动操作,提升交付速度与可靠性。
- 智能化:利用机器学习(ML)分析部署数据,提供风险预测、自动回滚等决策支持。
- 可观测性:提供部署过程的全链路监控、日志和指标,实现端到端的可视化。
- 开发者体验:通过声明式配置、GitOps 和直观的 UI,降低 DevOps 门槛。
本文将深入剖析 Harness 的核心架构原理,并通过详细的代码实践,展示如何利用 Harness 构建一个完整的、企业级的持续交付流水线。
2. Harness 核心架构解析
Harness 平台采用微服务架构,其核心组件协同工作,共同支撑起复杂的交付流程。下图展示了其简化的高层架构:
#mermaid-svg-uP6PMmItKyiaHYzJ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uP6PMmItKyiaHYzJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uP6PMmItKyiaHYzJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uP6PMmItKyiaHYzJ .error-icon{fill:#552222;}#mermaid-svg-uP6PMmItKyiaHYzJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uP6PMmItKyiaHYzJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uP6PMmItKyiaHYzJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uP6PMmItKyiaHYzJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uP6PMmItKyiaHYzJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uP6PMmItKyiaHYzJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uP6PMmItKyiaHYzJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uP6PMmItKyiaHYzJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uP6PMmItKyiaHYzJ .marker.cross{stroke:#333333;}#mermaid-svg-uP6PMmItKyiaHYzJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uP6PMmItKyiaHYzJ p{margin:0;}#mermaid-svg-uP6PMmItKyiaHYzJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uP6PMmItKyiaHYzJ .cluster-label text{fill:#333;}#mermaid-svg-uP6PMmItKyiaHYzJ .cluster-label span{color:#333;}#mermaid-svg-uP6PMmItKyiaHYzJ .cluster-label span p{background-color:transparent;}#mermaid-svg-uP6PMmItKyiaHYzJ .label text,#mermaid-svg-uP6PMmItKyiaHYzJ span{fill:#333;color:#333;}#mermaid-svg-uP6PMmItKyiaHYzJ .node rect,#mermaid-svg-uP6PMmItKyiaHYzJ .node circle,#mermaid-svg-uP6PMmItKyiaHYzJ .node ellipse,#mermaid-svg-uP6PMmItKyiaHYzJ .node polygon,#mermaid-svg-uP6PMmItKyiaHYzJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uP6PMmItKyiaHYzJ .rough-node .label text,#mermaid-svg-uP6PMmItKyiaHYzJ .node .label text,#mermaid-svg-uP6PMmItKyiaHYzJ .image-shape .label,#mermaid-svg-uP6PMmItKyiaHYzJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-uP6PMmItKyiaHYzJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uP6PMmItKyiaHYzJ .rough-node .label,#mermaid-svg-uP6PMmItKyiaHYzJ .node .label,#mermaid-svg-uP6PMmItKyiaHYzJ .image-shape .label,#mermaid-svg-uP6PMmItKyiaHYzJ .icon-shape .label{text-align:center;}#mermaid-svg-uP6PMmItKyiaHYzJ .node.clickable{cursor:pointer;}#mermaid-svg-uP6PMmItKyiaHYzJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uP6PMmItKyiaHYzJ .arrowheadPath{fill:#333333;}#mermaid-svg-uP6PMmItKyiaHYzJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uP6PMmItKyiaHYzJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uP6PMmItKyiaHYzJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uP6PMmItKyiaHYzJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uP6PMmItKyiaHYzJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uP6PMmItKyiaHYzJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uP6PMmItKyiaHYzJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uP6PMmItKyiaHYzJ .cluster text{fill:#333;}#mermaid-svg-uP6PMmItKyiaHYzJ .cluster span{color:#333;}#mermaid-svg-uP6PMmItKyiaHYzJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uP6PMmItKyiaHYzJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uP6PMmItKyiaHYzJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-uP6PMmItKyiaHYzJ .icon-shape,#mermaid-svg-uP6PMmItKyiaHYzJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uP6PMmItKyiaHYzJ .icon-shape p,#mermaid-svg-uP6PMmItKyiaHYzJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uP6PMmItKyiaHYzJ .icon-shape .label rect,#mermaid-svg-uP6PMmItKyiaHYzJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uP6PMmItKyiaHYzJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uP6PMmItKyiaHYzJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uP6PMmItKyiaHYzJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 拉取镜像、执行命令
反馈状态
上报数据
展示结果
开发者 (Git Push)
Harness GitOps Agent
Harness Manager (控制平面)
Harness Delegate (数据平面)
目标环境 (K8s, VMs, Serverless)
Harness Database (PostgreSQL)
Harness Secrets Manager
外部服务 (Docker Hub, AWS, GCP)
开发者/运维 (UI/API)
2.1 核心组件详解
-
Harness Manager (控制平面)
- 作用:提供 Web UI、API 和核心业务逻辑。它是用户交互和流程编排的中心。
- 功能:管理用户、项目、流水线(Pipelines)、机密(Secrets)、连接器(Connectors)等。
- 部署:通常由 Harness 以 SaaS 形式提供,也支持自托管(On-Premises)。
-
Harness Delegate (数据平面/代理)
- 作用:一个轻量级的 Worker 进程,部署在您的目标环境(如 Kubernetes 集群、VM)中。它是执行所有实际任务(如部署、测试、验证)的组件。
- 工作原理:Manager 将任务放入队列,Delegate 拉取任务并执行,然后将结果和日志上报给 Manager。
- 优势:无需在 Harness SaaS 和您的私有环境之间开放入站防火墙,Delegate 仅需出站连接到 Manager,安全性更高。
-
Harness GitOps Agent
- 作用:专门用于 GitOps 工作流。它持续监控 Git 仓库中声明的 Kubernetes 清单(如 YAML 文件),一旦有变更,就自动同步到目标集群。
- 与 Delegate 的关系:GitOps Agent 是 Delegate 的一种特殊类型,专注于 Git 仓库与集群状态的同步。
-
Harness Secrets Manager
- 作用:安全地存储和管理敏感信息,如 API 密钥、密码、证书等。
- 支持的后端:内置的 Harness Secrets Manager、HashiCorp Vault、AWS Secrets Manager、Azure Key Vault 等。
-
Harness Database
- 作用:存储平台的所有元数据、配置和运行数据。
- 技术栈:通常使用 PostgreSQL。
2.2 关键架构原则
- 声明式配置:所有流水线、服务、环境等均通过 YAML 或 UI 进行声明式定义,配置即代码(Configuration as Code)。
- 不可变基础设施:通过容器镜像和声明式清单(如 K8s YAML)来部署应用,确保环境一致性。
- 基于事件的驱动:整个交付流程由 Git Push、Webhook、定时器或 API 调用等事件触发。
- 插件化与扩展性:通过自定义步骤(Custom Steps)、脚本、插件市场(如 Drone 插件)来扩展功能。
3. 工程实践:构建一个完整的 K8s 部署流水线
我们将创建一个完整的流水线,实现以下流程:
- 代码提交到 Git 仓库(如 GitHub)触发流水线。
- 构建 Docker 镜像并推送到镜像仓库(如 Docker Hub)。
- 将应用部署到 Kubernetes 开发(Dev)环境。
- 运行自动化集成测试。
- 手动批准后,将相同的镜像部署到生产(Prod)环境。
- 进行部署后验证(如健康检查)。
3.1 前置准备
- Harness 账号 :访问 Harness.io 注册免费试用账号。
- 目标 Kubernetes 集群:一个可用的 K8s 集群(如 Minikube、Kind 或云厂商的 K8s 服务)。
- 代码仓库:一个包含简单应用的 GitHub 仓库。我们将使用一个示例 Node.js 应用。
- 镜像仓库:Docker Hub 或任何兼容的容器镜像仓库账号。
3.2 在 Harness 中配置连接器(Connectors)
连接器是 Harness 与外部系统(如 Git、Docker Registry、K8s 集群)通信的凭证和配置。
步骤 1:配置 Git 连接器
- 在 Harness 项目中,进入 Connectors -> + New Connector -> Git。
- 选择您的 Git 提供商(如 GitHub)。
- 选择认证方式(如 Personal Access Token)。
- 输入 Token 并测试连接。
步骤 2:配置 Docker Registry 连接器
- Connectors -> + New Connector -> Docker Registry。
- 选择提供商(如 Docker Hub)。
- 输入用户名和密码(或 Access Token)。
- 测试连接。
步骤 3:配置 Kubernetes 集群连接器
- Connectors -> + New Connector -> Kubernetes Cluster。
- 选择 Inherit from Delegate(推荐)。这意味着将使用部署在目标 K8s 集群中的 Harness Delegate 来执行部署操作,无需提供 Kubeconfig。
- 确保已在目标集群中安装了 Harness Delegate(安装向导会提供 YAML 文件)。
3.3 定义 Harness 服务(Service)
服务代表您要部署的应用程序。我们使用 Kubernetes 清单进行声明式定义。
- 在 Harness 项目中,进入 Services -> + New Service。
- 输入服务名称,如
nodejs-sample。 - 部署类型 选择 Kubernetes。
- 在 Service Definition 中,选择 Kubernetes Manifest。
- 在 Manifests 部分,点击 + Add Manifest -> K8s Manifest。
- 选择您之前创建的 Git 连接器,并指定存储 Kubernetes YAML 文件的仓库路径(如
/manifests/deployment.yaml)。
示例 deployment.yaml 内容:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nodejs-sample
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: nodejs-sample
template:
metadata:
labels:
app: nodejs-sample
spec:
containers:
- name: nodejs-sample
image: <+artifact.image> # Harness 表达式,运行时由流水线注入
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
---
apiVersion: v1
kind: Service
metadata:
name: nodejs-sample
namespace: default
spec:
selector:
app: nodejs-sample
ports:
- port: 80
targetPort: 3000
type: LoadBalancer # 或 ClusterIP,根据环境而定
注意 <+artifact.image> 是 Harness 的运行时表达式,它将在流水线执行时被替换为实际构建的镜像地址。
3.4 定义环境(Environments)与基础设施定义(Infrastructure Definition)
环境代表部署的目标,如开发、测试、生产。
- 进入 Environments -> + New Environment。
- 创建两个环境:
dev和prod。 - 为每个环境添加 Infrastructure Definition 。
- 类型选择 Kubernetes Direct(直接连接)。
- 选择之前创建的 Kubernetes 集群连接器。
- 指定命名空间(如
default)。
3.5 构建流水线(Pipeline)
这是核心部分,我们将编排整个交付流程。
- 创建流水线 :进入 Pipelines -> + New Pipeline。
- 添加触发器 :在 Triggers 选项卡,添加一个新的 Git 触发器。配置为监听主分支(如
main)的推送事件。这样,每次代码推送都会自动触发流水线。 - 设计流水线阶段 :
-
阶段 1: Build & Push Image
- 阶段类型: CI
- 执行步骤 :
-
Run : 一个
Run步骤,执行 Shell 命令来构建 Docker 镜像。bashdocker build -t yourdockerhub/username/nodejs-sample:<+pipeline.sequenceId> . docker push yourdockerhub/username/nodejs-sample:<+pipeline.sequenceId><+pipeline.sequenceId>是流水线运行 ID,可作为唯一标签。 -
Artifact Upload (可选但推荐) : 使用 Upload Artifact to Harness 步骤,将镜像信息(如 tag)作为制品上传,供后续阶段引用。
-
-
阶段 2: Deploy to Dev
- 阶段类型: CD
- 环境 : 选择之前创建的
dev环境。 - 服务 : 选择
nodejs-sample服务。 - 执行步骤 :
-
Rollout Deployment : 这是核心部署步骤。Harness 会使用服务中定义的 K8s 清单,并将
<+artifact.image>替换为第一阶段构建的镜像,然后执行kubectl apply。 -
Shell Script : 部署后,可以运行一个脚本进行简单的健康检查或冒烟测试。
bash# 示例:测试服务是否可达 sleep 30 # 等待 Pod 就绪 curl -f http://nodejs-sample-dev.default.svc.cluster.local || exit 1
-
-
阶段 3: Manual Approval
- 阶段类型: Approval
- 在部署到生产环境前,添加一个 Manual Approval 步骤。可以指定审批人(用户或用户组)。
-
阶段 4: Deploy to Prod
- 阶段类型: CD
- 环境 : 选择
prod环境。 - 服务 : 同样选择
nodejs-sample服务。 - 执行步骤 :
- Rollout Deployment : 与开发环境类似,但可能使用不同的配置(如副本数、资源限制)。可以通过 Harness 的 Service Overrides 或环境特定的 ConfigMap 来实现。
- Verify : 使用 Harness 的 Verify 步骤进行更深入的部署后验证。它可以集成 Prometheus、Datadog 等监控工具,分析部署前后的指标,自动判断部署是否成功,并在检测到异常时触发自动回滚。
-
3.6 高级特性实践:Canary 部署与自动回滚
Harness 的强大之处在于其高级部署策略。让我们修改生产环境部署阶段,使用 Canary 部署。
- 在 Deploy to Prod 阶段的 Execution 策略中,将 Deployment Type 从 Basic 改为 Canary。
- Harness 会提供一个可视化的配置界面。您可以定义:
- Canary Steps: 初始将 10% 的流量导到新版本。
- Post-Deployment Steps: 等待一段时间进行验证(如 10 分钟)。
- Verify Step: 分析此期间的错误率、延迟等指标。
- Promotion/ Rollback: 如果验证通过,则逐步将剩余流量切换到新版本(如每次 20%)。如果验证失败(错误率飙升),则自动将流量全部切回旧版本(回滚)。
配置示例(YAML 片段):
yaml
- step:
type: CanaryDeploy
spec:
canarySteps:
- step:
type: UpdateReleaseRepo
name: Canary Deployment 10%
spec:
instances: 10%
- step:
type: Verify
name: Verify Canary
spec:
duration: 10m
type: Prometheus
spec:
...
postDeploymentSteps:
- step:
type: CanaryDelete
name: Promote Canary
spec:
type: LoadBalancer
traffic: 100%
- step:
type: Rollback
name: Rollback Canary
spec:
type: LoadBalancer
traffic: 0%
通过这种配置,您实现了低风险的、基于指标的自动化渐进式交付。
4. 总结与最佳实践
通过上述架构解析与实践,我们可以看到 Harness 如何将复杂的持续交付流程标准化、自动化与智能化。
最佳实践建议:
- 一切皆代码:将流水线、服务、环境定义存储在 Git 仓库中,实现版本控制和审计。
- 善用 Delegates:根据环境隔离和网络策略,在不同集群或 VPC 中部署独立的 Delegates。
- 秘密管理:始终使用 Harness Secrets Manager 或集成的 Vault,切勿将敏感信息硬编码。
- 利用策略(Policies):定义部署策略(如必须通过安全扫描、必须有人工审批)并应用到环境。
- 监控与优化:充分利用 Harness 的部署分析(Deployment Analytics)功能,识别瓶颈,优化交付周期时间。
- 渐进式交付:对于关键应用,从 Blue-Green 或 Canary 部署开始,逐步建立对自动化部署的信心。
Harness 通过其模块化、可扩展的架构,不仅简化了 CI/CD 的初始搭建,更通过智能化功能为高速、高可靠性的软件交付提供了强大保障。随着团队和项目复杂度的增长,其平台价值将愈发凸显。