文件
k3s/flux
T

Flux GitOps

目录结构

flux/
├── clusters/
│   ├── base/                            # 基础集群编排,仅部署 infrastructure
│   │   ├── kustomization.yaml           # infrastructure 资源列表
│   │   ├── sources.yaml                 # infrastructure HelmRepository 源
│   │   ├── kube-system.yaml             # CoreDNS / NodeLocalDNS
│   │   ├── infra-devops.yaml            # cert-manager / reflector / velero
│   │   ├── infra-data.yaml              # CNPG / Valkey
│   │   ├── infra-monitor.yaml           # Loki / Prometheus (+ post: Promtail)
│   │   ├── infra-net.yaml               # Nginx / CrowdSec / Tailscale
│   │   └── infra-gitops.yaml            # Gitea (+ post: Gitea Actions / Flux Web)
│   └── dev-cm/                          # dev-cm 集群 overlay,额外部署 apps
│       ├── kustomization.yaml           # 引入 base,并追加 apps / app 依赖层
│       ├── apps-sources.yaml            # app HelmRepository 源
│       ├── apps-secrets.yaml            # apps namespace 与 app 专属 Secret
│       ├── apps.yaml                    # Halo / RustDesk / Penpot / Fillcode / SinceAI
│       └── apps-post.yaml               # CDN Ingress(依赖 apps
├── infrastructure/
│   ├── sources/                         # 所有 HelmRepository 定义
│   ├── kube-system/                     # CoreDNS 自定义 + NodeLocalDNS
│   ├── infra-devops/                    # cert-manager, webhook-dnspod, reflector, velero
│   │   └── post/                        # ClusterIssuer + cert-manager ServiceMonitor values
│   ├── infra-data/                      # CNPG operator, Barman, Valkey
│   │   ├── post-1/                      # PG Cluster / ObjectStore / databases / LB
│   │   └── post-2/                      # Reflector secret annotations
│   ├── infra-net/                       # ingress-nginx, CrowdSec, Tailscale DERP, 证书
│   ├── infra-monitor/                   # Loki, Prometheus+Grafana
│   │   └── post/                        # Promtail(依赖 infra-net,打破循环)
│   └── infra-gitops/                    # Gitea
│       └── post/                        # Gitea Actions + flux-operator WebOIDC/Ingress
└── apps/
    ├── sources/                         # app HelmRepository 定义
    ├── secrets/                         # apps namespace 与 app 专属 Secret
    ├── post/                            # CDN Ingress(依赖 apps,且引用部分 infra 服务)
    ├── helmrelease-halo.yaml            # Halo
    ├── helmrelease-rustdesk.yaml        # RustDesk
    ├── helmrelease-penpot.yaml          # Penpot
    └── ...                              # app 证书与 Ingress

前置准备

需要提前生成git访问凭证

ssh-keygen -t ed25519 -C "flux" -f ./flux-git-auth -N ""

ssh-keyscan github.com > ./known_hosts

kubectl -n infra-gitops create secret generic flux-git-auth \
 --from-file=identity=./flux-git-auth \
 --from-file=identity.pub=./flux-git-auth.pub \
 --from-file=known_hosts=./known_hosts

然后将 flux-git-auth.pub 文件内容添加到远端仓库中

应用flux实例 后续将自动开启部署流程

kubectl apply -f flux/flux-instance.yaml

部署顺序

sources → secrets → kube-system → infra-devops → infra-data → infra-data-post-1 → infra-data-post-2
       → infra-monitor → infra-net → infra-devops-post
       → infra-monitor-post (Promtail)
       → infra-gitops
       → apps-sources → apps-secrets → apps
       → apps-post (CDN Ingress)
       → infra-gitops-post (suspend=true,需手工凭据)

clusters/base 只包含到 infra-gitops-post 为止的 infrastructure 部署;apps-sourcesapps-secretsappsapps-post 只在 clusters/dev-cm 中声明。Kustomization 间通过 dependsOn + wait: true 串行等待,避免顺序错乱。

部署后手工步骤(infra-gitops-post

infra-gitops-post 在 base 层硬编码 spec.suspend: true 默认暂停,因为它依赖两类只能在 Gitea 启动后获取的凭据:

  1. Flux Operator Web 的 OIDC 客户端
  2. Gitea Actions Runner Token

凭据就绪、flux-env Secret 重新注入后,可以先用 flux resume kustomization infra-gitops-post -n infra-gitops 手工放行。

注意:手工 resume 只会修改集群里的 live 对象,不会改 Git 中的期望状态。 由于 base 层仍然声明了 spec.suspend: true,当上层 Kustomization 重新协调(如 30 分钟周期、Git 变更、手工 reconcile)时,它会再次把 infra-gitops-post 改回暂停。

如果希望恢复后保持开启,需要把 Git 中的期望状态也改掉,例如在环境 overlay(如 clusters/dev-cm/infra-gitops-post.yaml)中覆盖:

spec:
  suspend: false

步骤:

  1. 浏览器访问 https://git.dev.cm,首个注册账号自动成为 admin。

  2. 创建 OAuth2 应用

    • Site Administration → Integrations → Applications → Create OAuth2 Application
    • Redirect URI: https://cd.dev.cm/oauth2/callback
    • 记录 Client ID 与 Client Secret。
  3. 生成 Runner Token

    • Site Administration → Actions → Runners → Create new Runner → 复制 registration token。
  4. 更新 .env

    FLUX_WEB_OIDC_CLIENT_ID=<step 2 client id>
    FLUX_WEB_OIDC_CLIENT_SECRET=<step 2 client secret>
    GITEA_ACTIONS_TOKEN=<step 3 token>
    
  5. 重新注入 flux-env Secret 并协调:

    kubectl -n infra-gitops create secret generic flux-env \
      --from-env-file=.env \
      --dry-run=client -o yaml | kubectl apply -f -
    
    flux reconcile kustomization secrets -n infra-gitops
    flux resume kustomization infra-gitops-post -n infra-gitops
    flux reconcile kustomization infra-gitops-post -n infra-gitops --with-source
    
  6. 验证:

    kubectl -n infra-gitops get helmrelease gitea-actions
    kubectl -n infra-gitops get deploy flux-operator -o yaml | grep -A2 args   # 看到 --web-*
    curl -I https://cd.dev.cm                                                    # 走 Gitea OIDC
    

为何拆出 *-post 层?

  • infra-devops-postcert-manager 首次安装时不能依赖 ServiceMonitor CRD;post 层只在监控栈就绪后下发 ClusterIssuer 与可选 values ConfigMap,避免多个 Kustomization 共同管理同一个 HelmRelease。
  • infra-monitor-post (Promtail)Promtail 依赖至少一个带 devcm-log-collecting/enabled 标签的 Podingress-nginx);而 infra-net 又依赖 infra-monitor 的 CRD。Promtail 放到 post 层并 dependsOn: infra-net,打破循环。
  • apps-post (CDN Ingress)CDN Ingress 会引用 appsinfra-gitopsinfra-monitor 中的服务,因此不属于 base;只在 dev-cm 中声明,并依赖对应服务层。
  • infra-gitops-post (Gitea Actions + Flux Web):凭据必须在 Gitea 启动后手工创建;放在 post 层并默认 suspend,避免阻塞 bootstrap。