- 云原生
- DevOps
- 容器编排
- 运维
【免费下载链接】flux
Successor: https://github.com/fluxcd/flux2
本文面向 Flux v1 用户:当你的 GitOps 仓库托管在自建 Git 主机(如私有化部署的 GitLab、Bitbucket Server,或任意内部 Git 服务器)上时,默认镜像中内置的
known_hosts并不包含该主机的指纹,fluxd 守护进程将因 SSH 主机密钥校验失败而无法克隆仓库。本文以仓库文档 docs/guides/use-private-git-host.md 为主线,结合 fluxd 源码与 deploy/flux-deployment.yaml 部署清单,完整讲解"容器内排障验证 → 固化 SSH 主机密钥 → 挂载进 Daemon → 重启生效"的全流程,读完即可独立完成自有 Git 主机的接入配置。
⚠️ 版本前提:本文对应 Flux v1(已停止维护的 legacy 分支),仓库镜像 tag 示例为
docker.io/fluxcd/flux:1.25.4(见 deploy/flux-deployment.yaml)。若你正在新集群上启动,应优先评估并迁移至 Flux v2(fluxcd/flux2),本文所有配置仅适用于 Flux v1 部署。
一、问题根源:为什么私有 Git 主机连不上
Flux 的容器镜像在构建时只把少数几个公开 Git 主机(如 github.com、gitlab.com、bitbucket.org、Azure DevOps 等)的指纹固化进系统级known_hosts,参见 docker/Dockerfile.flux 中的ADD ./known_hosts.sh ... && sh /home/flux/known_hosts.sh /etc/ssh/ssh_known_hosts,以及 docker/known_hosts.sh 脚本内硬编码的主机列表:
hosts="github.com gitlab.com bitbucket.org ssh.dev.azure.com vs-ssh.visualstudio.com" hosts_2022="source.developers.google.com"同时,镜像内的默认 SSH 配置(docker/ssh_config)强制开启严格校验:
Host * StrictHostKeyChecking yes IdentityFile /etc/fluxd/ssh/identity IdentityFile /var/fluxd/keygen/identity LogLevel error HostkeyAlgorithms +ssh-rsa PubkeyAcceptedAlgorithms +ssh-rsaStrictHostKeyChecking yes意味着:凡是不在known_hosts里的主机,SSH 一律拒绝连接。因此,当你把--git-url指向自建 Git 主机时,fluxd 的 git 镜像克隆操作(底层通过 pkg/git/operations.go 的git clone/git clone --mirror执行)会直接报Host key verification failed,仓库无法拉取,同步自然无法进行。
理解了这一点,解决方案就很清晰:把自有 Git 主机的主机公钥写进 fluxd 容器内的~/.ssh/known_hosts(即/root/.ssh/known_hosts),并通过 ConfigMap 挂载实现持久化。
二、第一步:在 fluxd 容器内验证并修复克隆
2.1 找到 fluxd Pod 并进入容器
先按 Deployment 标签name=flux找到守护进程 Pod:
$ kubectl get pods --all-namespaces -l name=flux NAMESPACE NAME READY STATUS RESTARTS AGE weave flux-85cdc6cdfc-n2tgf 1/1 Running 0 1h然后通过kubectl exec进入容器,并设置两个环境变量:GITHOST(Git 服务器主机名,如githost)与GITREPO(仓库访问 URL,如user@githost:path/to/repo):
$ kubectl exec -n weave flux-85cdc6cdfc-n2tgf -ti -- \ env GITHOST="$GITHOST" GITREPO="$GITREPO" PS1="container$ " /bin/sh提示:
-ti表示以交互 TTY 方式进入;env ... /bin/sh用于在进入 shell 前注入本次验证所需的变量。
2.2 直接克隆,观察预期失败
在容器内执行git clone,由于容器已知主机表中没有githost,应当看到类似下面的失败(这是预期行为,无需惊慌):
container$ git clone $GITREPO Cloning into <repository name>... No ECDSA host key is known for <GITHOST> and you have requested strict checking. Host key verification failed. fatal: Could not read from remote repository2.3 追加主机密钥后重新克隆
用ssh-keyscan抓取该主机当前的主机公钥,追加到~/.ssh/known_hosts,再重试:
container$ ssh-keyscan $GITHOST >> ~/.ssh/known_hosts container$ git clone $GITREPO Cloning into '...' ...前置检查:如果这次依然失败,先确认部署用的 SSH 私钥是否已正确就位(私钥以identity为数据键存放在--k8s-secret-name指定的 Secret 中,默认flux-git-deploy,详见 docs/guides/provide-own-ssh-key.md),并确保该密钥对仓库具备读写(尤其是能创建/更新 tag)权限。容器内也可用ssh -vv $GITHOST查看详细握手日志来定位问题。
原理印证:fluxd 每次同步前会通过 pkg/git/mirrors.go 维护的镜像仓库执行
clone --mirror/Refresh,pkg/sync/git.go 还会通过MoveTagAndPush在远端仓库打flux-sync标签记录同步进度。整个链路都要经过 SSH 握手,主机密钥校验失败会在第一步就阻断。
三、第二步:把 known_hosts 固化为 ConfigMap
容器内临时追加的密钥在 Pod 重建后会丢失,必须持久化。在刚才那个容器 shell 内,把~/.ssh/known_hosts打包成 ConfigMap。为了确保 ConfigMap 创建在 Flux 所在命名空间,直接读取挂载的 ServiceAccount namespace:
container$ kubectl create configmap flux-ssh-config --from-file=$HOME/.ssh/known_hosts -n $(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) configmap "flux-ssh-config" created说明:
/var/run/secrets/kubernetes.io/serviceaccount/namespace是 K8s 自动注入的"当前命名空间"文件;显式指定-n可避免默认 namespace 与 Flux 部署命名空间不一致导致的挂载失效。命令中的$HOME在容器内为/root,因此写入的键名是known_hosts,与后续挂载路径配合即可。
3.1 模板方式:手工编写 ConfigMap
如果不想依赖容器内操作,也可以直接提交一份完整的 ConfigMap 模板。下面的示例同时收录了 GitHub 与私有 GitLab 的条目,格式为<host> <keytype> <base64 公钥>:
apiVersion: v1 data: known_hosts: | # github 192.30.253.112 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ== # github 192.30.253.113 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ== # private gitlab gitlab.________ ssh-rsa AAAAB3N... kind: ConfigMap metadata: name: flux-ssh-config namespace: <OPTIONAL NAMESPACE (if not default)>要点:
data.known_hosts键名必须固定为known_hosts,后续挂载时它将成为/root/.ssh/known_hosts文件;- 每行一条
主机名 密钥类型 公钥,#开头为注释;ssh-keyscan输出即可直接使用; namespace务必与 Flux Deployment 所在命名空间一致;- 私钥指纹属于敏感信息,建议通过内部受控渠道获取而非直接复制示例中的占位公钥(示例中的
AAAAB3N...是截断占位符)。
四、第三步:挂载 ConfigMap 并重启 Daemon
4.1 在部署清单中取消注释两处块
官方示例部署清单 deploy/flux-deployment.yaml 中,与known_hosts相关的部分已预置、默认注释,只需取消注释并在需要时调整:
① 卷声明(volumes 段),挂载名为flux-ssh-config的 ConfigMap:
- name: ssh-config configMap: name: flux-ssh-config② 容器内挂载点(volumeMounts 段),把该卷挂到/root/.ssh:
- name: ssh-config mountPath: /root/.ssh这两块对应仓库清单中的注释示例(deploy/flux-deployment.yaml 中# - name: ssh-config的 volume 与# - name: ssh-config的 volumeMount)。取消注释后重新kubectl apply -f deploy/flux-deployment.yaml,滚动重建后 fluxd 即可在每次启动时使用持久化的known_hosts。
关联阅读:Helm Chart 方式下,chart/flux/templates/ssh.yaml 会在设置
ssh.known_hosts时自动生成<release>-ssh-configConfigMap,并在 chart/flux/templates/deployment.yaml 中以defaultMode: 0600挂载到/root/.ssh(volumeMount 同时声明readOnly: true);同时 deployment 注解里还加了checksum/ssh,使 ConfigMap 内容变化时能触发滚动更新。对应 values 配置见 chart/flux/values.yaml 的ssh.known_hosts字段。
4.2 确认 ServiceAccount 名称
文档末尾特别提醒:若你的部署清单中有被注释的serviceAccountName: flux行,需要取消注释并确保它指向实际可用的 ServiceAccount,再应用清单。以 deploy/flux-deployment.yaml 为例,spec.template.spec.serviceAccountName: flux对应 deploy/flux-account.yaml 中定义的fluxServiceAccount(含 ClusterRole/ClusterRoleBinding,授予集群级读写权限)。这是因为 fluxd 需要足够的 RBAC 权限来完成清单同步、Secret/ConfigMap 读写等操作;若使用 Helm Chart,则通过--set serviceAccount.create=true或已有账号来满足。
4.3 重启与验证
$ kubectl rollout restart deployment/flux -n <namespace> # 或直接重新 apply 清单 $ kubectl logs -n <namespace> deploy/flux -f # 观察同步日志 $ kubectl get pods -l name=flux --all-namespaces # 确认 Pod Running重新拉起后,fluxd 的--git-url(例如git@yourhost:team/repo.git)即可通过 SSH 握手完成克隆与持续同步;你也可以回到容器内再次执行git clone确认无Host key verification failed报错。
五、源码级补充:fluxd 的 SSH 与 git 工作方式
5.1 SSH 密钥由 Secret 承载,密钥环自动维护
fluxd 通过--k8s-secret-name(默认flux-git-deploy)指定的 Kubernetes Secret 承载 SSH 私钥,并依靠 pkg/cluster/kubernetes/sshkeyring.go 中的SSHKeyRingConfig管理密钥生命周期:
- 若 Secret 中无
identity数据键,会在--ssh-keygen-dir(如/var/fluxd/keygen,建议 tmpfs)生成新密钥并回写 Secret; - 私钥文件必须为
0400权限,否则 ssh 拒绝使用(代码中privateKeyFileMode = 0400); - 密钥环接口定义见 pkg/ssh/keyring.go。
相关启动参数可在 cmd/fluxd/main.go 中确认:--k8s-secret-volume-mount-path默认/etc/fluxd/ssh,--k8s-secret-data-key默认identity。镜像内 docker/ssh_config 恰好让 ssh 依次从/etc/fluxd/ssh/identity与/var/fluxd/keygen/identity读取私钥。
5.2 同步链路:镜像 → 刷新 → 打标签
- pkg/git/mirrors.go 以
clone --mirror维护远端仓库镜像,并通过 channel 通知变化; - pkg/git/operations.go 提供
clone/mirror/checkout/MoveTagAndPush等底层 git 操作; - pkg/sync/git.go 的
GitTagSyncProvider通过移动flux-sync标签记录同步进度(对应--git-label=flux-sync)。
这些操作全部走容器内 ssh 客户端,因此"主机密钥校验通过"是 Flux 正常工作的硬前提——这也正是本文整套配置的价值所在。
六、常见排障清单
| 现象 | 原因 | 处理 |
|---|---|---|
Host key verification failed | 私有主机指纹不在known_hosts | 按本文第二、三步追加并固化主机公钥 |
| 加了指纹仍克隆失败 | SSH 私钥缺失/无权限/密钥格式不被接受 | 检查flux-git-deploySecret 的identity;用ssh -vv排查握手;确保密钥对仓库有 tag 读写权限 |
| Pod 重启后失效 | 只在容器内临时改写了known_hosts | 改为 ConfigMap 挂载(第三步) |
| 挂载后无效果 | ConfigMap 命名空间与 Deployment 不一致,或卷/挂载点未成对启用 | 核对-n与mountPath: /root/.ssh,确认两处注释块均已取消 |
| Chart 部署未生效 | 未设置ssh.known_hosts值 | 在 values 中填充ssh.known_hosts(多行主机公钥),Chart 会自动生成并挂载 ConfigMap |
补充安全建议:
StrictHostKeyChecking yes本身是防中间人攻击的正确姿势,本文方案并未放宽该校验,而是把可信指纹显式注入,属于推荐做法;请务必通过可信渠道(如主机管理员、HTTPS 管理界面公布的指纹)核对ssh-keyscan结果后再固化,不要盲目信任扫描输出。
七、相关文档与资源
- docs/guides/use-private-git-host.md:本文所依据的官方指南原文
- docs/guides/provide-own-ssh-key.md:自行提供 SSH 私钥的完整说明(含权限要求)
- deploy/flux-deployment.yaml:官方部署清单(含
ssh-config注释示例) - deploy/flux-account.yaml:flux ServiceAccount 与 RBAC 定义
- chart/flux/templates/ssh.yaml 与 chart/flux/templates/deployment.yaml:Helm Chart 下的自动 ConfigMap 生成与挂载实现
- docker/Dockerfile.flux、docker/known_hosts.sh、docker/ssh_config:镜像内默认已知主机与 SSH 配置的构建来源
- cmd/fluxd/main.go:fluxd 全部启动参数定义(
--git-url、--ssh-keygen-dir、--k8s-secret-name等)
- 云原生
- DevOps
- 容器编排
- 运维
【免费下载链接】flux
Successor: https://github.com/fluxcd/flux2
相关推荐
Magicodes.IE社区贡献指南:从问题反馈到代码提交的全流程
Magicodes.IE社区贡献指南:从问题反馈到代码提交的全流程 Magicodes.IE是一款功能强大的导入导出通用库,支持Dto导入导出、模板导出、花式导
后端Flux v1 API完整指南:掌握所有接口调用的终极教程
Flux v1 API完整指南:掌握所有接口调用的终极教程 Flux是一个基于GitOps理念的Kubernetes持续交付工具,通过自动化同步Git仓库中的配
云原生DevOps容器编排运维OmX插件开发指南:从零开始创建你的第一个Hook
OmX插件开发指南:从零开始创建你的第一个Hook OmX(Oh My CodeX)是一个强大的CodeX CLI工作流增强工具,它提供了丰富的插件扩展系统,让
人工智能AI AgentAgent 编排Agent 工作流CLI开发工具AI 技能
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考