GitOps 工作流
这个仓库是整个集群的唯一事实来源(source of truth)。ArgoCD 持续监视 yldm-tech/k8s-config 的 main 分支,把仓库目录里的 YAML 变成集群里运行的 Application,再由 Application 把各自的 manifest 同步进集群。合并到 main 几分钟后改动就会被自动同步,没有手动 kubectl apply 这一步。
automated: {prune: true, selfHeal: true},一个被合并的错误会自动生效。所以合并前一定要先在本地跑过 manifest 校验。集群整体分层见 集群架构。两层编排概览
ArgoCD 用两层结构把仓库变成运行的应用:第一层是 App-of-apps 根应用,负责自动发现 bootstrap/applications/ 下所有的 Application / ApplicationSet;第二层是其中一个特殊的 微服务 ApplicationSet(yldm-services),它用一个静态列表批量生成所有业务微服务的 Application。基础设施、数据库、监控、网络策略这类单例由第一层直接覆盖;业务微服务则交给第二层统一生成。
- Name
- ① App-of-apps 根应用
- Description
bootstrap/applications/root-app.yaml,用directory.recurse: true递归扫描bootstrap/applications/目录(排除自身),任何放进去的 Application / ApplicationSet YAML 都会被自动发现,无需手动注册。
- Name
- ② 微服务 ApplicationSet
- Description
bootstrap/applications/orchestration/production-services.yaml,ApplicationSet 名为yldm-services,用 List generator +goTemplate由静态列表批量生成业务服务的 Application。
App-of-apps 根应用
根应用 root-app(namespace argocd,project default)的 source 指向仓库 bootstrap/applications 路径,开启 directory.recurse: true 并 exclude: 'root-app.yaml'(避免自引用)。它本身就是一个 Application,作用是把 bootstrap/applications/ 目录下的每一份 Application / ApplicationSet 清单都同步进集群。
这意味着新增一个 ArgoCD Application 或 ApplicationSet 时,只要把 YAML 放进 bootstrap/applications/ 下任意位置,根应用就会在下次 reconcile 时自动发现并接管 —— 不需要在任何地方手工登记。这条路径覆盖的是各类单例:infrastructure、databases、monitoring、network policies,以及 cluster/ 下的集群级配置。
# bootstrap/applications/root-app.yaml (节选)
spec:
source:
repoURL: git@github.com:yldm-tech/k8s-config.git
targetRevision: main
path: bootstrap/applications
directory:
recurse: true
exclude: 'root-app.yaml'
syncPolicy:
automated:
prune: true
selfHeal: true
微服务 ApplicationSet
业务微服务不是一个个手写 Application,而是由 ApplicationSet yldm-services 统一生成。它用 List generator 配合 goTemplate: true(并设 goTemplateOptions: ["missingkey=error"]),列表里每个元素是一组字段:service / serviceType / namespace / replicas(还有 category,少数元素带 sourceRepo 覆盖)。
template 把每个列表元素渲染成一个名为 <serviceType>-<service> 的 Application(例如 platform-fluxa、app-aidict、game-dnf-server),source 指向仓库的 applications/<serviceType>/<service> 路径,destination namespace 取该元素的 namespace,project 取 serviceType。
applications/app/ 下新建一个目录不会自动上线,必须同时往这个列表里加一个元素。反过来,注释掉某个元素 = 下线该服务 —— ApplicationSet 开了 syncPolicy.applicationsSync: sync,移除列表元素时控制器会顺带删掉对应的 Application,而不是留下一个孤儿。所以崩溃或闲置的服务是在列表里被注释掉(manifest 仍保留在 applications/<category>/ 下待恢复),而不是删除目录。每个生成的 Application 同样开 automated: {prune, selfHeal}(并 allowEmpty: false),带 PrunePropagationPolicy=foreground / PruneLast=true 等 syncOptions 和重试退避,且 ignoreDifferences 忽略 Deployment 的 /spec/replicas(让 HPA 调整副本数时不被判为 drift)。游戏服务器一类的具体部署可参见 游戏服务。
# production-services.yaml template (节选)
template:
metadata:
name: '{{.serviceType}}-{{.service}}'
spec:
project: '{{.serviceType}}'
source:
path: 'applications/{{.serviceType}}/{{.service}}'
destination:
namespace: '{{.namespace}}'
AppProject 隔离
bootstrap/projects/*.yaml 定义了 6 个 AppProject,用来限定每个 Application 能创建哪些资源、落到哪个 namespace。ApplicationSet 生成的业务 Application 的 project 字段就取自列表元素的 serviceType,正好对应到这里的 app / platform / game。
| AppProject | 用途 | 资源范围 |
|---|---|---|
app | YLDM Application Services | namespace 限定 app |
platform | YLDM Platform Services | namespace 限定 platform |
game | YLDM Game Services | namespace 限定 game |
infrastructure | 基础设施组件(Ingress、存储、证书管理等) | 允许集群级资源(显式 whitelist) |
ci-cd | CI/CD 系统(Tekton Pipelines、Triggers 等) | 允许集群级资源 |
monitoring | 监控和日志系统(Prometheus、Grafana、Loki 等) | 允许集群级资源 |
app / platform / game 是 namespace-scoped 的(clusterResourceWhitelist 不开放或受限,destinations 锁到单一 namespace);infrastructure / ci-cd / monitoring 则通过显式的 clusterResourceWhitelist 放行 ClusterRole、CRD、Webhook、StorageClass、ClusterIssuer 等集群级资源。
自动同步与镜像回写
两层结构下的 Application 普遍开启 automated.prune 和 automated.selfHeal:prune 会删掉已从 git 移除的资源,selfHeal 会把集群里被手动改动的资源拉回 git 声明的状态。所以改集群的正确方式是改仓库再合并,手动 kubectl edit 会被 selfHeal 覆盖回去。
镜像 tag 不靠手工维护,而是由 argocd-image-updater 反向回写。每个应用在 applications/infrastructure/argocd-image-updater/imageupdaters/<app>.yaml 有一份 ImageUpdater CR,采用 semver 策略并用严格正则 ^[0-9]+\.[0-9]+\.[0-9]+$ 过滤 tag(跳过 latest / sha / 任意 tag)。检测到新版本时,它通过 SSH 把新 tag 写回该应用 kustomization 的 images: 块,提交到 main(就是仓库里那些 build: automatic update of … 的提交),随后 ArgoCD 再把新镜像同步进集群。
renovate.json 里带 dependencyDashboardApproval 门控;接版本时要在同一个 PR 里一并移植上游 manifest 改动,不要单独合并 tag。