本仓库是浙江大学超算队(ZJUSCT)的 Kubernetes 集群 GitOps 配置中心,实现集群状态的声明式管理与持续同步。本项目是一次面向 AI 辅助运维(AIOps)新范式的探索与实践。
本项目的设计理念可以用一句话概括:让 AI 接管耗时巨大的信息处理工作,从而使人类工程师能聚焦于系统的逻辑设计与架构决策。
传统运维工作的核心挑战,源于系统不断演进中积累的固有复杂性,以及随之而来的信息传递与处理的高昂成本。配置的意图、服务间的依赖、历史决策的上下文等信息,往往隐没在命令行历史、临时的环境变量或不完整的文档中,使得维护、排障与知识传承变得异常困难,系统状态也变得脆弱而模糊。
我们认为,以大型语言模型(LLM)为代表的 AI 技术,为改变这一现状提供了新的工具。其关键在于明确划分 AI 与人类在运维工作中的不同角色:
- AI 应作为强大的信息处理器与聚合器:LLM 擅长从海量、多源的文本(代码、配置、日志、文档)中快速检索、提取和总结信息。这意味着,它可以高效地替人类完成信息搜集、整理与初步归因等工作,将运维人员从繁琐的“信息考古”中解放出来。
- 人类必须始终掌控系统的逻辑思考与设计权:必须清醒认识到,当前基于概率统计的 LLM 并不具备真正的系统逻辑能力。它无法理解架构设计的深层意图,无法在模糊地带做出负责任的权衡,也无法进行真正的创造性的抽象设计。对于“系统边界应如何划定”、“服务抽象是否合理”、“变更的长远影响是什么”这类需要逻辑推演、价值判断和创造性思维的核心问题,人类工程师的角色不可替代。
因此,我们所探索的范式是:人类负责定义系统逻辑与架构(What & Why),AI 辅助人类高效地处理实现与状态信息(How & Current Status),双方在清晰的边界内协同工作。
本仓库是这一理念的初步实践载体。我们尝试通过 GitOps 方法论,将集群的期望状态彻底代码化、版本化,致力于 “将 Git 打造为系统状态唯一可靠的单一事实来源”。这一实践旨在减少运行环境与声明式代码之间的信息差,从而为 AI 工具提供一个结构清晰、可追溯的分析基座,使其能够更可靠地辅助人类洞察系统状态、评估变更和定位问题。
在此框架下,AI 将被鼓励作为本仓库的主要日常操作者,在人类设定的逻辑框架与监督下,完成集群的运维工作。
那么运维团队要掌握什么呢?运维团队需要掌握系统的 Concept model。例如,运维 Tekton 这个 K8S 原生的 CI/CD 系统,运维只需要阅读 Concept model | Tekton 这一篇文章即可,然后直接指导 AI 来完成具体的配置、排障等工作。
README.md:AI 和人类工程师都应当阅读的总体介绍。AGENTS.md:参考 AGENTS.md。这里放置对 AI 的总体约束与指导原则,明确 AI 在本项目中的角色定位、能力边界与行为规范。- 内容:注意不要堆砌文档,比如服务的 Git 配置文件中显而易见的事实不应当在文档中再次陈述。文档仅记录那些不易从代码中直接获取、但对理解系统状态与设计决策至关重要的信息,如设计决策的背景与权衡、服务间复杂依赖关系的解释、历史变更的上下文等。
production/— 已经在生产环境中稳定部署的应用dev/— 用于开发/测试应用scripts/— 辅助脚本,如验证、部署等工具脚本`
我们的 K8S 应用部署方法经过了四个阶段的迭代:
- kubectl:手动管理资源,缺乏版本控制和自动化
- Helm:引入 Helm chart,提升了模板化和参数化能力,但难以管理模板以外的资源
- Kustomize:补足 Helm 的短板,实现所有 K8S 资源的声明式管理
- Argo CD:实现了 GitOps 模式,自动同步 Git 仓库与集群状态
- Argo CD 管理一个个 Application,它们可以是 Helm Chart、Kustomize 应用等
- Application 属于特定的 Project
- Application 可以由 ApplicationSet 自动生成
- 我们配置了 Application 和 ApplicationSet 的 Any Namespace 功能,以方便部署任意命名空间的应用
dev/ 和 production/ 目录各由一个 Argo CD ApplicationSet 管理,其核心机制是通过 Git 生成器将每个子目录映射为一个 Application,使用文件夹名作为名称和目标命名空间。具体配置见 production/argo-cd/apps.yaml,其中的关键规则如下:
generators:
- git:
directories:
- path: production/*
template:
metadata:
name: '{{path.basename}}'
namespace: '{{path.basename}}'
spec:
source:
path: '{{path}}'
destination:
namespace: '{{path.basename}}'每个应用文件夹(production/* 或 dev/*)遵循此模式:
namespace-name/
├── .gitignore
├── kustomization.yaml # 主 Kustomize 配置
├── values/ # Helm chart 值覆盖
│ ├── chart1.yaml
│ └── chart2.yaml
├── resources/ # 自定义 Kubernetes 资源
│ ├── namespace.yaml
│ ├── configmaps.yaml
│ └── *-sealedsecret.yaml # 加密密钥
└── charts/ # 本地 Helm charts(如果需要)
└── chart-name/
Kustomize 通过 HelmChartInflationGenerator 管理 Helm Chart,但有不少缺点,我们采取了相应措施:
-
缺点:Kustomize 只会 Pull 一次 Chart 到
charts/(默认的chartHome目录),然后反复使用该本地副本进行渲染。未指定version时目录名为name,指定version时目录名为name-version/name。措施:
-
通过
version字段明确指定 Chart 的版本,否则本地渲染和 Argo CD 渲染时的版本可能不同。 -
.gitignore排除 Kustomize 自动拉取的 Helm Chart,避免将其纳入版本控制。例外是一些自定义的 Helm Chart 可能需要被版本控制,举例:charts/* !charts/freeipa
-
-
缺点:Kustomize 不会预先运行
helm dependency build,导致如果 Chart 有依赖关系时渲染失败。见 Allow building helm dependencies when dealing with local charts · Issue #5851 · kubernetes-sigs/kustomize。措施:
- Argo CD 需要使用 Config Management Plugins - Argo CD - Declarative GitOps CD for Kubernetes,相关配置见
production/argo-cd/plugin.yaml。参考 You may need to runhelm dependency buildto fetch missing dependencies: · Issue #11564 · argoproj/argo-cd。
- Argo CD 需要使用 Config Management Plugins - Argo CD - Declarative GitOps CD for Kubernetes,相关配置见
-
缺点:不支持 overlays 方式覆盖 Helm Chart 的 values ,见 How to properly override helmChart values using overlays?
我们暂时没有使用 Overlay 功能,不考虑这个问题。
起初我们仅在 Value 文件中放置需要覆盖的值,但遇到了下列问题:
- 默认值变更:Helm Chart 默认值会随着版本更新而变化,仅覆盖部分值难以发现和适配这些变更。
- 比对困难:常常需要拿着 Chart 的默认值与覆盖值进行对比,心智负担较重。
- AI 幻觉:如果不提供完整的默认值,AI 可能会编造配置导致错误。
为了解决上述问题,values/<name>-<version>.yaml 均复制自相应版本 Helm Chart 的默认值 charts/<name>-<version>/<name>/values.yaml,修改后可使用 dyff 与默认值清晰比对。
命名规范:values 文件必须命名为 values/<chart-name>-<version>.yaml 格式,以明确对应的 Chart 版本。
pre-commit 将对本节前述内容进行检查,步骤如下:
-
检查
kustomization.yaml中helmCharts字段:# repo 和 version 要么同时存在,要么都不存在(本地 Chart) repo: version: # 必须 name: releaseName: namespace: # 与目录名相同 includeCRDs: true valuesFile: values/<name>-<version>.yaml
-
检查 Helm Chart 是否有新版本,若有则提示更新。
-
本地构建 Kustomize 确保能成功渲染。
本节记录 production/ 目录下部署的服务及其配置要点。
| 项目主页 | 社区 |
|---|---|
| refector | 未知 |
| kubelet-csr-approver | 公司:PostFinance |
| FreeIPA | 公司:RedHat |
| buildkit | 公司:Docker |
| GitLab Runner | 公司:GitLab |
| Ingress Nginx | Kubernetes SIG Network(Deprecated) |
| metrics-server | Kubernetes SIG Instrumentation |
| Argo CD | Linux Foundation - CNCF |
| Jenkins | Linux Foundation - CD Foundation |
| Tekton | Linux Foundation - CD Foundation |
| Metal3 | Linux Foundation - CNCF |
| OpenEBS | Linux Foundation |
| Rook | Linux Foundation - CNCF |
| Harbor | Linux Foundation - CNCF |
| Dragonfly | Linux Foundation - CNCF |
| Cilium | Linux Foundation - CNCF |
| Envoy Gateway | Linux Foundation - CNCF |
| cert-manager | Linux Foundation - CNCF |
| Metallb | Linux Foundation - CNCF |
| ExternalDNS | Kubernetes SIG Network |
-
获取 Helm Chart 及其版本,将
values.yaml复制到values/<name>-<version>.yaml,并根据需要修改覆盖值。helm search repo ... helm show values ...
-
放置
.gitignore,排除 Kustomize 自动拉取的 Helm Chart。 -
为服务配置外部访问:
- 使用 Chart 内置的 Gateway API 或 Ingress。如果 Chart 不支持,则自行创建 HTTPRoute 资源。
- 域名:
*.clusters.zjusct.io、*.s.zjusct.io。如果应用支持多 Host 则前述域名均应当配置,否则仅配置第一个。
Argo CD 作为 GitOps 的核心组件,负责将 Git 仓库中的声明式配置自动同步到 K8S 集群中。
Argo CD 在等待上一轮同步成功完成前不会执行新的同步,因此如果某个应用的同步失败了,后续的变更将无法部署到集群中。此时一般强制停止当前同步,然后 Argo CD 会触发新的同步,应用新的变更。
作为 CNI 插件,并提供 LoadBalancer 功能。
-
地址段
172.28.0.0/16,通过 BGP 将路由信息通告到集群主路由。 -
LoadBalancer IP 不会响应 ICMP,因此无法通过 ping 命令测试连通性。
-
Pod 内无法访问 LoadBalancer IP。两种解决办法:
-
K8S 内应当通过 Service IP/DNS 访问相应服务,但内部往往没有 TLS(TLS 配置在 Gateway/Ingress 上),不适用于需要 TLS 的服务。
-
使用 DNS Split Horizon 方法,通过 CoreDNS rewrite 将解析结果指向 Service IP,例:
- name: rewrite parameters: stop configBlock: |- name exact harbor.clusters.zjusct.io envoy-gateway.envoy-gateway.svc.cluster.local answer auto
-
集群搭建 Harbor 用于内网镜像服务,域名 harbor.clusters.zjusct.io。配置了知名 Registry 的 Pull Through Cache,将其添加为前缀即可。例如:
ubuntu->harbor.clusters.zjusct.io/hub.docker.com/library/ubuntuquay.io/minio/minio->harbor.clusters.zjusct.io/quay.io/minio/minio
K8S 上部署的服务均应使用 Harbor 作为镜像前缀。kustomization.yaml 中使用 image-prefix.yaml 配置集群内镜像服务的前缀。
transformers:
- ../../image-prefix.yaml对于 Docker Hub 上的短镜像名,需要先通过 images 字段将其转换为完整镜像名,例如:
images:
- name: ubuntu
newName: docker.io/library/ubuntu提供 IngressClasses nginx,虽然使用广泛但已进入维护状态,建议使用更新的 Gateway API。
提供 Gateway envoy-gateway,已配置下列 Listener
- 80:HTTP
- 443:HTTPS,已配置 TLS 泛域名证书
- 444:TLS Passthrough,适用于需要直接暴露 TLS 服务的应用
P2P 文件分发。containerd 已启用集成,节点间 K8S 镜像将通过 P2P 方式分发。
已配置 ACME 从 Let's Encrypt 获取 TLS 证书,用于 *.clusters.zjusct.io 域名。
其他用途(如内部服务)应当自行创建 Issuer 配置自签名证书。
FreeIPA 作为集群域控,提供 LDAP、DNS、Automount 等服务。ExternalDNS 自动将集群内 service、ingress 和 Gateway 相关的 DNS 记录同步到 FreeIPA 的 DNS 中。
seald secret
裸金属节点管理。
TODO:命名空间迁移。目前 metal3 占据独立的 3 个命名空间,与仓库中其他应用不一致。
提供本地存储 openebs-hostpath,适用于数据库等自身具有 Replica 功能、对读写性能有较高要求的应用。
用于在命名空间间同步资源,参考 Syncing Secrets Across Namespaces - cert-manager Documentation。
提供分布式存储:
ceph-block:适用于需要高可用和弹性扩展的应用ceph-filesystem:适用于需要共享访问的应用